Ogledna aktivacija php-a. Kako stvoriti vlastitu stranicu za prijavu u WordPress Multisite

Danas ćemo pogledati iskorištavanje kritične jednodnevne ranjivosti u popularnom Joomla CMS-u, koja je eksplodirala na Internetu krajem listopada. O ranjivostima ćemo govoriti s brojevima CVE-2016-8869, CVE-2016-8870 I CVE-2016-9081. Sva tri dolaze iz istog dijela koda koji je čamio u utrobi okvira dugih pet godina, čekajući da se oslobodi i donese kaos, hakirana mjesta i suze nevinih korisnika ove Joomle. Samo najhrabriji i najhrabriji programeri, čije su oči crvene od svjetla monitora, a tipkovnice pune mrvica kruha, uspjeli su izazvati bijesne zle duhove i položiti svoje glave na oltar popravaka.

UPOZORENJE

Sve informacije su date samo u informativne svrhe. Ni urednici ni autor nisu odgovorni za bilo kakvu moguću štetu prouzročenu materijalima ovog članka.

Kako je sve počelo

Dana 6. listopada 2016., Demis Palma je napravio topic na Stack Exchangeu, u kojem je pitao: zašto, zapravo, u Joomla verziji 3.6 postoje dvije metode za registraciju korisnika s istim imenom register() ? Prvi je u UsersControllerRegistration kontroleru, a drugi je u UsersControllerUser. Damis je htio znati koristi li se negdje metoda UsersControllerUser::register() ili je to samo evolucijski anakronizam preostao iz stare logike. Bio je zabrinut zbog činjenice da čak i ako ovu metodu ne koristi nijedan pogled, ona se i dalje može pozvati generiranim zahtjevom. Na što sam dobio odgovor od programera pod nadimkom itoctopus, koji je potvrdio da problem stvarno postoji. I poslao izvješće programerima Joomle.

Daljnji događaji razvijali su se najbrže. Dana 18. listopada Joomla programeri prihvaćaju izvješće Damisa, koji je do tada izradio PoC koji omogućuje registraciju korisnika. Objavio je bilješku na svojoj web stranici, gdje je općenito govorio o problemu koji je zatekao i svojim razmišljanjima o njemu. Istog dana izlazi nova verzija Joomle 3.6.3, koja još uvijek sadrži ranjivi kod.

Nakon toga, Davide Tampellini vrti bug u stanje registracije ne jednostavnog korisnika, već administratora. I već 21. listopada, novi slučaj stiže Joomla sigurnosnom timu. Već govori o eskalaciji privilegija. Istog dana na web stranici Joomla pojavljuje se obavijest da će u utorak, 25. listopada, izaći sljedeća verzija sa serijskim brojem 3.6.3, koja popravlja kritičnu ranjivost u jezgri sustava.

Dana 25. listopada Joomla Security Strike Team pronalazi najnoviji problem koji je stvorio dio koda koji je otkrio Damis. Zatim se commit od 21. listopada s neupadljivim nazivom Prepare 3.6.4 Stable Release gura u glavnu granu službenog repozitorija Joomla, čime se popravlja nesretna pogreška.

Nakon ovog izlaska, brojni zainteresirani pojedinci pridružuju se developerskoj kabali - počinju vrtjeti ranjivost i pripremati sploite.

Dana 27. listopada, istraživač Harry Roberts učitava gotovu eksploataciju u repozitorij Xiphos Research koja može učitati PHP datoteku na poslužitelj s ranjivim CMS-om.

pojedinosti

Pa, pretpovijest je gotova, prijeđimo na najzanimljivije - analizu ranjivosti. Kao eksperimentalnu verziju instalirao sam Joomlu 3.6.3, tako da će svi brojevi redaka biti relevantni za ovu verziju. I sve staze do datoteka koje vidite sljedeće bit će naznačene u odnosu na korijen instaliranog CMS-a.

Zahvaljujući otkriću Damis Palme, znamo da postoje dvije metode kojima se vrši registracija korisnika u sustavu. Prvi koristi CMS i nalazi se u datoteci /components/com_users/controllers/registration.php:108. Drugi (onaj koji trebamo pozvati) živi u /components/com_users/controllers/user.php:293 . Pogledajmo ga pobliže.

286: /** 287: * Metoda registracije korisnika. 288: * 289: * @return boolean 290: * 291: * @od 1.6 292: */ 293: public function register() 294: ( 295: JSession::checkToken("post") ili jexit(JText::_ ("JINVALID_TOKEN")); ... 300: // Dobivanje podataka obrasca. 301: $data = $this->input->post->get("user", array(), "array"); . .. 315: $return = $model->validate($form, $data); 316: 317: // Provjerite pogreške 318: if ($return === false) 319: ( ... 345: / / Završite registraciju.346: $return = $model->register($data);

Ovdje sam ostavio samo zanimljive retke. Puna verzija ranjive metode može se vidjeti u repozitoriju Joomla.

Razmotrimo što se događa tijekom normalne registracije korisnika: koji se podaci šalju i kako se obrađuju. Ako je registracija korisnika omogućena u postavkama, tada se obrazac nalazi na http://joomla.local/index.php/component/users/?view=registration.


Zahtjev za legitimnu registraciju korisnika izgleda kao na sljedećoj snimci zaslona.


Za rad s korisnicima odgovorna je komponenta com_users. Obratite pozornost na parametar zadatka u zahtjevu. Ima format $controller.$method. Pogledajmo strukturu datoteke.

Nazivi skripti u mapi kontrolori odgovaraju nazivima pozvanih kontrolera. Budući da naš zahtjev sada ima $controller = "registration" , datoteka će biti pozvana registracija.php i njegova metoda register().

Pažnja, pitanje je: kako prenijeti obradu registracije na ranjivo mjesto u kodu? Vjerojatno ste već pogodili. Imena ranjive i prave metode su ista (registar), tako da samo trebamo promijeniti ime pozvanog kontrolera. A gdje je ranjivi kontroler? Tako je, u dosjeu korisnik.php. Ispada $controller = "user" . Spajajući sve zajedno, dobivamo task = user.register . Sada se zahtjev za registraciju obrađuje metodom koja nam je potrebna.


Druga stvar koju trebamo učiniti je poslati podatke u ispravnom formatu. Ovdje je sve jednostavno. Legitimni register() od nas očekuje niz pod nazivom jform , u koji prosljeđujemo podatke za registraciju - ime, prijavu, lozinku, mail (pogledajte sliku zaslona sa zahtjevom).

  • /components/com_users/controllers/registration.php: 124: // Dobivanje korisničkih podataka. 125: $requestData = $this->input->post->get("jform", array(), "array");

Naše dijete prima ove podatke iz polja pod nazivom korisnik.

  • /components/com_users/controllers/user.php: 301: // Dobivanje podataka obrasca. 302: $data = $this->input->post->get("user", array(), "array");

Stoga mijenjamo nazive svih parametara u zahtjevu iz jfrom u user.

Naš treći korak je pronaći važeći CSRF token, jer bez njega neće biti registracije.

  • /components/com_users/controllers/user.php: 296: JSession::checkToken("post") ili jexit(JText::_("JINVALID_TOKEN"));

Izgleda kao MD5 hash, a možete ga uzeti, na primjer, iz obrasca za autorizaciju na stranici /index.php/component/users/?view=login .


Sada možete kreirati korisnike putem željene metode. Ako je sve uspjelo, onda čestitamo - upravo ste iskoristili ranjivost CVE-2016-8870"Nedostaje provjera dopuštenja za registraciju novih korisnika."

Evo kako to izgleda u "radnoj" metodi register() iz kontrolera UsersControllerRegistration:

  • /components/com_users/controllers/registration.php: 113: // Ako je registracija onemogućena - Preusmjerava na stranicu za prijavu. 114: if (JComponentHelper::getParams("com_users")->get("allowUserRegistration") == 0) 115: ( 116: $this->setRedirect(JRoute::_("index.php?option=com_users&view=) prijava", lažno)); 117: 118: vrati lažno; 119: )

I tako u ranjivima:

  • /components/com_users/controllers/user.php:

Da, nema šanse.

Da bismo razumjeli drugi, mnogo ozbiljniji problem, pošaljimo zahtjev koji smo formirali i vidimo kako se izvršava u različitim dijelovima koda. Ovdje je dio koji je odgovoran za provjeru valjanosti korisnički dostavljenih podataka u metodi radnika:

Nastavak dostupan samo članovima

Opcija 1. Pridružite se zajednici "site" kako biste pročitali sve materijale na stranici

Članstvo u zajednici tijekom navedenog razdoblja omogućit će vam pristup SVIM hakerskim materijalima, povećati vaš osobni kumulativni popust i omogućiti vam da skupite profesionalnu ocjenu Xakep Score!

Omogućuje korištenje jedne WordPress instalacije za više web stranica u isto vrijeme. U tom slučaju svaka stranica dobiva vlastite tablice u bazi podataka s jedinstvenim prefiksom.

Tablice s podacima registriranih korisnika zajedničke su za sve mrežne stranice. Ovo je definitivan plus i jednom registracijom možete dobiti pristup na nekoliko stranica. Štoviše, na svakoj stranici isti račun može imati različita prava. Na primjer, korisnik može biti urednik na jednom mjestu i administrator na drugom.

U tipičnoj instalaciji WordPressa, stranica za prijavu, prijavu i ponovno postavljanje lozinke prikazuje se u datoteci wp-login.php.

  • wp-login.php - autorizacija
  • wp-login.php?action=register - registracija
  • wp-login.php?action=lostpassword - ponovno postavljanje lozinke

U Multisite modu, jezgra WordPressa počinje se ponašati malo drugačije i kada kliknete na vezu wp-login.php?action=register, preusmjerit će se na wp-signup.php. Ovo je stranica za registraciju vaše mreže koja prema zadanim postavkama dolazi s WordPressom.

Osim registracije običnih korisničkih računa, na njemu možete kreirati i novu stranicu ako je superadministrator omogućio tu mogućnost u postavkama mreže (Administrator mreže → Postavke → Postavke mreže).

U većini tema stranica za registraciju ne izgleda baš dobro. Mnoge teme koriste CSS okvire kao što je Bootstrap i svoje specifične klase za stiliziranje različitih elemenata na stranici, tako da je teško napisati jedan HTML koji odgovara svima.

Ali nemojte očajavati ako stranica izgleda neuredno. Datoteka wp-signup.php je izvrsna na početku, kada nemate vremena raditi na svakom detalju stranice - možete se fokusirati na druge važnije stranice i sadržaj.

Kada budete spremni napraviti vlastitu stranicu za prijavu, wp-signup.php je dobra referenca i primjer koji će vam pomoći da razumijete niz značajki koje WordPress pruža za obradu i provjeru valjanosti unosa korisnika i stvaranje novih računa.

Glavna stranica mreže

Prema zadanim postavkama, WordPress otvara stranicu za prijavu (wp-signup.php) na glavnoj domeni (web stranici) weba. Međutim, možete izraditi stranice za registraciju za svako mjesto na mreži, čak i ako ima teme.

Razmotrit ćemo slučaj kada sve stranice u mreži koriste istu temu, ali svaka od njih ima stranicu za registraciju. Stranice se razlikuju po jeziku (engleski i ruski), tako da će stranica za registraciju biti prikazana na "materinjem" jeziku stranice. U slučaju da web-mjesta koriste različite teme, sve će ovisiti o tome koje su teme, odgovara li im isti izgled (odlična situacija koja vas može potaknuti da objedinite sve svoje teme) ili se isplati razvijati stranice pojedinačno.

funkcije.php alternativa

Redoslijed datoteka

MU dodaci mogu sadržavati bilo koji broj datoteka i strukturu koja vam se čini logičnom. Slijedim ovakvu hijerarhiju:

| mu dodaci | | load.php | | selena mreža | | | prijaviti se | | | | dodatak.php | | | ... | | | mlazni ruksak | | | | dodatak.php

U datoteci load.php povezani su prijevodi i svi potrebni "dodaci":

// Učitaj prijevode za MU dodatke load_muplugin_textdomain("selena_network", "/selena-network/languages/"); // Funkcionalnost stranice za registraciju zahtijeva WPMU_PLUGIN_DIR. "/selena-network/signup/plugin.php"; // Drugi dodatak // zahtijeva WPMU_PLUGIN_DIR ...

Mape dodataka pohranjene su unutar direktorija selena-network. Svaki ima svoj plugin.php, koji uključujemo u load.php. To daje fleksibilnost i mogućnost trenutnog onesposobljavanja i omogućavanja pojedinačnih komponenti na radnom projektu u slučaju nužde.

Stranica za registraciju

Nakon što smo shvatili gdje i kako ćemo napisati kod, možemo prijeći na izradu stranice za registraciju.

Kreirajmo stranicu s adresom example.org/signup/ kroz uobičajeno sučelje. Kao adresu možete koristiti bilo koji URL koji se čini prikladnim za vaš projekt.

Preusmjerite na potrebnu stranicu za registraciju

Kako bi WordPress saznao za našu novu stranicu za registraciju i preusmjerio na nju, kada kliknete na poveznicu “Prijavi se”, koristi se filter wp_signup_location. Može se pronaći unutar wp-login.php i odgovoran je za preusmjeravanje na wp-signup.php prema zadanim postavkama.

Case "register" : if (is_multisite()) ( wp_redirect(apply_filters("wp_signup_location", network_site_url("wp-signup.php"))); izlaz; // ...

Kao što se sjećate, prema zadanim postavkama stranica za registraciju otvara se na glavnoj mrežnoj domeni. Zato se ovdje koristi network_site_url().

Dodajmo naš rukovatelj filtru u mu-plugins/selena-network/signup/plugin.php, koji će dati adresu stranice za registraciju na trenutnoj stranici:

Funkcija selena_network_signup_page($url) ( return home_url("signup"); ) add_filter ("wp_signup_location", "selena_network_signup_page", 99);

selena_network je prefiks koji koristim u imenima svih funkcija unutar MU dodataka na svojoj stranici kako bih izbjegao kolizije, trebao bi se zamijeniti mojim vlastitim jedinstvenim prefiksom. Dodajte prioritet filtra 99 jer neki dodaci poput bbPress i BuddyPress mogu prebrisati ovu adresu svojom (MU dodaci se učitavaju prije normalnih dodataka, pogledajte gore).

Imajte na umu da se koristi home_url() koji, za razliku od network_site_url(), vraća adresu trenutne stranice, a ne glavne stranice na mreži.

wp-signup.php funkcionalnost

Datoteka wp-signup.php sadrži mnogo funkcija i koda. Da biste vidjeli veliku sliku, možete upotrijebiti preklapanje koda. U pravilu, na engleskom se to zove "code folding".

Na samom početku datoteke od redaka 1 do 80 (u verziji 4.1.1) vrše se različite provjere i prikazuje se “početak” stranice pomoću get_header() .

Zatim se deklarira mnogo metoda, a prije nego počnemo raditi s njima, vrijedno je razumjeti što svaka funkcija radi. Mnogi od njih često koriste druge funkcije s prefiksom wpmu_, a sve su navedene u datoteci wp-includes/ms-functions.php. Ovaj je odjeljak teško razumjeti bez da sami vidite kôd. Dolje je kratak opis glavnih funkcija u slučaju da imate poteškoća.

  • wpmu_signup_stylesheet() - Ispis dodatnog CSS-a na stranici za registraciju.
  • show_blog_form() - polja za registraciju stranice (adresa, naziv, vidljivost za tražilice).
  • validate_blog_form() - Provjerava valjanost unesene adrese i naslova web stranice pomoću wpmu_validate_blog_signup() .
  • show_user_form() - polja za registraciju korisnika (login i email adresa).
  • validate_user_form() - provjera valjanosti unesene prijave i adrese e-pošte. pošta s wpmu_validate_user_signup() .
  • signup_another_blog() - polja za registraciju novih stranica pomoću show_blog_form() za korisnike koji su već registrirani na stranici.
  • validate_another_blog_signup() - Provjerava adresu i naslov stranice s validate_blog_form() .
  • signup_user() je glavna funkcija za prikaz polja stranice za prijavu.
  • validate_user_signup() - Provjerava korisničko ime i adresu e-pošte. pošta s validate_user_form() .
  • signup_blog() - polja za unos adrese, naziva i vidljivosti stranice (drugi korak registracije) pomoću show_blog_form() .
  • validate_blog_signup() - potvrđuje prijavu, adresu e-pošte. mail, adresu i naziv stranice.

Na samom dnu datoteke wp-signup.php (od retka 646 u verziji 4.1.1) nalazi se glavna logika stranice za prijavu, koja koristi sve gore opisane metode. Ovaj dio koda nije premješten u funkciju. Na kraju se poziva get_footer().

Kopirajte funkcionalnost wp-signup.php

Zatim će biti opisana procedura kopiranja wp-signup.php u MU dodatke i izmjene na "forku". Možda se ovo ne čini kao ispravan način. Umjesto toga, možete napisati vlastite funkcije za provjeru valjanosti i prikazivanje obrazaca ispočetka koristeći klase umjesto uobičajenih funkcija. Po mom mišljenju, wp-signup.php već ima svu potrebnu logiku za našu stranicu, preostaje samo napraviti male izmjene.

Prilikom ažuriranja WordPressa, wp-signup.php također se mijenja s vremena na vrijeme, ali to ne znači da ćete morati sinkronizirati svoju “fork” sa svakim izdanjem. Funkcije unutar wp-signup.php u osnovi ne rade ništa osim HTML izlaza, provjere valjanosti podataka, kreiranja računa i web mjesta te wpmu_ prefiksiranih metoda deklariranih u ms-functions.php.

Kreirajmo funkciju koja će prikazati obrazac za registraciju na stranici. Da biste to učinili, kopirajte wp-signup.php iz korijena WordPressa u mu-plugings/selena-network/signup/ . Spojite ga unutar mu-plugins/selena-network/signup/plugin.php).

Zahtijevaj WPMU_PLUGIN_DIR. "/selena-network/signup/wp-signup.php";

Uklonite sve potrebne i nepotrebne provjere od samog početka kopirane datoteke. U verziji 4.1.1, ovo je sav kod od redaka 1 do 80.

Sada smo spremni za izradu glavne funkcije za prikaz obrasca za prijavu. Da bismo to učinili, prenijet ćemo svu logiku iz retka 646 do samog kraja datoteke u funkciju koja se zove selena_network_signup_main. Na samom kraju ćemo ukloniti dva dodatna zatvaranja

(linije 722 i 723), kao i poziv get_footer() .

U novokreiranoj selena_network_signup_main() , na samom početku ćemo deklarirati globalnu varijablu active_signup , koju koriste sve ostale metode iz ove datoteke. I dodajte poziv u događaj before_signup_form, koji smo uklonili sa samog početka datoteke.

Funkcija selena_network_signup_main() ( globalna $active_signup; do_action("before_signup_form"); // ... )

Sada preostaje samo promijeniti izgled na svim mjestima gdje je to potrebno i stranica za registraciju je spremna.

Ispis obrasca za registraciju

Ovdje postoje najmanje dvije opcije. Prikladniji način je stvoriti kratki kod i postaviti ga na stranicu putem običnog uređivača.

// Stvaranje kratkog koda network_signup add_shortcode("network_signup", "selena_network_signup_main");

Druga opcija je stvaranje predloška stranice page-signup.php u mapi podređene teme. Umjesto riječi "prijava", možete koristiti jedinstveni ID dodijeljen stranici. Unutar predloška dodajte potreban izgled i pozovite selena_network_signup_main() na pravo mjesto.

Kao rezultat toga, moja stranica za registraciju izgleda puno bolje i čistije.

Stranica za aktivaciju

WordPress prema zadanim postavkama uvjetno dijeli proces registracije u Multisite u dva koraka - ispunjavanje obrasca na stranici i aktivaciju računa klikom na poveznicu poslanu u e-poruci. Nakon što ispunite obrazac kreiran u prethodnom odjeljku, WordPress šalje e-poruku s nekim uputama i poveznicom za aktivaciju vašeg računa.

Za prikaz aktivacijske stranice odgovorna je datoteka wp-activate.php koja se nalazi u korijenskom direktoriju WordPressa. wp-activate.php također se može potpuno promijeniti. Proces je sličan onome što smo već napravili za wp-signup.php.

Kreirajmo stranicu example.org/activate/ kroz uobičajeno sučelje. Za adresu koristite bilo koji URL koji vam se čini odgovarajućim.

Kopirajte datoteku wp-activate.php u naše MU dodatke i uključite je u mu-plugins/selena-network/signup/plugin.php.

Zahtijevaj WPMU_PLUGIN_DIR. "/selena-network/signup/wp-activate.php";

Unutra nema puno sadržaja, za razliku od wp-signup.php. Datoteka izvodi jednu operaciju - aktivira račun ako se primi točan ključ i prikazuje poruku o pogrešci ili uspjehu.

Uklonimo sve nepotrebne provjere i zahtijevamo - retke 1 do 69 u WordPressu 4.1.1. Na samom kraju ćemo ukloniti poziv get_footer(). Preostali sadržaj bit će prebačen u funkciju selena_network_activate_main().

Zanimljivo je napomenuti da je ovdje prije učitavanja WordPressa (wp-load.php) deklarirana konstanta WP_INSTALLING. Njegova prisutnost uzrokuje da WordPress ne učitava dodatke.

Kao iu slučaju stranice za registraciju, ostaje samo ispraviti izgled gdje je to potrebno. Također možete promijeniti tekst prikazanih poruka (u ovom slučaju, ne zaboravite dodati tekstualnu domenu vaših MU dodataka u sve funkcije prevoditelja, ona nije nigdje postavljena prema zadanim postavkama).

Gotova funkcija može se koristiti na unaprijed stvorenoj stranici putem kratkog koda ili zasebnog predloška u podređenoj temi.

Aktivacijske e-poruke s ispravnim poveznicama

Aktivacijska stranica je spremna za rad, ali WordPress ne zna za to i svejedno će slati aktivacijske e-poruke s vezom na wp-activate.php. Za razliku od wp-signup.php, ne postoji filter koji bi vam omogućio promjenu adrese. Umjesto toga, trebate napisati vlastitu funkciju koja će slati e-poštu s ispravnim vezama.

Prilikom ispunjavanja i slanja obrasca na stranici za registraciju, WordPress poziva wpmu_signup_ korisnik() ili wpmu_signup_ blog() ovisno o vrsti registracije. Obje funkcije stvaraju novi unos u tablici wp_signups, ispunjavajući je potrebnim sadržajem, uključujući aktivacijski ključ računa.

Nakon toga, ovisno o funkciji, poziva se wpmu_signup_ korisnik _notification() ili wpmu_signup_ blog _obavijest() . Obje funkcije imaju sličnu funkcionalnost - generiraju i šalju e-poštu s vezom za aktivaciju, ali uzimaju različite argumente. Oba imaju filtere za "hvatanje" događaja.

If (! apply_filters("wpmu_signup_user_notification", $user, $user_email, $key, $meta)) return false;

Da biste aktivirali račune stvaranjem bloga:

If (! apply_filters("wpmu_signup_blog_notification", $domain, $path, $title, $user, $user_email, $key, $meta)) ( return false; )

Ostaje samo da napišete vlastite handlere unutar kojih šaljete pisma putem wp_mail() , a na samom kraju obavezno dajte false kako WordPress ne bi dva puta poslao aktivacijsko pismo - jedno je vaše, drugo je zadano pismo s poveznica na wp-activate.php.

Funkcija selena_network_wpmu_signup_user_notification($user, $user_email, $key, $meta = array()) ( // Generiraj zaglavlje, tijelo i zaglavlja e-pošte // ... // Pošalji e-poštu ili dodaj Cron zadatak za slanje e-pošte wp_mail($user_email , wp_specialchars_decode($subject), $message, $message_headers); // Proslijedi false kako WordPress ne bi poslao aktivacijsku e-poštu dva puta vrati false; ) add_filter("wpmu_signup_user_notification", "selena_network_wpmu_signup_user_notification", 10, 4);

Ako šaljete e-poštu putem SMTP poslužitelja ili je broj registracija vrlo velik, razmislite o tome da e-poštu ne šaljete odmah. Umjesto toga, možete dodati Cron poslove koristeći WordPress Cron.

Zatvaranje pristupa wp-signup.php i wp-activate.php

Nakon što ste izradili vlastite stranice za registraciju i aktivaciju, možda ćete morati zatvoriti "izvornike". Na primjer, ako na stranici za registraciju postoje dodatna polja koja je potrebno ispuniti. Također, mnoge WordPress stranice podliježu registraciji neželjene pošte.

Kako biste riješili dva problema u jednoj akciji, možete zatražiti od Apachea da vrati 404 u slučaju pokušaja otvaranja ovih stranica. Da biste to učinili, samo trebate registrirati nekoliko dodatnih RewriteRule u vašoj konfiguracijskoj datoteci ili .htaccess .

RewriteEngine On RewriteBase / # Poznavanje regularnih izraza nikad nije suvišno :) RewriteRule ^wp-signup\.php - RewriteRule ^wp-activate\.php - # POČNI WordPress # Ostavi zadana WordPress pravila :) # ... # KRAJ WordPress

Zaključak

Za ovaj i mnoge druge "probleme" vezane uz WordPress postoje brojna rješenja na internetu. Na primjer, kako bi se stvorile stranice za registraciju i aktivaciju, neki predlažu ponovno pisanje izvornih wp-signup.php i wp-activate.php. Ne biste to trebali činiti jer ako ažurirate WordPress, izgubit ćete sve promjene napravljene u datotekama, a također nećete moći provjeriti integritet jezgre pomoću .

Kada razvijate bilo koji dodatak, temu ili rješenje, odvojite malo vremena da se uhvatite ukoštac s onim što se događa unutar WordPressa. Za to postoje mnogi korisni alati za otklanjanje pogrešaka.

p.s.

Možete koristiti dodatak za upravljanje korisnicima na više stranica za automatsko dodjeljivanje različitih uloga novim korisnicima.

Ako nakon čitanja članka imate bilo kakvih pitanja ili poteškoća tijekom izrade stranica za registraciju i aktivaciju, ostavite komentar i mi ćemo vam sigurno odgovoriti.

27.03.2015 27.03.2015

WordPress programer. Voli red u svemu i razumijevanje novih alata. Nadahnut arhitekturom komponenti Symfony.

  • Teme obično nisu funkcionalne, ali ponekad mi kao programeri moramo implementirati neke značajke u svoju temu kako bismo je učinili malo boljom i praktičnijom.

    U ovom ćemo vodiču istražiti pojam "teritorij dodataka" i također naučiti kako koristiti fantastičan alat koji je napisao Thomas Griffin: TGM knjižnicu za aktivaciju dodataka.

    Funkcionalnost teme: Invazija teritorija dodatka

    Teme su dizajnirane za promjenu dizajna WordPress web stranice. U idealnom slučaju, tema bi trebala utjecati samo na vizualni aspekt. Međutim, u naše zlatno doba WordPressa, programeri dodataka često uključuju značajke u svoje teme koje im pomažu da ostanu konkurentni na tržištu.

    Ovo je invazija na teritorij dodataka. Možemo zamisliti "područje dodatka" kao neki funkcionalni dio koda. Svaki dio koda koji mijenja funkcionalnost vaše stranice mora se poslati kao dodatak, osim ako navedeni kod nije ugrađen u jezgru WordPressa.

    Već sam formulirao pravilo o "teritoriju dodataka" ranije u jednom od mojih članaka:

    Ako je značajka povezana s vizualnom prezentacijom stranice, tada bi je trebalo uključiti u temu; ako se odnosi na funkcionalnost, onda bi trebao biti predstavljen kao zaseban dodatak.

    Prilično jednostavno pravilo. Ljudi i dalje pokušavaju kodirati funkcionalne isječke u svoje teme, ali direktoriji tema (poput WordPress.org ili ThemeForest) ne prihvaćaju teme koje zadiru na "područje dodataka". Stoga je ponuda funkcionalnosti u temama postala definitivan izazov.

    Srećom, postoji jednostavno rješenje koje nije u suprotnosti s pravilom "teritorija dodataka".

    Uvod u TGM biblioteku za aktivaciju dodataka

    Konfiguriranje aktivacije TGM dodatka

    Obratite pozornost na funkciju tgmpa() s dva parametra na samom kraju koda. Drugi parametar je varijabla $config, koja je također niz, baš kao i $plugins. Kao što naziv sugerira, možete prilagoditi biblioteku TGM Plugin Activation pomoću ovog polja. Varijabla također prihvaća vlastiti skup opcija:

    • id (string) - jedinstveni id za biblioteku TGM Plugin Activation u vašoj temi. Ovo je vrlo važno: ako drugi dodaci također koriste TGM Plugin Activation, različiti ID-ovi spriječit će moguće sukobe.
    • default_path (string) - Zadana apsolutna staza za dodatke u vašoj temi. Nakon što ga instalirate, moći ćete koristiti naziv ZIP datoteke kao vrijednost parametra izvora za vaš dodatak.
    • izbornik (string) – izbornik izbornika za stranicu instalacije dodatka.
    • has_notices (boolean) - ako je postavljeno na true, izdavat će se obavijesti administratora za potrebne/preporučene dodatke.
    • dismissible (boolean) - ako je postavljeno na true, korisnik može "odbaciti" obavijesti.
    • dismiss_msg (string) - Ako je opcija za odbacivanje postavljena na false, ova će poruka biti prikazana iznad obavijesti administratora.
    • is_automatic (boolean) - ako je postavljeno na true, dodaci će se aktivirati nakon što ih korisnik pristane instalirati.
    • poruka (string) - dodatni HTML izlaz prije tablice dodataka.
    • nizovi (niz) - niz koji uključuje izlazne poruke. Možete ih odrediti kao nizove emitiranja. Potpuni popis svih objava potražite u datoteci example.php.
    "mytheme-tgmpa", // vaš jedinstveni TGMPA ID "default_path" => get_stylesheet_directory() . "/lib/plugins/", // zadana apsolutna staza "menu" => "mytheme-install-required-plugins", // izbornik izbornika "has_notices" => true, // Prikaži obavijesti administratora "dismissable" => false , // obavijesti se NE mogu odbaciti "dismiss_msg" => "Stvarno, stvarno trebam da instalirate ove dodatke, u redu?", // ova poruka će biti ispisana na vrhu nag "is_automatic" => istina, // automatski aktiviraj dodatke nakon instalacije "poruka" => "", // poruka za izlaz neposredno prije tablice dodataka "strings" => array(); // Niz nizova poruka koje koristi TGM Plugin Activation); ?>

    Zaključak

    Kao što vidite, moguće je ponuditi funkcionalnost u WordPress temama - samo prvo morate razmisliti o korisnicima koji bi mogli prijeći s jedne teme na drugu. Knjižnica TGM Plugin Activation nudi stvarno pametan način za to.

    Što mislite o ovom alatu? Jeste li ga ikada koristili, planirate li ga koristiti u budućnosti? Podijeli svoje misli!

    Kreirajmo vlastitu stranicu za registraciju na više stranica umjesto standardne wp-signup.php.

    U tipičnoj instalaciji WordPressa, stranica za registraciju (prijava, poništavanje lozinke) prikazana je u datoteci wp-login.php.

    • /wp-login.php - autorizacija
    • /wp-login.php?action=register - registracija
    • /wp-login.php?action=lostpassword - ponovno postavljanje lozinke

    Postoje zasebni uvjeti za multisite u wp-login.php. Dakle, kada kliknete na /wp-login.php?action=register na multisite-u, ​​WordPress će preusmjeriti na stranicu /wp-signup.php. U mnogim temama stranica ne izgleda baš privlačno, pa ćemo napraviti vlastitu.

    Glavna stranica mreže

    Prema zadanim postavkama, WordPress otvara stranicu za prijavu (wp-signup.php) na glavnoj domeni (web stranici) weba. Međutim, moguće je napraviti zasebnu stranicu za registraciju za svako mjesto u mreži, čak i ako imaju različite teme. Razmotrit ćemo slučaj kada sve stranice u mreži imaju svoju stranicu za registraciju, ali se koristi ista tema i stranice se razlikuju samo po jeziku. Ako se koriste različite teme, bit će potrebno više koda.

    funkcije.php?

    Ne. Čini se da se naziv ove datoteke spominje u svakom WordPress članku. U našem slučaju, uzimajući u obzir činjenicu da je funkcionalnost registracije dizajnirana za nekoliko stranica, ima smisla premjestiti je na MU dodatke koji se učitavaju kada se bilo koja stranica otvori.

    Lirska digresija

    Vrijedno je napomenuti da se MU dodaci učitavaju prije normalnih dodataka i prije nego što se jezgra WordPressa potpuno učita, tako da pozivanje nekih funkcija može dovesti do kobnih pogrešaka u PHP-u. Ovo "rano" učitavanje ima svoje prednosti. Recimo, unutar bilo koje teme ne možete se uhvatiti za neke akcije koje rade čak i prije nego što se datoteka functions.php učita iz teme. Primjer za to su akcije iz Jetpack dodatka oblika jetpack_module_loaded_related-posts (related-posts je naziv modula) pomoću kojih je moguće pratiti aktivnost modula u Jetpacku. Ova se radnja ne može "priložiti" iz datoteke teme jer je akcija već pokrenuta prije učitavanja teme - dodaci se učitavaju prije tema. Možete pogledati opću sliku redoslijeda učitavanja WordPressa na stranici Action Reference u kodeksu.

    Redoslijed datoteka

    MU dodaci mogu sadržavati bilo koji broj datoteka i bilo koju strukturu koja vam se čini logičnom. Slijedim ovakvu hijerarhiju:

    |-mu-dodaci |-|-load.php |-|-|-selena-network |-|-|-|-prijava |-|-|-|-|-plugin.php |-|-|-| -|-... |-|-|-|-jetpack |-|-|-|-|-plugin.php

    U datoteci load.php spojeni su svi potrebni "pluginovi" za našu mrežu:

    // Učitaj Traslates za sve dodatke load_muplugin_textdomain("selena_network", "/selena-network/languages/"); // Prijava na mrežu zahtijeva WPMU_PLUGIN_DIR. "/selena-network/signup/plugin.php"; // Još jedan dodatak // zahtijeva WPMU_PLUGIN_DIR ...

    Mape dodataka pohranjene su unutar mape selena-network, svaka ima svoj plugin.php , koji uključujemo u load.php . To daje fleksibilnost i mogućnost brzog onemogućavanja i omogućavanja određenih stvari.

    URL stranice za registraciju

    Filter wp_signup_location koristi se za određivanje adrese stranice za prijavu. Može se pronaći unutar datoteke wp-login.php i odgovoran je za preusmjeravanje na wp-signup.php.

    Case "register" : if (is_multisite()) ( wp_redirect(apply_filters("wp_signup_location", network_site_url("wp-signup.php"))); izlaz;

    Dodajmo našu funkciju u mu-plugins/selena-network/signup/plugin.php , koja će dati adresu stranice za registraciju na trenutnoj stranici:

    Funkcija selena_network_signup_page ($url) ( return home_url () . "/signup/"; ) add_filter ("wp_signup_location", "selena_network_signup_page", 99);

    selena_network je prefiks koji koristim u nazivima svih funkcija unutar MU dodataka na svojoj stranici kako bih izbjegao kolizije, trebao bi se zamijeniti vašim vlastitim jedinstvenim prefiksom. Dodajte prioritet filtra 99 jer neki dodaci poput bbPress i BuddyPress mogu prebrisati ovu adresu svojom (MU dodaci se učitavaju prije normalnih dodataka, pogledajte gore). Imajte na umu da se home_url() koristi umjesto network_site_url() kako bi se posjetitelj zadržao na istoj domeni. Bilo koji URL može se koristiti kao adresa.

    Izrada stranice

    Kreirajmo sada stranicu s adresom site.com/prijava/ kroz uobičajeno sučelje, au mapi podređene teme predložak za našu novu stranicu je stranica-prijava.php. Umjesto riječi "prijava" možete koristiti jedinstveni ID.

    Unutar novog predloška morate pozvati funkciju selena_network_signup_main(), koja će prikazati obrazac za prijavu.

    Vrijedno je napomenuti da je cijeli postupak s predlošcima neobavezan i umjesto toga možete stvoriti vlastiti kratki kod, koji će također pozvati funkciju selena_network_signup_main().

    wp-signup.php i wp-activate.php

    Kreirajmo sada funkciju koja će prikazati obrazac za registraciju. Da biste to učinili, kopirajte datoteke wp-signup.php i wp-activate.php iz korijena WordPressa u mu-plugings/selena-network/signup/ (i ne zaboravite ih uključiti unutar mu-plugins/selena-network /signup/plugin.php) . Daljnje manipulacije datotekama izuzetno je teško i dugo opisati, pa ćete ih morati učiniti sami. Samo ću opisati što točno treba učiniti i objaviti izvorne datoteke mog projekta:

    1. Na početku datoteke uklonite sve zahtjeve, pozive funkcija i drugi kod izvan funkcija.
    2. Preimenujte sve funkcije dodavanjem jedinstvenih prefiksa imenima.
    3. Zamotajte donji dio koda wp-signup.php u funkciju selena_network_signup_main i na samom početku napišite globalnu $active_signup; .
    4. Zamijenite izgled vlastitim na pravim mjestima.

    Unutar wp-activate.php trebate učiniti istu stvar:

    1. Uklonite sav kod izvan funkcija, zamotajte izgled u zasebnu funkciju.
    2. Promijenite izgled gdje je potrebno.

    Datoteka wp-activate.php odgovorna je za stranicu za aktivaciju računa. Kao i kod stranice za registraciju, za nju morate izraditi poseban predložak unutar kojeg trebate pozvati funkciju iz datoteke wp-activate.php.

    Slanje aktivacijskih e-poruka

    Stranica za registraciju šalje e-poruku posjetitelju s poveznicom za aktivaciju računa. Prema zadanim postavkama, ovime upravlja funkcija wpmu_signup_user_notification() iz datoteke ms-functions.php. Njegova se funkcionalnost može posuditi za njegovu funkciju. Razlog zbog kojeg morate prestati koristiti ovu značajku je taj što šalje vezu za aktivaciju računa s wp-activate.php. Ovu funkciju možete "isključiti" pomoću filtra wpmu_signup_user_notification tako da mu date false (ako se to ne učini, aktivacijsko pismo će biti poslano dva puta, ok, zapravo dva različita slova).

    Funkcija armyofselenagomez_wpmu_signup_user_notification($user, $user_email, $key, $meta = array()) ( // ... // Kod iz wpmu_signup_user_notification() funkcija wp_mail($user_email, wp_specialchars_decode($subject), $message, $message_headers) ; return false; ) add_filter("wpmu_signup_user_notification", "armyofselenagomez_wpmu_signup_user_notification", 10, 4);

    Kao rezultat toga, stranica za registraciju u temi Selena postala je mnogo čišća i urednija.

    Zaključak

    Ima mnogo drugih ne baš ispravnih načina na internetu kako napraviti isto - Apache preusmjeravanja, AJAX forme koje neće raditi bez Java Scripta, itd. Nije mi se baš svidjelo sve ovo, pa sam pokušao to učiniti što korektnije moguće na mojoj web stranici.

    Napominjem da biste trebali pažljivo uređivati ​​datoteke i pokušati ne odstupati previše od originalnih, kako bi u budućnosti, ako WordPress promijeni datoteke wp-signup.php i wp-activate.php, bilo lakše usporediti da pronađu promjene.

    Ne zaboravite pogledati izvorni kod svih gore opisanih funkcija kako biste u potpunosti razumjeli što se i kako događa unutar koda.

    Bonus. Zaštita od spamera

    Čak su i najmanje WordPress stranice često bombardirane neželjenim registracijama. Možete napisati beskonačne uvjete za filtriranje botova, često više kao pokušaj stvaranja umjetne inteligencije 🙂 U slučaju multisite-a, uobičajeno preusmjeravanje u Apacheu mi je puno pomoglo, s kojim sam tražio izdavanje 404 pri otvaranju /wp-signup. php i /wp-acitvate.php (nisam stručnjak za postavljanje Apachea, pa moja pravila možda nisu baš točna).

    RewriteEngine On RewriteBase / RewriteRule ^wp-signup\.php - RewriteRule ^wp-activate\.php - # POČETAK WordPressa # Zadana pravila WordPressa :) # ... # KRAJ WordPressa

    P.S. Pokušavam što detaljnije opisati neke stvari treće strane, jer kad sam ja počinjao, ponekad nije bilo nikoga da potakne i objasni mnoge stvari. Također vjerujem da će takvi mali savjeti o drugim materijalima potaknuti nekoga da nauči nešto novo i proširi svoje područje znanja. Unosi RewriteRule koriste regularne izraze, uopće nisu komplicirani, npr. znak ^ označava početak retka.

    Registrira funkciju koja će se aktivirati kada se dodatak aktivira.

    Ova funkcija pridružuje navedenu funkciju povratnog poziva kuki activate_(plugin) i predstavlja omotač za ovu kuku.

    (plugin) u kuki activate_(plugin) zamjenjuje se imenom relativne staze do glavne datoteke dodatka. Na primjer, ako se dodatak nalazi: wp-content/plugins/sampleplugin/sample.php , tada će naziv kuke biti: activate_sampleplugin/sample.php .

    Od verzije 3.1. Priključak se aktivira samo tijekom aktivacije dodatka, a ne aktivira se tijekom automatskog ažuriranja dodatka.

    Kako radi

    Dodatak se aktivira funkcijom activate_plugin(), koja pokreće kuku activate_(plugin).

    Funkcija activate_plugin() u jezgri poziva se nakon učitavanja okruženja VI. Ova funkcija uključuje glavnu datoteku dodatka (i sve u njoj), a zatim putem kuke aktivira navedenu funkciju povratnog poziva. Zbog toga su sve funkcije i klase dodatka dostupne u našoj funkciji povratnog poziva. No, budući da su se sve glavne WP zakačke već pokrenule tijekom učitavanja WP okruženja, nijedan događaj dodatka obješen na zakačke, kao što je plugins_loaded, više neće raditi kada je uključena glavna datoteka dodatka. To znači da će naš dodatak biti spojen, ali ne u potpunosti: ne zato što bi trebao biti spojen kad je već aktiviran.

    Tako, na primjer, ako dodatak učini nešto tijekom događaja plugins_loaded, tada se sve te radnje jednostavno neće dogoditi kada se dodatak aktivira. Na primjer, ako uključuje datoteku prijevoda, tada datoteka prijevoda neće biti uključena kada se pokrene funkcija povratnog poziva navedena za register_activation_hook().

    U pravilu, nakon pokretanja funkcije povratnog poziva, postoje 2 događaja na kojima se funkcije mogu objesiti: activated_plugin i shutdown.

    Da biste učinili nešto otmjeno kada aktivirate dodatak, pogledajte primjer 5.

    Uvjeti korištenja

    Funkcija neće raditi ako se pozove u trenutku pokretanja bilo koje kuke, na primjer plugins_loaded, init. Funkcija se mora pozvati izravno iz glavne datoteke dodatka. Pravila aktivacije:

      register_activation_hook() se mora pozvati iz glavne datoteke dodatka gdje se nalazi naredba Plugin Name: ... i ne smije se pozvati iz bilo koje kuke kao što su plugins_loaded ili init.

      Funkcija kuke mora biti u istoj datoteci kao kuka ili uključena unaprijed iz druge datoteke.

      U funkciji kuke, izlaz na ekran (echo) ne radi. Jer postoji preusmjeravanje i nećete vidjeti odjek. Ali možete koristiti die() .

    1. Globalne varijable (ako ih ima) moraju biti eksplicitno definirane kako bi im se pristupilo iz funkcije kuke.

    Napomena o opsegu varijable

    Kada je dodatak aktiviran, glavna datoteka dodatka nije uključena u globalni opseg, već unutar funkcije activate_plugin(). Stoga varijable koje se smatraju globalnima u normalnom načinu rada dodatka neće biti globalne.

    Na primjer, funkcija koja se koristi u register_activation_hook() možda neće vidjeti globalne varijable, čak i ako ste ih deklarirali kao globalne unutar te funkcije. Primjer:

    $myvar = "nešto"; kuka_za_aktivaciju_registra (__DATOTEKA__, "moj_plugin_aktivirati"); function myplugin_activate()( global $myvar; echo $myvar; // Varijabla nije jednaka "nečemu" )

    Zbog ove osobitosti, globalne varijable moraju uvijek biti eksplicitno navedene. Sve globalne varijable moraju biti definirane kao globalne, čak i ako je varijabla navedena u tijelu dodatka. Samo u ovom slučaju bit će im pristup bilo gdje. Primjer:

    Globalni $myvar; // eksplicitno naznačite da je ovo globalna varijabla $myvar = "nešto"; kuka_za_aktivaciju_registra (__DATOTEKA__, "moj_plugin_aktivirati"); funkcija myplugin_activate()( globalni $myvar; echo $myvar; //> nešto)

    Nema kukica.

    vraća

    ništavan. Ne vraća ništa.

    Korištenje

    kuka_za_aktivaciju registra($datoteka, $funkcija); $datoteka (string) (obavezno) Put do glavne php datoteke dodatka, uključujući naziv samog dodatka. Obično se koristi čarobna PHP konstanta __FILE__. $funkcija (string/niz/lambda) (obavezno)

    Naziv funkcije povratnog poziva. Za klase koristite niz: array($this, "function_name"); .

    Funkcija će primiti Booleovu varijablu $network_wide - je li dodatak aktiviran za cijelu mrežu stranica, s više stranica.

    Primjeri

    #1. Pokretanje funkcije kada je dodatak aktiviran

    Pretpostavimo da imamo funkciju my_plugin_activate() u glavnoj datoteci dodatka: wp-content/plugins/myplugin/myplugin.php, a zatim za pokretanje ove funkcije tijekom aktivacije dodatka upotrijebite sljedeći kod:

    Priključak_za_aktivaciju_registracije(__FILE__, "moj_plugin_aktivirati"); funkcija my_plugin_activate() ( // Aktivacijski kod... )

    #2. Izvođenje metode klase

    Ako dodatak koristi PHP klasu, aktivacijski kod se dodaje ovako:

    Register_activation_hook(__FILE__, array("My_Plugin", "install")); klasa My_Plugin ( statička funkcija install() ( // Ne stvarajte nikakav izlaz ovdje... ) )

    #3. Izvođenje metode klase iz zasebne datoteke

    Ako je klasa koja sadrži aktivacijsku funkciju u zasebnoj datoteci, registrirajte aktivacijsku funkciju ovako:

    uključi_jednom __DIR__ . "/class-My_Plugin.php"; kuka_za_aktivaciju_registra (__FILE__, array("Moj_dodatak", "na_aktivaciji_funkcije"));

    #4. Pokretanje metode klase iz same klase

    Ako ste unutar __construct() . Važno, __FILE__ mora "pogledati" glavnu datoteku dodatka:

    Register_activation_hook(__FILE__, array($this, "YOUR_METHOD_NAME"));

    #5 Učinite nešto odmah nakon aktivacije dodatka

    Nakon što se dodatak aktivira, pokreću se samo dvije kuke: activated_plugin i shutdown.

    Kada morate nešto učiniti odmah nakon aktivacije dodatka, možete im priložiti funkciju.

    Kada to rješenje ne radi, možete koristiti WP opcije: pohranite podatke u opciju, a zatim provjerite postoji li opcija i učinite nešto ako opcija postoji:

    // Glavna datoteka dodatka. ... funkcija my_plugin_activate() ( // dodaj opciju da kasnije, ako postoji, učiniš nešto. add_option("Activated_Plugin", "Plugin-Slug"); // Aktivacijski kod ovdje... ) register_activation_hook(__FILE__, " my_plugin_activate"); funkcija load_plugin() ( if (is_admin() && get_option("Activated_Plugin") == "Plugin-Slug") ( // uklonite dodanu opciju tako da više ne radi // i učinite ono što trebamo... delete_option( "Activated_Plugin "); // Učinite nešto jednom, nakon aktivacije dodatka // Na primjer: add_action("init", "my_init_function"); ) ) add_action("admin_init", "load_plugin");

    Još jedna opcija da učinite nešto tijekom aktivacije dodatka je kreiranje vlastitog događaja poput ovog:

    Funkcija my_plugin_activate()( // Instalirajte našu kuku tako da se može spojiti na nju iz datoteka dodatka do_action("my_plugin_activate"); ) register_activation_hook(__FILE__, "my_plugin_activate");

    #6 Još jedna demonstracija korištenja funkcije

    Mali dodatak koji pokazuje kako se koristi funkcija:

    /* Naziv dodatka: Opis testa: Test */ require_once dirname(__FILE__) . "/moja_druga_datoteka.php"; /* Ovaj kod neće raditi. Aktivacijska kuka mora biti pozvana iz glavne datoteke. register_activation_hook (dirname(__FILE__) . "/my_other_file.php", "my_other_function"); */ // Ovo je radni kod. kuka_za_aktivaciju_registra(__FILE__, "test_aktivirano"); /* Ovo je ispravan način za deklariranje i pristup globalnim varijablama. Globalne varijable moraju biti jasno deklarirane. Bez toga im nećete imati pristup. */ globalno $some_var; $some_var = "hej"; // Funkcija aktivacijske funkcije test_activated()( // ovdje $some_var neće biti jednako hey global $some_var; // A ovdje će $some_var biti jednako hey // Ova funkcija definirana je u datoteci "my_other_file.php" my_other_function (); /* Ovo neće raditi Ako želite zapisivati ​​zapisnike u privremenu datoteku koristite fopen/fwrite Ako želite testirati radi li kuka za aktivaciju koristite exit() unutar funkcije kuke */ echo "test_activated called !";)