Jump to content

Dr4k3

Active Members
  • Posts

    427
  • Joined

  • Last visited

Everything posted by Dr4k3

  1. pwei aia intreb si yo...si defapt yo am scris aia...ce e acolo...
  2. pe ce ip l-ai folosit si ce port ai ales?
  3. sincer m-am saturat de windows si de bily ala cu microsoftu lui... nu stiu de ce da cred ca (sigur) o sa ma dau p linux...
  4. ehehehehe...asa crezi u ca e...de fapt sunt sigur ca pe roman il tin cateva luni la cancera pana ii face un psiholog un test de inteligenta sia poi pleaca omu linistit la nasa si ya acolo salariu mai mare decat gigi si traieste linistit si fericit omu...
  5. ce e cu "@hanibal"-u ala acolo???
  6. si mai precis ce se intelege prin a ajuta forumul? inteleg ca bani nu vreti...mi se pare corect...oarecum...atunci ce doriti?sa fac multe posturi?sa fac ce??? srry da chiar vreau vip sau mod pe forum...sincer mai mult mod decat vip...
  7. voi doi ne acuzati pe mine si pe hanibal de post hunting deci...atunci mai bine cautati voi posturile noastre...si daca la mine posturile aiurea is in procent mai mare de 20% eu cer ban!
  8. voi despre ce vb? srry astoria nu stiam k ejti fata
  9. lol...anyway is multi care inca folosesc 7.5 ...nush de ce...
  10. am dat...fura si u de pe altceva
  11. Tehnica SQL injection da posibilitatea unui atacator sa execute comenzi SQL neautorizate porfitand de oportunitati neortodoxe de intrare in aplicatiile web construind interogari SQL dinamice. Acesta devine posibil deoarece PHP combina sirurile interogarilor MYSQL pe care le setezi cu variabila inainte pentru ca cineva sa poata adauga o a doua interogare sau schimba interogarea ta pentru a le oferi informatii sau acces pe care nu ar trebui sa il aiba. Cele mai obisnuite dintre aceste intrari includ apostrofuri unescaped in declaratiile SQL. PROBLEMA Considerati urmatoarea interogare SQL in PHP: $result=mysql_query('SELECT * FROM users WHERE username="'.$_GET['username'].'"'); Interogarea selecteaza toate randurile din tabelul userilor unde username-ul este acelasi cu cel din sirul de interogari. Daca priviti cu atentie, veti realiza ca declaratia este vulnerabila la SQL injection - apostroful in $_GET['username'] nu sunt , si prin urmare nu vor fi cuprinse ca parte din declaratie, ceea ce permite un comportament defectuos. Ganditi-va ce s-ar intampla daca $_GET['username'] ar fi urmatorul: " OR 1 OR username = " (dublu apostrof, urmat de textualul " OR 1 OR username = " urmat de un alt dublu apostrof). Cuprins in expresia originala, interogarea devine urmatoarea: SELECT * FROM users WHERE username = "" OR 1 OR username = "". Altfel, un dublu apostrof va ramane la sfarsitul afirmatiei. Aceasta selecteaza toate sirurile din tabelul userilor. Desi nu pare periculos, alte coduri infectate pot fi adaugate, mai ales in interogarile DELETE sau UPDATE care modifica tabelul. De asemenea, un alt sir de coduri SQL poate fi adaugat la SELECT * FROM `users` WHERE username = '' adaugand un apostrof sau o semicoloana la sfarsit, astfel sirul devene SELECT * FROM `users` WHERE username = ''; ' care cu usurinta se transforma in SELECT * FROM `users` WHERE username = ''; DELETE * FROM `forum` WHERE title != '' SOLUTIA Niciodata sa nu aveti incredere in informatiile userului, procesati informatia numai dupa validare. De regula, aceasta se face prin pattern matching. In exemplul urmator, username-ul este restrictionat la caractere alfanumerice plus underscore si cu o lungime cuprinsa intre 8-20 caractere – modificati la nevoie. if (preg_match("/^w{8,20}$/", $_GET['username'], $matches)) $result = mysql_query("SELECT * FROM users WHERE username=$matches[0]"); else // we don't bother querying the database echo "username not accepted"; O buna practica in codare afirma ca apostrofurile duble ar trebuie folosite mereu in oricarei informatii variabile. Ori folosing slash dublu apostrof , ori apostrof simplu, cadrand intreaga interogatie, pentru ca tipul opus de interogatie sa nu trebuiasca escaped, desi acelasi tip de apostrof trebuie escaped. $result = mysql_query('SELECT * FROM users WHERE username = "$usern"'); or $result = mysql_query("SELECT * FROM users WHERE username = "$usern" "); Pentru o siguranta mai mare, renuntati la executarea scriptului inlocuind echo cu exit() or die(). Aceasta inca se mai aplica atunci cand se folosesc checkboxuri, butoane ratio, liste de selectie, etc. Orice browser cerut (chiar si POST) poate fi REPLICATED prin telnet, situri duplicate, javascript, sau codare(chiar si PHP), asadar intotdeauna trebuie sa fiti prevazatori in privinta restrictiilor pentru codarea aferenta clientului. Folosirea mysql_real_escape_string() PHP ofera o functie care se ocupa cu inserarea userului in MySQL, si aceea este mysql_real_escape_string(string unescaped_string[, resource link_identifier]). Acest script scapa de toate caracterele potential periculoase din sir si transforma sirul escaped intr-unul prudent pentru a fi folosit in sirul MySQL. (Functia originala, myqsl_escape_string, nu a luat in considerare caracterul curent pentru a iesi din sir, nici nu a acceptat argumentul conexiunii. Este dezaprobata inca de la PHP 4.3.0) Spre exemplu, luati urmatorul exemplu: $result=mysql_query('SELECT * FROM users WHERE username="'.$_GET['username'].'"'); Aceasta poate fi escaped dupa cum urmeaza: $result=mysql_query('SELECT * FROM users WHERE username="'.mysql_real_escape_string($_GET['username']).'"'); Astfel, daca userul a incercat sa insereze o alta declaratie in afara de DELETE, ar fi interpretat inofensiv ca o parte din parametrul clauza WHERE: SELECT * FROM `users` WHERE username = '';DELETE * FROM `forum` WHERE title != '' Backslashurile adaugate de mysql_real_escape_string face ca MySQL sa le interpreteze ai degraba ca si caractere cu un singur apostrof decat ca si parte din declaratia SQL. Luati la cunostinta cu MySQL nu permite multe interogari asadar DELETE FROM din tabel nu merge oricum. Autor madaeroblade
  12. In incercarea noastra de a scrie cat mai putin cod pentru aceleasi lucruri, ne aplecam destul de des asupra problemei query-urilor catre baza de date. Avem cateva tipuri de query-uri pe care le repetam de fiecare data cand vrem ceva din baza de date. Poate ca unii dintre voi au deja cateva functii standard prin care isi fac treaba cu SQL-ul. Si mai multi insa prefera framework-uri consacrate, cum ar fi PEAR::DB in combinatia uluitoare si flexibila cu DB::FormBuilder. Daca insa sunteti printre cei care nu vor o solutie atat de complicata, dar totusi, zic eu, fiabila, stati cu mine. PEAR::DB si FB au dezavantajele lor, printre care viteza redusa, numarul mare de variabile si parsari ale FB. Despre probleme ca acestea, si in special cea a parsarii template-urilor, vom discuta cu alta ocazie. Ceea ce intereseaza acum este o clasa care ne va oferi acces usor la baza noastra de date. Vom denumi clasa noastra DBFrame. Ea este un exemplu real de lucru si este deja folosita in dezvoltarea LifeCMS. Am furat o idee de la PEAR::DB. Fiecare baza de date va fi instantiata intr-un obiect al clasei noastre (nu fiecare tabel, ca in PEAR). Astfel, vom putea lucra cu baze multiple, daca este nevoie. Prima functie de care ne vom ocupa este constructorul clasei, cel care va realiza conexiunea cu baza de date. Cu siguranta, codul va este cunoscut: class DBFrame{ function __construct($host,$user,$pass,$database) $con = mysql_connect($host,$user,$pass) or die("Conectare nereusita:".mysql_error()); $db = mysql_select_db("$database", $con) or die("Nu pot selecta baza de date ".$database.":".mysql_error()); } Vom instantia bazele de date folosind urmatoarea linie. Trebuie sa aveti grija insa ca liniile de instantiere sa fie scrise intr-un fisier sigur, pentru ca vor contine datele de conectare la baza. $baza_de_date1 = new DBFrame("localhost","user","parola","tabel1"); Dupa ce ne-am conectat, urmeaza sa scriem o functie care sa execute variatele query-uri de care vom avea nevoie. function execute_query($q){ $handle=mysql_query($q); return $handle; } Aceasta functie nu face decat sa execute query-ul primit si sa ii intoarca rezultatul brut. Pentru a putea folosi insa datele intoarse va trebui sa le formatam intr-un fel. De aceea, mai avem nevoie de inca o functie. function query($q){ $result=$this->execute_query($q); $ret=Array(); while($ret[]=mysql_fetch_assoc($result)); array_pop($ret); return $ret; } Functia query() foloseste execute_query(), prima functie pe care am creat-o, pentru a obtine un handle pentru query-ul primit, si apoi formateaza datele in array-ul $ret, pe care il intoarce. Linia array_pop($ret); este necesara, deoarece functia mysql_fetch_assoc() intoarce intotdeauna un camp gol in plus, la sfarsitul array-ului. Ce putem realiza pana acum? Putem instantia foarte usor mai multe baze de date si putem executa query-uri pe ele printr-o singura linie: $baza_de_date=new DBFrame("localhost","user","parola","tabel"); $tabel=$baza_de_date->query("SELECT * FROM tabel"); Putem simplifica query-urile si mai mult. Putem scrie o functie care sa execute query-uri de tip SELECT, alta care sa faca numai DELETE, EMPTY sau DROP, alta pentru INSERT etc. Dintre toate, cea din urma pare cea mai cu probleme. Sa vedem cum facem usor un insert cu mica noastra DBFrame. in primul rand, este de observat ca, in afara de SELECT, nici un tip de query nu intoarce nimic. in scrierea functiei pentru SELECT vom utiliza functia query(), pentru ca ea intoarce datele formatat. Pentru INSERT si toate celelalte vom folosi execute_query(), pentru ca este mai rapida, in cazul in care nu avem nevoie de datele returnate. Si, in plus, nu va mai da eroare. Sunteti liberi sa incercati Sa ne gandim la inserarea in baza de date. De obicei, este nevoie de asa ceva atunci cand exista un form de inserare a datelor in baza. Aproape toate insert-urile de pe web au un front-end, care este aproape intotdeauna un form. Atunci vom construi functia noastra de insert direct adapdata la un form. M-am gandit ca nu as vrea sa scriu o functie separata pentru UPDATE, asa ca o sa punem cateva conditii in plus si ne vom face functia sa updateze automat. De fapt, aproape automat: vom include in formular un camp ascuns in care vom stoca primary key. Daca acesta este gol, inseamna ca se va face insert. Daca nu, atunci inseamna ca userul a folosit butonul de edit si atunci facem update. Si deci functia: function insert($table_name,$values,$primary='id'){ if(!empty($values[$primary]) && isset($values[$primary])) $q="UPDATE ".$table_name." SET "; else $q="INSERT INTO ".$table_name." SET "; foreach($values as $key=>$value) if($key!=$primary) $q.=$key.'="'.$value.'",'; $q=substr($q,0,-1); // scoate virgula in plus de la ultima iterare a lui foreach if(!empty($values[$primary]) && isset($values[$primary])) $q.=' WHERE '.$primary.'="'.$value.'"'; $this->execute_query($q); } Dupa cum am spus, intai stabilim daca este vorba de un INSERT sau un UPDATE si apoi cream query-ul, conform valorilor din arrayul $values. Ceilalti parametrii sunt $table_name pentru numele tabelului pe care se va executa query-ul si $primary pentru primary key, in caz ca aceasta nu are ca nume obisnuitul "id". La sfarsitul query-ului adaugam o clauza WHERE in cazul in care exista "id" si apoi executam query-ul folosind execute_query(), deoarece nu avem nevoie de rezultat. Acum ramane de vazut cum vom construi formularul. Fiecare camp va trebui sa poarte numele asociat din baza de date. De ce? Pentru a nu ne complica. Daca facem asta, tot ce trebuie sa-i servim functiei noastre insert() va fi $_POST. Desigur, $_POST va contine si butonul de submit, dar problema se poate rezolva simplu: if(isset($_POST['submit'])){ array_pop($_POST); insert('tabel',$_POST); } Daca este vorba de un edit, scriptul ar trebui sa stie. Pentru asta, nu trebuie decat sa introducem campul cu numele primary key-ului din tabel si sa-i atribuim o valoare, de obicei din $_GET: <input type="hidden" name="id" value="<?=$_GET['tabel_id']?>" />
  13. Cea mai frumoasa si mai gustoasa supa nu are nici o legatura cu farfuria in care este pusa. Ati incercat totusi sa mancati cea mai frumoasa si mai gustoasa supa dintr-o farfurie perfect plata? Stiti, sunt farfuriile acelea patrate si mari, mari de tot, care fac o supa la fel de buna ca mult prea mult bors. Un site este asemanator unei astfel de supe in multe privinte. Toate ingredientele pot fi perfect echilibrate, iar siteul poate lasa un gust perfect in mintea vizitatorului, insa totul depinde de modul in care siteul ajunge la vizitator. URL-uri frumoase si usor de tinut minte sunt la fel de importante ca restul siteului. Si Google mananca supa din farfurie adanca Oricat de ciudat suna, asa este. Motoarele de cautare precum Google nu indexeaza decat anumite URL-uri, in speta, le sare pe acelea care contin caractere ciudate precum ? sau &, sau alte extensii decat .html (de exemplu, .php). Si atunci siteul nostru nu mai este indexabil. Problema trebuie rezolvata cat mai repede. Cum va place urmatorul URL: http://www.example.com/index.php?pid=categories&action=edit&eid=14 Am putea sa-l schimbam foarte usor, pentru a arata in felul urmator: http://www.example.com/categories/edit/14/ Mult mai bine acum, nu? Plus ca este usor de retinut si indexabil. Apache si .htaccess Pentru a realiza acest mic feat trebuie sa-i spunem serverului sa ne transforme URL-ul primit la o cerere HTTP intr-unul de o forma mai atragatoare. Apache permite rescrierea URL-urilor printr-un modul minunat numit mod_rewrite. Pentru a specifica niste reguli de rescriere pe care acest modul sa le foloseasca, vom utiliza fisierul .htaccess. In radacina siteului vostru creati un fisier fara nume, doar cu extensia .htaccess. Acest fisier este de tip text si in el vom scrie ce ne trebuie. Este bine sa setam in scripturile noastre parametrii impliciti si sa prevedem URL-uri de forma: http://www.example.com/categories/ http://www.example.com/categories/edit/ De aceea vom incepe rescrierea progresiv, cu primul parametru, apoi cu al doilea si asa mai departe. Pentru a fi siguri de rezultat, vom incepe fisierul nostru .htaccess cu o conditie: <IfModule mod_rewrite.c> RewriteEngine on </IfModule> Conditia testeaza existenta modulului mod_rewrite. In cazul in care el exista, il va porni. Desi el este setat pe ON in majoritatea pachetelor de hosting, niciodata nu strica sa verifici. Sa purcedem acum la rescriere. Fiecare pagina a siteului va avea un numar de parametri $_GET, pornind de la 0 la un numar maxim pe care va trebui sa-l stabiliti voi. Majoritatea programatorilor prefera modelul de tip MVC, in care primul parametru este pagina, al doilea actiunea, iar ceilalti doi variaza. In exemplul nostru nu am avut nevoie decat de id-ul elementului ce trebuia editat. Presupunem deci ca avem un GET de forma: $_GET = Array( page, action, param1, param2 ) Haideti sa rescriem primul parametru, "page". Vom utiliza comanda rewriteRule pentru a stabili regula. RewriteRule <regex::rezultat> <string::URL> Prima parte a comenzii, <regex::rezultat> reprezinta rezultatul la care vrem sa ajungem, iar a doua, <string::URL>#end_code este URLul initial cu ? si & cu care suntem obisnuiti. Apache va modifica toate URLurile de forma <regex::rezultat> in URLuri de forma <string::URL>#end_code. Astfel, daca vom scrie in browser <regex::rezultat>, serverul va trimite inapoi <string::URL>. Nimic mai simplu. Dar sa lamurim printr-un exemplu. Practica nu ne omoara RewriteRule ^([a-zA-Z]+)[/]*$ ?page=$1 Am utilizat regular expressions. Daca nu va sunt familiare, va spun doar ca ceea ce pare complicat de fapt nu este. Puteti citi tutorialul precedent pentru a va lamuri ce inseamna tot ce am scris acolo. Promit ca o sa fie de folos. Prin urmare, ce am facut este sa-i spun Apacheului ca atunci cand intalneste un URL de forma "/" sa serveasca browserului pagina aflata la URLul ?page=, adica pagina normala server-side pe care o foloseati pana acum. $1 din sirul ?page=$1 inseamna prima paranteza din regexul precedent, adica ^([a-zA-Z]+)[/]*$. Sa trecem mai departe la al doilea parametru: action. RewriteRule ^([a-zA-Z]+)[/]([a-zA-Z]+)[/]*$ ?model=$1&action=$2 Nu am facut decat sa repetam prima paranteza, iar in URLul initial sa scriem &action=$2, intocmai cum am fi scris inainte, cand foloseam URLuri cu $_GET. Pentru al treilea si al patrulea parametru vom proceda intocmai. Si acum cum ne mai folosim de $_GET? E o intrebare fireasca. Daca URLul nostru arata acum astfel: http://www.example.com/categories/edit/14/ atunci unde gasim cheile si valorile din $_GET. Nu uitati ca am stabilit niste chei standard, pe care le-am folosit in RewriteRule: page, action, param1 si param2. Acestea sunt cheile arrayului $_GET, iar valorile sale sunt caracterele dintre slash-uri. Astfel, cunoscand aceste chei si privind URLul nostru, putem deduce usor GET-ul: $_GET = array ( 'page' => 'categories', 'action' => 'edit', 'param1' => '14' ) In spatele acestui URL, serverul utilizeaza de fapt un alt URL, si anume cel pe care il utilizam noi inainte de a invata rewrite: http://www.example.com/index.php?pid=categories&action=edit&eid=14 Practic, URLul rescris, http://www.example.com/categories/edit/14/, nu este decat "de ochii lumii", serverul lucrand in continuare la fel. Astfel, veti putea utiliza GET-ul ca si pana acum. Puteti modifica aceste chei pentru a va servi propriului site. Nu uitati sa modificati si in .htaccess. Intreaga smecherie este insa de a utiliza aceiasi parametri, aceleasi chei ale arrayului GET. Daca siteul tau are doua pagini, si fiecare pagina are parametrii ei, vei avea mai multe reguli de scris - cate una pentru fiecare parametru - plus ca va trebui sa verifici in regex ce fel de parametru ai. Daca parametrii GET nu sunt comuni intregului site, URLul ar trebui sa se transforme in: http://www.example.com/page/categories/action/edit/ iar regula in: RewriteRule ^([a-zA-Z]+)[/]([a-zA-Z])+[/]([a-zA-Z]+)[/]([a-zA-Z]+[/])$ ?$1=$2&$3=$4 Acest lucru este necesar pentru pastrarea numelor parametrilor, in cazul in care acestia sunt diferiti de la pagina la pagina. Daca insa alegeti acelasi nume pentru toti parametrii din site, va va fi mult mai usor sa lucrati si nu va mai fi nevoie sa transmiteti numele parametrilor in URL. Daca totusi ati utilizat parametrii diferiti, o solutie este sa le schimbati numele in "param1", "param2" etc. Daca faceti asa, va trebui sa modificati scriptul si sa fiti atenti la ordinea parametrilor in URL. Exemplu: pagina 1 = ?cat=1&id=213 pagina 2 = ?firma=32&user=no Parametrii vor trebui sa se transforme astfel: Pagina 1 : cat in param1, id in param2 Pagina 2 : firma in param1, user in param2 Sper ca am fost destul de clar in explicarea unei probleme destul de spinoase. Parte din puterea mod_rewrite consta in utilizarea optima a regular expressions, asa ca aruncati un ochi si peste tutorialul care le trateaza, pentru a putea aplica cu mai mult succes tehnica rescrierii. Autor Vlad Fratila
  14. Nu am folosit niciodata Smarty, desi implementarea lui are anumite avantaje. Insa am fost nevoit: stiti cum sunt designerii. Am construit cateva clase care ma ajuta sa pornesc repede un template, fie cu Smarty, fie fara. Intotdeauna trebuie sa fii pregatit sa faci munca HTML, si nu as vrea sa ma incetinesc cu Smarty. Am construit o clasa de baza, pe care mai apoi voi construi alte doua clase: una pentru include-uri, care va compune un template normal, si alta pentru Smarty. Aplicatia va hotari cand este cazul sa construiasca obiectul pe Smarty si cand nu. Aceasta abordare este interesanta si din punctul de vedere al optimizarii vitezei de executie: de ce sa incarci Smarty daca nu iti trebuie? Iata clasa de baza, denumita iView. Abstract class iView { var $registry; var $model; var $action; function __construct($model,$action){ $this->model = $model; $this->action = $action; parent::__construct(); if(function_exists($this->__init())) $this->__init(); } abstract function render(); } Templateurile mele sunt denumite in forma model_action.tpl – de aici necesitatea variabilelor $model si $action. In afara de acestea, clasa defineste alte doua functii. Prima este __init, pe care o va apela la construire, dar doar daca exista. Dupa cum vom vedea, Smarty va avea nevoie de o initializare, care se va petrece in aceasta functie. In cealalta clasa, pe care o vom apela daca nu vom folosi Smarty, nu va fi nevoie de __init(). A doua functie, render() este de tip abstract. Asta inseamna ca fiecare copil o va implementa, lucru normal, de altfel – este metoda principala a acestui grup de clase. Sa construim mai intai clasa SimpleHTML pentru cazurile In care nu vom folosi Smarty. Ea va implementa doar functia render(), care va include templateurile conform variabilelor model si action. class VSimpleHTML extends iView { function render(){ $this->_pageTitle = $this->model.$this->action; if(file_exists('app/public/header.tpl')) include 'app/public/header.tpl'; if(file_exists('app/views/'.$this->model.'/'.$this->action.'.tpl'))include 'app/views/'.$this->model.'/'.$this->action.'.tpl'; if(file_exists('app/public/footer.tpl')) include 'app/public/footer.tpl'; } } Acestea sunt include-urile mele. Cred ca arata destul de familiar pentru a nu mai fi explicate. Acum sa trecem la clasa de smarty. Aplicatia Smarty consta intr-o serie de clase legate impreuna in smarty.class.php din directorul libs/. Aceasta clasa va trebui instantiata pentru a avea acces la Smarty. Dupa cum am spus, vom folosi functia __init() pentru acest lucru. class VSmarty extends iView { var $smarty; function __init(){ require (SMARTY_DIR. 'libs/smarty.class.php'); $this->smarty = new Smarty(); $this->smarty->template_dir = MAIN_PATH.'/templates'; $this->smarty->compile_dir = MAIN_PATH.'/templates_c'; $this->smarty->config_dir = MAIN_PATH.'/configs'; $this->smarty->cache_dir = MAIN_PATH.'/cache'; } function render(){ $this->smarty->display($this->model. '_'.$this->action.'.tpl'); } } La Inceput se va apela functia __init(), asa cum am definit in constructorul clasei de baza. Aici instantiem obiectul Smarty si setam caile de acces. Structura de baza a Smarty consta in patru directoare: * templates_dir – locul templateurilor de baza (create de designer) * compile_dir – locul templateurilor compilate – aici intra templateurile de baza impreuna cu fisierele pe care le includ * config_dir – locul fisierelor de configurare * cache_dir – directorul de cache Asta este toata initializarea de care avem nevoie. Vom stoca templateurile in directorul „templates/”, numindu-le dupa conventia stabilita: model_actiune.tpl. In functie de cele doua variabile vom randa templateul In functia render() folosind functia smarty::Display. Ati observat cele doua constante: fac viata mai usoara. Integrarea Smarty este foarte simpla in acest mod si, daca nu va convine, puteti trece imediat inapoi pe HTML simplu. Pe viitor, ati putea cu usurinta adauga o clasa care sa randeze RSS-uri sau PDF-uri. Daca aveti nelamuriri, acum avem si sectiune de comentarii, courtesy of AHAH. Poate pe viitor voi arata cum sa implementam un presenter de PDF. Autor Vlad Fratila
  15. Unde vrem sa ajungem ? Cand ati ajuns sa descoperiti ca Flash-ul poseda un tip de data numit "Date", este imposibil sa nu va doriti sa construiti un ceas analogic precum acesta. Cu ce cunostinte puteti porni la drum? Pai v-ar trebui cam asa: putina tigonometrie, notiunea de movieclip si cea de punct de insertie a acestuia, functii pentru determinarea orei, minutului, secundei, proprietatea _rotation a unui movieclip si un mecanism de a rula o functie in mod repetitiv (gen setInterval sau onEnterFrame). Incepeti prin a crea un document nou flash la dimensiunile 200 x 200 si fundal negru. Desenati un cerc (eu am ales: 170.5px x 170.5px) pozitionat in centrul scenei Transformati-l in movieclip (tasta Fb) , denumiti acest movieclip contur si instanta de pe scena tot contur. Ceas analogic in Flash Ceas analogic in Flash Autor Corina Haloiu Adauga comentarii Commentariile voastre Ceas analogic in Flash Unde vrem sa ajungem ? Cand ati ajuns sa descoperiti ca Flash-ul poseda un tip de data numit "Date", este imposibil sa nu va doriti sa construiti un ceas analogic precum acesta. Cu ce cunostinte puteti porni la drum? Pai v-ar trebui cam asa: putina tigonometrie, notiunea de movieclip si cea de punct de insertie a acestuia, functii pentru determinarea orei, minutului, secundei, proprietatea _rotation a unui movieclip si un mecanism de a rula o functie in mod repetitiv (gen setInterval sau onEnterFrame). Incepeti prin a crea un document nou flash la dimensiunile 200 x 200 si fundal negru. Desenati un cerc (eu am ales: 170.5px x 170.5px) pozitionat in centrul scenei Transformati-l in movieclip (tasta Fb) , denumiti acest movieclip contur si instanta de pe scena tot contur. Completati designul format din cifrele sale (de diviziunile corespunzatoare orelor ne vom ocupa ceva mai incolo), apoi realizati 3 movieclip-uri pentru limbile ceasului (eu le-am numit: hour, min si sec) pentru care punctul de insertie sa fie capatul limbii care "sta" fix, adica cel din centrul cadranului ceasului. In acest moment documentul vostru ar trebui sa arate astfel: Sa facem limbile sa se miste! Ceea ce trebuie sa stiti este ca proprietatea _rotation a unui movie clip are valori cuprinse intre 0 si 180 pentru o rotire in sensul acelor de ceas, respectiv intre 0 si -180 pentru o rotire in sensul invers acelor de ceas si ca de exemplu 367 grade este totuna cu 7 grade, iar 270 de grade este totuna cu -90 grade. Apoi, tinand cont ca pentru cele 360 de grade cat are un cerc secundarul parcurge 60 de secunde, inseamna ca fiecarei secunde ii va corespunde un unghi egal cu 360/60 adica 6 grade. Mai clar spus, la trecerea unei secunde, movieclip-ul numit sec trebuie sa faca o rotatie cu 6 grade in sensul acelor de ceas evident. Acelasi lucru se va intampla cu movieclip-ul numit min. In schimb, pentru cele 360 grade corespunzatoare unui cerc, orarul parcurge 12 ore, deci la trecerea unei ore, movieclip-ul numit hour va face o rotatie de 360/12 adica de 30 de grade. Sa analizam functia setare de mai jos. Aceasta este functia care se va executa in mod regulat la fiecare 100 de milisecunde trecute. Codul ei este pe scena principala, in primul frame. function setare() { var my_date:Date = new Date(); var h = my_date.getHours(); var m = my_date.getMinutes(); var s = my_date.getSeconds(); sec._rotation = 6*s; min._rotation = 6*m; hour._rotation = 30*h+m/2; } Variabilele h, m, s vor memora ora, minutul, respectiv secunda pentru momentul de timp curent. Daca s este 3, avem nevoie de o rotatie egala cu 6 grade * 3; la modul general o rotatie cu 6*s pentru movieclip-ul numit sec. De aceea avem atribuirea: sec._rotation = 6*s; La fel se vor petrece lucrurile si pentru min._rotation. Pentru movieclip-ul hour, unghiul de rotatie este suma a doua unghiuri. Primul are valoarea 30*h si reprezinta rotatia pentru fiecare trecere a cate unei ore conform rationamentului de mai sus, iar expresia m/2 se datoreaza faptului ca vrem ca, daca ora este de exemplu 5:30, movieclip-ul numit hour sa nu fie exact in dreptul cifrei 5, ci undeva la jumatatea arcului de cerc dintre 5 si 6, astfel ca avem nevoie de o regula de trei simpla si anume: daca in 60 de minute acul care indica ora parcurge un arc de cerc de 30 grade, atunci, in m minute va parcurge un arc de cerc de m*30/60 grade, adica de m/2 grade. Acum cred ca este mai clar de unde vine atribuirea: hour._rotation = 30*h+m/2; Ramane doar sa apelati functia setare, nu o singura data ci, dupa primul apel sa stabiliti reapelarea acesteia la un interval de 100 ms sa zicem. Altfel spus, codul actionscript se rezuma la functia setare si cele doua randuri de mai jos. setare(); setInterval(setare, 100); Daca nu functioneaza, urmariti daca movieclip-urile pentru cele 3 limbi ale ceasului poarta numele hour, min, sec. Daca nici asa nu functioneaza... trimite-ti un email Inapoi la diviziuni Veti spune probabil ce mare filosofie sa desenezi niste bulinute sau liniute. Numai ca farmecul nu este acela de a le desena, ci de a scrie un script care sa faca munca asta, mai ales ca este atat de simplu... Sa pornim deci la drum. Va amintiti ca avem un movieclip care se numeste contur? Si ca nu l-am folosit deloc pana acum ? Acum i-a venit si lui randul sa devina util. Dar mai intai avem nevoie de un alt movieclip pentru una din cele 12 diviziuni ce corespund orelor. Creati un cerc cu diamentrul de 5px, transformati-l in movieclip (din nou F8, ati retinut, da ?) iar in fereastra Convert to Symbol selectati butonul Advanced spre a putea sa asociati un identificator acestui movieclip (in Library). Bifati deci “Export for ActionScript” si alegeti un nume. Eu i-am spus bulina. O sa va intrebati la ce foloseste asta ? Raspuns: pentru a putea apoi sa cream diviziunile in mod dinamic, prin actionscript. In primul frame, tot acolo unde aveti si scriptul care face ca limbile ceasului sa se miste, va aparea in plus partea de script pentru crearea diviziunilor. Am marcat cu rosu ceea ce este nou. diviziuni(); setare(); setInterval(setare, 100); function diviziuni() { var raza = contur._width/2-4; var niv = 100; for (var i=0; i<12; i++) { var flm=attachMovie("bulina", "b"+i, ++niv); unghi = i*360/12; alfa = (unghi)*Math.PI/180; flm._x = contur._x+raza*Math.cos(alfa); flm._y = contur._y-raza*Math.sin(alfa); } } function setare() { var my_date:Date = new Date(); var h = my_date.getHours(); var m = my_date.getMinutes(); var s = my_date.getSeconds(); sec._rotation = 6*s; min._rotation = 6*m; hour._rotation = 30*h+m/2; } Sa analizam sursa functiei diviziuni care face toata munca de trasare a diviziunilor. Si pentru ca un desen face mai mult decat o mie de cuvinte, in imaginea de mai jos am exemplificat pozitia bulinei relativa la centrul cercului numit contur. Mai intai am fixat o raza a unui cerc imaginar pe care voi pozitiona aceste diviziuni ca fiind aproximativ egala cu jumatate din diametrul cercului numit contur. Mai exact cu 4 pixeli mai mica. Apoi am ales un nivel pe stiva pentru crearea celor 12 movieclip-uri (100). Si in sfarsit, in cadrul structurii for se vor executa, pentru fiecare din cele 12 diviziuni pasii: * crearea unei instante pe scena ca si copie a movieclip-ului numit bulina, instanta identificata mai apoi prin intermediul variabilei flm (var flm=attachMovie("bulina", "b"+i, ++niv) * fixarea unghiului de rotatie unghi (vezi figura) (360/12 reprezinta a 12-a parte dintr-un cerc, pentru prima bulina unghiul va fi de 0 grade, pt urmatoarea de 360/12 grade, pentru urmatoarea de doua ori 360/12 grade s.a.m.d) (unghi = i*360/12;) * transformarea acestui unghi din grade in radiani pentru ca functiile flash pentru calculul sinusului si cosinusului primesc argumentele exprimate in radiani (alfa = (unghi)*Math.PI/180;) * fixarea poxitiei bulinei (flm._x = contur._x+raza*Math.cos(alfa); si flm._y = contur._y-raza*Math.sin(alfa) Autor Corina Haloiu
  16. C++ ca limbaj de programare, suporta 3 baze de numaratie: normalul decimal, folositorul hexadecimal si total inutilul si eventual creatorul de probleme octal. Ma refer aici la conventia de scriere a unui numar in octal: orice numar incepand cu cifra 0. De aici confuzii de genul 0033 fiind de fapt 27 si nu 33 prefixat cu 0-uri pt. frumusete sau stil:) Ca o paranteza curioasa, numerele de genul 08, 09 sunt total ilegale in C/C++, deoarece evident octul are cifre numai de la 0 la 7. Incercati de exemplu int i = 08; in orice compilator si urmariti efectul! C/C++ fiind limbaje de nivel mediu, operand cu concepte per masina: pointeri, sizeof(), etc, ar fi trebuit sa contina si posibilitatea de a scrie numere direct in baza 2 (in binar) care de mult ori ar fi fost de dorit decat blamatul octal. Cei care lucreaza des cu operatii pe biti, cred ca ar fi apreciat cel mai mult o atare functionalitate. Exista compilatoare care suporta numere introduse direct in baza binar, de exemplu GCC, dar mult de preferat ar fi fost o standardizare. Bineinteles ca se pot scrie functii specializate pentru asa ceva (conversie din/in binar) cand este nevoie, dar cum orice programator de C/C++ stie, o functie inseamna extra timp la rulare, chiar daca in ziua de azi e de ordinul mili/nanosecundelor. Deci inca odata, o solutie din compilator ar fi perfecta! Desi C++ nu ofera asa ceva, ofera in schimb suportul pentru a construi asa ceva... Ma refer aici la template-uri si mecanismul de specializare a acestora. Prin utilizarea unei clase template specializata pe int, se pot realiza in C++ constructii in baza 2, care vor fi evaluate de compilator automat drept simple numere in baza 10! De examplu putem avea ceva de genul: binar<11>::valoare care va fi automat evaluat si inlocuit de compilator (deci fara nici o implicatie asupra rularii programului) cu valoarea in baza 10:3 Codul care face posibil asa ceva: /* * determinam la inceput cel mai mare integer care poate fi * descris (atomic) pe o masina, pt a beneficia de cele mai * multe lungi secvente de cifre pe o masina de 32 biti: * 'long'(dword din asm) de maxim 10 cifre pe masini x86 * 'long long' de maxim 19 cifre pe masini x64 * (long long exista si pe masina de 32 biti, dar va * fi simulat sau truncat) */ typedef long long longest_t; /* * clasa template, specializata numai pentru longest_t * tot secretul aici este valoarea elementului 'value' din * enum, care nu e precizat direct ci lasat sa fie evaluat * prin recursivarea in alte instante ale clase template, * adica numarul nostru 'deghizat' in binar (el fiind tot * scris in decimal), va fi impartit pana la epuizare la * 10, retinand resturile impartirii (adica izoland cifra * cu cifra) apoi reinmultind cu 2 pt a schimba baza. */ template<longest_t N> class bin { public: enum { value = (N % 10) + (bin<N/10>::value << 1) }; }; /* * ne vom opri la ultima cifra, pt a ingadui incheierea * lantului recursivitatii si 'reimpachetarea' stivei * acest lucru este posibil datorita specializarii (adica * tratarii separate a) template-ului pt. cazul cand * numarul devine 2 (acest lucru e 'fortat' de noi mai * jos...) */ class bin<2> { public: enum { value = 0 }; }; Desi template-urile au realizat toata treaba pentru noi si sunt instrumente perfecte aici, operand numai in timpul compilarii, vom apela totusi la fratii lor 'vitregi': macrocomenzile, din doua motive: # 1. e destul de ciudat a scrie bin<10>::value de fiecare cand vrem numarul 2 scris in binar # 2. dupa cum am spus in introducere octalul ne poate juca feste, asa ca vom prefixa invizibil un 2 in fata oricui numar in noua baza, pt a inlatura orice confuzii si pt a avea si un mecanism simplu de stop. Macro-ul este: #define binary(n) bin<2##n>::value De notat aici operatorul ## al preprocesorului, care lipeste direct doi operanzi sau paramatri (din a##b va rezulta ab). Cu toate acestea puse la punct, nimeni nu ne mai opreste sa scriem de acum incolo: binary(11) = binary(011) = binary(000000000000000011) pentru 3 binary(11111111) pentru 255 binary(100000000000000000) pentru 131072 binary(111111111111111111) pentru 262143 (maximumul in binar pe un sistem pe 32biti) Sper sa va placa micul truc si folositi-l pe oriunde aveti ocazia sau nevoia! Ca o nota in plus, pe acest mecanism al utilizarii templaturilor si faptul ca ele sunt evaluate de catre compilator printr-o 'pseudoexecutie', numeroase alte programe interesante se pot realiza: numarare de biti, mini calculatoare pt. constante, etc. O nota de inspiratie personala a fost vizualizarea unui mini compilator de LISP realizat numai in template metaprogramming (exact ce am utilizat mai sus)! credits: it-zone
  17. adik ai nevoie de c++ ca sa il compilezi...
  18. pwei am pus da nu asa repede...tu cronometrezi intervalul dintre 2 posturi(100s) si postezi tut...ur fuckin crazy...
  19. La inceputul acestui an, Sony anunta cu mare pompa primul hardware e-Book reader ce va folosi e-Ink, o tehnologie ce ofera unui ecran aspect perfect de foaie de hartie. Luna trecuta, acest produs s-a materializat, devenind produsul din imagine: Sony Reader. Deviceul are un ecran cu diagonala de 6". Displayul este intr-adevar asa cum a promis Sony, si anume bazat pe tehnologia e-Ink. Aceasta consta in pixeli care pot fi albi sau se pot colora in 4 trepte de gri, pana la negru complet. O data ce pixelii au fost colorati intocmai datelor documentului deschis, ei vor ramane asa, astfel incat deviceul nu consuma curent decat la schimbarea pixelilor (in genere, atunci cand dai pagina). Acestea fiind spuse, Sony Reader iti va permite sa citesti astfel orice vrei tu: PDFuri, DOCuri, chiar si imagini si MP3uri. Totusi, in memoria interna de 128MB nu pot incapea prea multe, asa ca Sony s-a decis sa ofere Readerului suport pentru carduri SD si Memory Stick (si MS Duo, cu adaptor). Cititorii avizi sunt desigur deja decisi. Pentru ei, nu mai spun decat ca pretul este de 350$. Din pacate, produsul abia lansat, nu este disponibil inca in Romania. Pentru cei mai sceptici, Sony Reader nu poate atrage prea mult ca idee: trebuie sa vezi ca sa crezi. Displayul este perfect si nu are nici o problema la citirea niciunui fisier: toate documentele sunt automat adaptate on-the-fly pentru ecranul de 6", textul poate fi marit pana la 200%, bateria tine 7500 de intaorceri de pagina. Sony a deschis recent si un magazin cu ebookuri, books.connect.com, insa acestea nu sunt foarte multe, si nici foarte ieftine. Insa ebookuri se gasesc.
  20. Microsoft a lansat astazi un update pentru Vista care ar trebui sa detecteze orice incercare de piratare a procesului de autentificare si sa opreasca sistemul. Compania Microsoft s-a aratat foarte prompta la atacul noului lor sistem de operare de catre grupari de hackeri. La cateva saptamani de la lansare, Vista este deja piratat, si nu intr-un singur fel. Noul efort in prevenirea pirateriei se numeste Frankenbuild. Daca scriptul detecteaza o incercare de piratare, userul va avea 30 de zile sa cumpere software valid. Daca nu, scriptul va forta sistemul sa intre intr-o stare minima de functionare, in care userii vor putea doar vizualiza documente si accesa internetul timp de o ora, dupa care vor trebui sa restarteze computerul. Aceasta actiune de a introduce masuri anti-piraterie in interiorul OSului reprezinta un pas inainte in lupta contra pirateriei software purtata de Microsoft de la Windows XP incoace. Compania a declarat ca nu se va opri, pirateria fiind unul dintre principalele domenii care aduc pierderi considerabile.
  21. lol...a fost destept omu...da ce drq criptare e aia...400 calc si 12 ani lol...mai bine ii dau lui cu bruteforce
  22. hoooooooooooo baa...mai usor...ai pus vro 20 da tut da ieri pana azi...mai usor...
  23. de ce nu is si yo "in pas cu moda???"
  24. bah daca omu adik hanibal...ma rog nu e prea om...a gresit si el odata...lasa ca asta e forum de hacking nu de limba romana... si a avut foarte dreptate..daca nemesis e n00b atunci M4Nu ce mai e???
  25. om bun puteai sa te exprimi si altfel...
×
×
  • Create New...