Izgleda da je ovo tjedan 5 lajnera u pythonu. Anywho, radim neki backend za jedan hax0rski portal. U biti, radim neuspješnu reinkarnaciju Metafeeda-a u vidu naslovnice za site Razmjena vještina. Svečana prezentacija bi trebala biti na "Ništa se neće dogoditi". Nakon toga siguran sam da će to biti vaš prvi (ako ne i jedini) feed uz koji ćete ujutro pijuckati kavu.

Daklem... jedna od stvari koja mi treba za backend portala je operacija "uzmi mi random sliku sa images.google.com". Mislio sam da će biti nekog HTML parsanja sa BeautifulSoup ali moj dragi Google me lijepo iznenadio. Pljunu natrag gomilu JavaScripta koji izgenerira stranicu u samom Browseru. Koristeći najobičniji regular expression uzmem sadržaj tog JavaScript Arraya (kao string). Zgodno je što je u ovom slučaju sintaksa za Array polja u JavaScriptu identična Pythonovim listama pa iskoristim običan Pythonov eval da od toga dobijem Pythonovu listu. Da sam i imao želju za Djeda Mraza (iliti lika sa Coca-Coline reklame) ne bi bilo ovako lako na kraju.

Naravno, cijela ova fora će raditi dok Google ne odluči promjeniti sintaksu. Cilj skripte je pokazati ukratko kako sam rješio problem dobivanja URL-a slike (a i da popunim blog ovom trivijalijom). Zbog toga i nisam onečistio code sa provjerama u slučaju grešaka i neispravnih rezultata. Baš mi nešto i ne radi num argument za podešavanje broja rezultata na stranici. Zato koristim argument -p koji mi kaže na koju stranicu rezultata da odem.

Upotreba:

skini.py -p 4 krava muzara
skini.py -r svinjska gripa
 

Skripta skini.py:

#!/usr/bin/python

import urllib2, urllib, re, sys, getopt, random

def fetchURL(query, start = 0):
    req = urllib2.Request('http://images.google.com/images?hl=en&q=%s&gbv=2&aq=f&oq=&aqi=g10&start=%s' % (urllib.quote_plus(query), start))
    req.add_header('User-Agent', 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.1pre) Gecko/20090701 Ubuntu/8.10 (intrepid) Shiretoko/3.5.1pre')
    req.add_header('Accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8')
    req.add_header('Accept-Language', 'en-us,en;q=0.5')
    req.add_header('Accept-Encoding', 'deflate')
    req.add_header('Accept-Charset', 'ISO-8859-1,utf-8;q=0.7,*;q=0.7')
    req.add_header('Connection', 'close')
    r = urllib2.urlopen(req)
    data =  r.read()
    return data

def parseImages(data):
    p = re.compile(";dyn\.setResults\(\[(.+)\]\);\<\/script\>")
    m = p.search(data)
    lst = eval(m.group(1))
    return lst

if __name__ == '__main__':
    try:
        optlist, args = getopt.getopt(sys.argv[1:], 'rp:')
    except getopt.GetoptError, err:
        print "skini.py [-p <page number>] [-r] args\n"
        print str(err)
        sys.exit(-1)
    start, isRandom = 0, False
    for arg, value in optlist:
        if arg == '-p': start = value
        if arg == '-r': isRandom = True
    data = fetchURL(' '.join(args), start = start)
    images = parseImages(data)
    if not isRandom:
        for img in images:
            print img[3]
    else:
        print random.choice(images)[3]
 

"Ej Aco.." - prekinuo me Srki u ___________ dok sam ljenčario na poslu. Naime, zanima ga... da li bi mu mogao prebaciti sadržaj "prodaja Ega/hiperinflacija Emocija" sa http://srdjansandic.blog.com/ na blogger.com. Da li bih mogao... pif....

S obzirom da Aco nije nikad odbio besplatno pivo odlučio sam složiti neku sitnu skriptu koja će mu to raditi. Naime, blogger.com (kaže Srki, nisam ja provjeravao) ne može to sam importati. blog.com nema nikakav public API za export podataka ali zato blogger/blogspot ima.

Brz na idejama, kakav već jesam, bacio sam kratki pogled na
http://srdjansandic.blog.com/. Analizirajući stranice mojim omiljenim FireBugom odlučio sam se na najkraće moguće rješenje (u međuvremenu se malo promjenio template ali u vremenu kad sam prebacivao code je imao smisla).

Daklem.... govoreći riječnikom iskusnih kiber hakera i internauta odlučio sam se za slijedeće:


ćopi_sve_linkove_na_arhivu sa strane "http://srdjansandic.blog.com/";
vrti_kroz_te_stranice { | stranica |
  ćopi_sve_linkove_na_perma_link sa stranica;
  -- LoL !
  vrti_kroz_te_stranice { | stran1ca |
      ćopi_sadržaj_stranice stran1ca;
      izvuci_iz_dom [title, datum, content] -> snimi_u_bazu;
  }
}
 

Naime, šema je slijedeća. Ćopim naslovnu stranu. Na naslovnici se nalaze linkovi na stranice sa arhivama. Uzmem te linkove i skinem svaku od tih stranica posebno. Tamo se nalazi popis svih postova (lako je jer je sve na jednoj stranici) sa dijelom sadržaja. Vrtim kroz svaki od tih postova i uzmem linkove na koje pokazuje link na njihov permalink. Uzmem svaku od tih permalink stranica i iz nje izvučem sadržaj naslova, datum objave i sadržaj. Može i komentare na taj način ali Srki je rekao da nema potrebe za tim.

Zatim dobiven sadržaj spremim negdje (u mom slučaju sqlite3). S obzirom da blogger ima neku zaštitu od SPAM-anja podnosi samo određeni broj postova u danu. Preko Web interfacea se može postati više ali se mora popuniti neki CAPTCHA. Preko GData API-a nisam vidio da ima neka opcija za to pa zbog toga svaki dan opalim nekih 50-etak novih članaka iz baze.

U svemu ovome koristio sam Beautiful Soup. Zakon library koji mi je do sad dosta puta uskočio u pomoć. Kuži loš HTML, lako se izvlači sadržaj iz njega i brine se za encodinge. To im čak piše i na naslovnoj stranici :) Iz nepotpunog primjera koji slijedi (koji nisam ni isprobao) je vidljivo kako se koristi Beautiful Soup i kako sam ja primjenio gornji algoritam na Srkijevom siteu.


import urllib
from BeautifulSoup import BeautifulSoup

def fetchURL(url):
    return BeautifulSoup(urllib.urlopen(url).read(), fromEncoding="utf-8")

soup = fetchURL("http://srdjansandic.blog.com/")

for link in soup.find('div', {"class":"block slideshow"}).findAllNext("a"):
    archive = fetchURL(link["href"])

    for post in archive.find('div', {"id": "posts", "class": "posts"}):
        for plink in post.findAllNext("span", {"class": "permalink"}):
            clanak = fetchURL(plink.next["href"])

            title = clanak.find("h4", {"class": "posttitle"}).next
            datum = clanak.find("h3", {"class": "date"}).next
            text = clanak.find("div", {"class": "posttext"}).next
 

Fali dio koji izvlači podatke iz baze i preko GData python clienta posta na blogger/blogspot.

Tags:

Osobni identifikacijski broj

Thu, 01/08/2009 - 16:07 | Add new comment

Mrzim prepisivanje priča kojih je pun Internet pa se neću baviti ovom temom više od par rečenica. http://www.oib.hr/ je web site gdje možete preko web forme dobiti svoj Osobni identifikacijski broj. To je identifikacijski broj koji će zamjeniti MBG i ne bi baš trebao biti dostupan javnosti. U njihovom FAQ-u kaže...

5. Tko ima pristup mom OIB-u, odnosno, može li ga netko zloupotrijebiti?

Uvid u podatke o OIB-u imat će samo ovlaštene osobe i institucije s tim da će oni putem OIB-a moći ostvariti uvid samo u one podatke za koje su ovlašteni. Središnji registar, u kojem će se putem OIB-a moći vidjeti svi podaci, bit će samo na jednom mjestu za točno određene službenike Porezne uprave uz maksimalnu zaštitu svih upisanih podataka.

Ne vidim impressum na siteu i nisam previše upoznat s tim tko je ovaj site radio, pa s obzirom da ću s ovim ljudima navjerovatnije u jednom trenutku i surađivati neću prstom pokazivati i nazivati ljude imenima ali pobogu.... Pobogu kažem ja!

Ne krivim ja baš toliko onog radnika na industrijskoj traci koji je otvarao svoj prvi web projekat u Eclipesu kad je ovo radio koliko onog tko mu je ovo uopće odobrio i tko je osmislio te financirao cijeli projekat. Nije uopće bitno što im je privatnost toliko bitna da sve vrte preko HTTP-a, nije čak bitno ni što im 8-godišnjak može razbiti captcha, nije čak bitno ni što je taj posao masno plaćen (hardware, software, licence...) već je bitno da su uzeli moje pare, fino ih raspodjelili, napravili to govno (ne samo tehnički) i sad mi ga pokazuju i žele da ja kažem "woooowww...". E pa... wow! Nije prvo a na žalost nije ni zadnje govno koje sam vidio.

Popis JMBG-ova sa imenom i prezimenom nije tako teško nabaviti. Ti podaci su se prije prostituirali šakom i kapom. Sve što netko treba napraviti da postane ovlaštena osoba ili institucija koja ima pristup tim podacima je da rezultat koji se dobije od ovih par programa spojiti sa jednim HTTP POST-om....

Ja ne kažem da bi vi to trebali probati. Ja samo kažem, ako bi netko išao probati sigurno bi to išao ovako napraviti. Ali ako bi ipak išli probati treba vam: wget, Image Magick i ocrad. Za one koji ne znaju što bi ovi programi ukomponirani mogli raditi je: 1) kreira session 2) skine sliku 3) convertira sliku u pbm format 4) ocr-a sliku i vrati tekst. Napomena: ja se nadam da session treba kreirati, to sam onako instinktivno stavio.

Ovo je onako plain u tri linije, neće baš svaku riječ prepoznati ali zavrtite 20 puta pa ćete vidjeti neki prosjek. Uz malo twikanja uz ovakav captcha bez problema se da upogoniti 100% prepoznavanja.

Ako nekome još nije jasno ovo je jedan od dijelova slagalice kako saznati nečiji OIB ako znate njegov MBG. Izgleda da bi trebalo biti dosta jednostavno.... Nije da sam probao ili da planiram.

Sve u svemu, jedva čekam da vidim elektronsko glasanje u hrvatskoj....


wget http:⁄⁄oib.oib.hr/SaznajOibWeb/fizickaOsoba.html --quiet

wget http:⁄⁄oib.oib.hr/SaznajOibWeb/captcha.html --quiet -O - | convert - /tmp/mirko.pbm

ocrad /tmp/mirko.pbm
 

Tags:

Jedna od zadnjih epizoda "30 Rock"-a me podsjeti na nešto što sam radio u ona davna vremena dok sam još imao živaca kodirati 24 sata u komadu. Ne vjerujem ali možda se ipak potrudim i pokušam osposobiti prastaru 386-icu da na njoj pronađem sve te zaboravljene bitova.

Kao velik broj mojih projekata i ovome je na kraju trebalo onih zadnjih 20% ne bi li se finalizirao. Ono što ga ipak razlikuje od ostalih je što sam na ovome prestao raditi jer se projekat u jednom trenutku transformirao u nešto drugo. Vjerovali ili ne ali Pornodrom kao gnutella based server za razmjenu pornjave (sa web front i back endom) se transformirao u ništa drugo doli web kolaboracijski alat za web publishing pod nazivom TamTam. Znam, znam.. TamTam nisam napisao ja već Guru® Neno. Svi mladi haktivisti kiber festivala od Baltika pa do Crnog mora to odavno znaju... Ah, ah.. ali ajmo taj dio priče za sad ostaviti za neki drugi post.

Pretpostavljam da ne treba spominjati da je samo ime "Pornodrom" referenca na Cronenbergov film "Videodrome"?! Uglavnom, Gnutella se tek pojavila i bilo je očito da se radi o nečem vrućem. Postojeći clienti nisu zadovoljavali moje potrebe i osjetio sam potrebu da sebi kao konzumentu olakšam upotrebu cijele te mreže. Koji bolji razlog za pisanje softwarea nego izrada nečega što koristim svakodnevno. Tko će mi bolje napisati software nego ja sam?! Tko zna bolje moje potrebe od mene samoga ?!

Pisati svoj pear-to-peer nema smisla i zato je cijeli sustav bio zamišljen kao nadogradnja nad arhitekturom već postojećeg i raširenog protokola. Nadogradnja u smislu metapodataka za same sadržaje koji se razmjenjuju, naprednijeg pretraživanja, mogućnosti previewa (slike i videa), lakšeg pregleda sadržaja koji drugi ljudi shareaju, komunikacija s ljudima, "agenti" koji pamte preference i konstantno pretražuju mrežu u potrazi za zanimljivim sadržajem itd. Da..da.. dosta toga su imale svakojake mreže i clienti koji su se pojavili poslije, ali u tom trenutku oni nisu bili na tržištu. Uglavno, ta "nadogradnja" je značila da se Pornodrom ponaša kao tipičan Gnutella node koji je bio u stanju slati neke dodatne sadržaje koje su neki napredniji clienti znali interpretirati. Onima koji nisu ti dodatni sadržaji nisu smetali i normalno su komunicirali sa Pornodromom.

Meni je osobno killer dio cijele priče bila mogućnost pristupu serveru preko weba. Zašto? Pa zato što sam imao pristup unixoidnim serverima koji su na brzim Carnetovim linkovima. Pornodrom na njima visi 24/7 te skuplja i sharea s drugima podatke koji se arhiviraju na njemu. U određenom trenutku spojim se preko ultra spore modemske veze na jedan od tih nodova te u browse modu (nešto kao web image gallery sa thumbnailovima) pregledam raspoloživ sadržaj i obrišem nepotrebno. Možda zvuči smješno ali skidati 300Kb sliku preko modema (ili ne do bog gnutelle) da bih rekao "ahhhh...." mi nije bila neka velika sreća. Bolje je pogledati mali animirani GIF-ić koji barem otprilike dočarava što se dešava u videu pa se tek onda odlučiti na download od par desetaka minuta ili sati. Anywho, ako ustreba jedan rcp i fileovi su nakon dosta vremena lokalno na disku.

Sramim se i priznati ali eto, napravio sam cijeli "application server" sa svojim gnutella bibliotekama za sve to. U pozadini python, ZODB kao objektna baza podataka i neki moj template (je*eš python programera koji nije napravio svoj template engine) engine u pozadini. Nikad ja nisam ništa napisao ako mu nisam prvo dao ime. Ovo čudo se zvalo "Thunder" i imalo je čak male munjice za logo. Uglavno, različiti aplikacije unutar Thundera koje međusobno komuniciraju. Web sučelje sa public dijelom kojem pristupaju drugi korisnici (za browse i skidanje sadržaja) te posebno administrativni dio za managiranje Pornodroma i gnutella servera.

U jednom trenutku cijela ta ideja i arhitektura se samo transferirala u nešto drugo i negdje po putu izgubila gnutella server i moje autorstvo :) Čudni su putovi bitova.... čudni.... sad ga imaš a sad ga nemaš ali uvijek dobiješ neko smeće od BLOB-a za kraj.

Tags:

Kako Aco bira prijatelje

Fri, 10/17/2008 - 12:51 | 1 comment

Na oglas o novim prijateljima je bilo različitih reakcija. Od uvrijeđenih poznanika do ideja da je moj stan javna igraonica. U svakom slučaju, kao i svaki majstor i ja volim iskoristiti alate koje svakodnevno koristim da mi olakšaju život. Stvar je dosta modularna tako da se može lako proširivati sa novim Acinim uslovima. Podrška za Profile (Aco je veseo, Aco je depresivan, Snjeg pada vani i Aci je milo) bi svakako dobro došla.

Kroz ovaj priority queue prođu svi.


from heapq import heappush, heappop
import datetime

DOBRO, VALJA, JEBENO  = 0, 1, 2
NECE, HOCE = False, True
MUSKO, ZENSKO = False, True

ACINE_GODINE  = datetime.date.today().year-1976
FAKTOR_GODINA = -20

acin_um = {"vrckast":  lambda val: -2,
           "stan":     lambda val: val == True and -10 or 1,
           "auto":     lambda val: val == True and -5 or 0,
           "star":     lambda val: round(abs(ACINE_GODINE-val)/100.0*FAKTOR_GODINA),
           "wii":      lambda val: val == True and -5 or 0,
           "udan":     lambda val: val == True and 10 or 0,
           "zauzet":   lambda val: 2,
           "spol":     lambda val: val == True and -10 or 0,
           "ima_maca": lambda val: 0,
           "sise":     lambda val: (-2,-5,-10)[val],
           "guza":     lambda val: (-2,-5,-10)[val]
           }

def create_prijatelj(name, **kw):
    return (reduce(lambda a, b: a+b, map(lambda opc: acin_um[opc](kw[opc]) , kw.keys())), name)

potencijalni = []

heappush(potencijalni, create_prijatelj("osoba jedan",
                                        sise    = JEBENO,
                                        guza    = VALJA,
                                        stan    = False,
                                        vrckast = True)
         )

# itd.. itd... itd..

heappush(potencijalni, create_prijatelj("osoba n",
                                        wii     = HOCE,
                                        udan    = True
                                        )
         )

print "* drum roll *"
print "Najbolji kandidat za acinog novog prijatelja je: ", heappop(potencijalni)[1]
 

Tags:

Goran Zec protiv blogova osovine

Sat, 10/04/2008 - 11:00 | 8 comments

Ograda

Znači ovo je samo šala i ja znam da mi Goran neće ništa zamjeriti a za sourceove odskrolajte preko prvih par paragrafa...

Kako je sve počelo

Pojavio se novi super heroj u gradu i kako stvari trenutno stoje to nije "Aco Pretnja"! Postoji neka anketa http://www.galoviceva-jesen.com/blog.asp za najbolji blog (što god). Veseli i razdragani kandidati latili su se svojih web 2.0 social siteova i počeli nagovarati svoje vjerne čitatelje da im podare koji glas. Sad tu stvari postaju malo zanimljivije. Kako je bilo i sa onim srednjoškolskim demonstracijama i ovaj put je facebook napravio sranje!

Kao što se na ovom screenshotu friendfeeda vidi Rusulica je koristeći twitter svojim vjernim subscriberima poslala link gdje mogu za nju glasati. Oni naravno kreću sa klikanjem! Priznajem, i ja sam dao svoj glas. Vjerni sam čitatelj rusuličinih tekstova, subscriber videa na youtubeu i njenog emo streama na last.fm-u. Anywho, Goran kuži.... Goran nije od jučer i on je odmah pokušao u svojem Firefoxu isključiti kolačiće ne bi li podario koji glas više našoj Rusulici. To mu na kraju i uspjeva ali jedna mu stvar upada u oči. Glasovi za Srđana se povećavaju prevelikom brzinom!

Prosječna brzina klikanja

Goran je u tom biznisu dosta dugo i on zna da PBK (prosječna brzina klikanja) ne može biti ovako velika. Kao Power user Firefoxa (koji ima nekih 30-etak pluginova instaliranih na sistemu) on uzima iMacro i zadaje nizove komandi svojem Firefoxu da automatizira sam proces klikanja. Nabija Rusulici dodatnih 1300 bodova..... Ajmo Rusulica!

Izmjerimo mu glavu!

Tko je taj Srđan i kad je on postao osovina blogova (očigledno aludirajući na Bushove osovine zla)? Srki je "gel velike glave" koji honorari za 12 kuna u leglu NGO mafije. Bogu troši dane surfajući na desku, piše blog, chata na silnim IM-ovima, dopisuje se preko Facebooka. Isto kao i Rusulica pozvao je svoje frendove preko Facebooka da glasaju za njega.

A očeš ti glaaaasati za mene

Tu se sad dešava nekoliko stvari. Srki je dok se to sve počelo zahuktavati radio u m.a.m.i. Radio u m.a.m.i. koja je u tom trenutku bila prepuna "gelova" istih kao i on koji su došli na jedno od događanja na "Queer Zagreb" koje se dešavalo u mami. Mnogi od njih poznaju Srkija i mnogi od njih su na njegov nagovor prošetali do kompa i kliknuli jednom za Srkija. Isto tako, Srki je svim svojim online (znači 100 najmanje) prijateljima rekao da glasaju za njega. Sigurno je otišao i na brojne dating siteove da proširi vijest o svojem nebeskom uspjehu sa glasanjem a ne bi se začudio ni da je iskoristio službeni telefon u mami da pozove sve svoje kontakte u adresaru i uputi ih na časni čin glasanja! Pravi aktivizam na djelu. Da se toliko trudio kad su Teu trebali glasovi za "Pravo na grad" ne bi sada bilo radova na cvjetnome.

Što učini!

Uvijek sam ja govorio da će nas pederi doći glave, ali me malo ljudi sluša. U svakom slučaju, Srkijevi discipliniraniji poznanici učinili su svoje. Nekome je taj mali skok u glasovima mogao značiti samo jednu stvar. Neko hakira! Postanje svoje gole ženske guzice na blog je dobar način da ti ljudi prate blog ali katkada i nedovoljan razlog da se toliko okupe oko neke online ankete.... Anywho, Goran je napuco 1300 glasova, onda su drugi koji su skužili njegovu nečasnu rabotu napucali ostalim isto toliko glasova a sad Goran u maniri drugog razreda srednje škole i dalje uvjeren u bjelosvjetsku blog zavjeru napucava Rusulici dodatne tisuće i tisuće glasova..... O Crni Gorane! ŠTO UČINI CRNI GORANE!

Što bi...

Kao netko tko je u svom životu radio ovakve sustave za procesiranje online anketa (i sličnih online stvari) moram priznati da je ovaj problem zaslužio da se o njemu malo kaže riječ dvije.

Recimo da se radi o nagradnoj igri i recimo da je jako bitno da se pokuša napraviti nagradna igra ili nekakvo glasanje što je moguće regularnije. Osloniti se samo na cookije nije dovoljno. Koji god ASP-eaš je radio ovu nagradnu igru koju je Goran unakazio učinio je katastrofalnu grešku. Ok, možda na Internet Exploreru treba klikati po nekim ne toliko dostupnim mjestima u opcijama pa za to ljudi i ne znaju ali isključiti podršku za cookije je brz način za glasanje u nedogled. Napisati kratku skriptu koja će to raditi za vas je još lakše.

Ako se proba napraviti ograničenje "jedan glas == jedan IP" dolazi se do problema "što sa ljudima iz npr. nekog cyber caffea". Što sa 3 člana obitelji koji bi preko lokalnog internet providera htjeli odvojeno glasati. U našem slučaju bi to značilo da Srki iz maminog cyber caffea (čitaj mjesta gdje honorari) može dobiti samo jedan glas. To definitivno nije dobro. Da sam ja radio
anketu na http://www.galoviceva-jesen.com/blog.asp definitivno bih stavio ograničenje da sa jednog IP-a u određenog vremenskom intervalu može doći određen broj glasova. Znači: glaso si sad pa možeš opet za n minuta ali isto tako ne možeš sa tog IP-a baš da mi glasaš 100 puta u zadnjih m sati. S obzirom da sam i ja honorario u mamu taj mamin IP prema van i glasanje visoko pozicioniranih džabalabatora mi je ostalo u pamćenju :)

Naravno, to ovisi i od konkretne situacije. Ako je broj hitova na site 5 u sekundi i svi glasaju za istu stvar više je nego očigledno da netko fakea. Tako da se isplati ograničiti broj glasova za određeni item (sa svim IP-eva). Koliki? Ovisi od konkretne situacije.

Da ja sad moram napraviti neko glasanje osim svega ovoga stavio bih definitivno i jedan Captcha. To definitivno otjera away jeftine pokušaje fakeanja ali na žalost ne štiti ništa od "ako ti je stvarno stalo daš $50 dolara indijcima i oni klikću cijeli dan".

A kako bih ovo

Da sam se želio baviti ovom rabotom i ovom konkretnom anketom radio bih to ovako. Ovo nije ništa komplicirano i ne zahtjeva neko prčkanje sa Firebugom pa bih zato samo otišao na stranicu i pogledao source. Fino kaže da radi POST methodu na url /anketa/default.asp?act=1&pid=4. Radi se neka nebitna validacija na onSubmit. Postoje tri "radio buttona" koji se zove answer. Moguće vrijednosti su "11", "12", "13". Pogrešno je stavljeno da su svi "checked" što znači u ovom slučaju da je Rusuličin blog automatski selektiran kao defaultni. Pa ako radite svoje ankete pazite da ne radite ovakve greške.


<form name="frmpoll" id="frmpoll" method="post" action="/anketa/default.asp?act=1&pid=4" onsubmit="javascript: return PollVoteFormValidate();"><b>Ocjenite najbolji blog</b><ul id="answers" class="ulist"><li><input name="answer" checked type="radio" value="11" />Garden of Arcane Delights</li><li><input name="answer" checked type="radio" value="12" />Prodaja Ega-Hiperinflacija emocija by "Srdjan Sandic"</li><li><input name="answer" checked type="radio" value="13" />Rusulica</li></ul><input type="submit" class="button" title="glasaj" value="glasaj" /><br/><a href="/anketa/default.asp?pid=4">rezultati</a><br/>glasalo je <strong>10527</strong> osobaglasanje do: <b>10.10.2008</b></form>
 

Ja nisam haker pa ne bih koristio neke pluginove već bi to zdravo seljački napisao npr. ovako:


wget --no-cookies --post-data 'answer=11' "http://www.galoviceva-jesen.com/anketa/default.asp?act=1&pid=4"
 

Gornja linija onom trećem blogu koji se ni kriv ni dužan našao ovdje napucava dodatne glasove. Stavite to u neku petlju, pokrenite na nekoliko različitih kompjutera u isto vrijeme i vojla!

Ok.. a sad, što bi bilo kad bi bilo da su ovi npr. kontrolirali da sa jednog IP-a može samo jedan glas ili da može samo n glasova u sat vremena....

Ima nekoliko načina kako se ovo može izvesti ali evo jedan brutalno banalan. Njegova velika prednost je što možete kontrolirati s kojih adresa ćete napadati. Jer ako se radi o glasanju za hrvatski blog godine lako se shvati da 1000 glasova iz Kazahstana pomalo smrdi.

Znači tajna je u anonimnim HTTP proxijima. Odite na google i skinite si neku od aktualnih listi proxija. Nekih 1000 recimo i skopirajte si u ovu skriptu.


import os, random
SERVERI = """218.249.12.133:8080       anonymous proxy Oct-03, 14:49   China
88.191.60.104:3128      anonymous       Oct-03, 14:46   France
... itd itd itd ..."""
LISTA = [x.split("\t")[0] for x in SERVERI.split("\n")]
n = 0
# daj 100 glasova nabij
while n < 100:
    # daj mi random proxy iz cijele liste
    proxy_server = random.choice(LISTA)
    # slozi wget komandu
    #  - postavi http proxy
    #  - neka snima output u /dev/null
    #  - neka timeouta nakon 10 sekundi
    #  - u slucaju timeouta ne pokusavaj ponovo
    #  - ne koristi cookije
    #  - postaj datea koji daje dodatni glas onom prvom
    #    bezveznom blogu
    wget_command = "http_proxy=\"%s\" wget -O /dev/null --timeout=10 --tries=1 --no-cookies --post-data 'answer=11' \"http://www.galoviceva-jesen.com/anketa/default.asp?act=1&pid=4\" " % proxy_server
    result = os.system(wget_command)
    # brisi sa liste poznatih proxy servera
    # ako je timeoutao
    if result != 0:
        LISTA.remove(proxy_server)
        print "Removing ", proxy_server, " from the list."
    else:
        n += 1
 

Ne može biti jednostavnije. Ono što se isplati napraviti je npr. pobacati listu ovih proxya u neku sqlite bazu. Jer sad nakon svakog pokretanja on pokušava
sve http proxy-e iz početka. Staviti u bazi, staviti potencijalnu pauzu između svakog slanja, staviti da jedan proxy može koristi svakih n minuta, staviti da različiti procesi mogu (znači pokreneš 100 puta) pristupati tim podacima i eto ti silnih glasova iz svih država naše lijepe Europe.

Jedna od stvari na koju treba obratiti pažnju je nešto što se zove concurrency iliti istodobnost. Vašoj online aplikaciji (recimo glasanje) može u isto vrijeme pristupiti nekoliko korisnika. Ono što treba obratiti pažnju je na sve te resource koji se međusobno shareaju među različitim sessionima. Normalno to i nije veliki problem jer site ima 5 hitova na dan pa se to i ne primjeti ali kad stavite beskonačnu petlju i 5 procesa koji napadaju site u isto vrijeme ako je neki džabalabator pisao skripte (jer skripte se danas copy pasteaju sa weba i tutoriala, to svi znaju) mogli bi njegov mili uradak staviti na muke.

Kao što se vidi na slici, zamislite da u isto vrijeme dvije osobe dođu na web stranice i da glasaju. Skripta za glasanje uzima broj dosadašnjih glasova. Uvećava ga za jedan i sprema u bazu novu vrijednost. Na gornjoj slici vrijednost u bazi bi na kraju trebala biti 7 ali bit će 6. Problemi sa resoursima koji se dijele se pokazuju u zavisnosti od konkretne situacije ali kod web aplikacija to su obično rad s i samim podacima u bazi podataka ili u datotekama na datotečnom sustavu. U našem slučaju se upiše kriva vrijednost ali ono što se isto vrlo lako može desiti su svakojaki exceptioni kod pristupa već otvorenim ili zalokanim resourcima. Pa vi dajte malo vašoj skripti timeouta ne bi li skriptice sa druge strane dobile malo vremena da dišu....

Eto... toliko od Ace Pretnje.

Reinteract je najnoviji igrač na sceni Python shellova (uz IPython, hotwire-shell i možda još pokoji).



Bilo je samo pitanje vremena kad će netko ponovo otkriti stare ideje i razveseliti gomile python freakova. Cijela stvar je bazirana na GTK bindingsima za python i u principu omogućuje da (kao što se vidi i na gornjoj slici) embedate GTK widgete u Reinteract shell. Istina, gornji primjer embedanja TreeView-a sa listom fileova i nije baš nešto što će čovjeka potaknuti da kaže "wooooooowwww" ali treba uzeti u obzir da je ovo poprilično svjež projekat (danas izašao ako se ne varam). Zato, odite na site, skinite source i napišite nove maštovitije widgete. Meni iskreno rečeno pada par na pamet.

Naravno, Reinteract je dosta dobar i zbog toga što vam omogućuje da se vratite na prijašnje komande, modificirate ih i automatski refreshate operacije koje su se desile nakon. Kratko se igrajući sa cijelim sustavom meni se učinilo dosta korisno i to što možete unositi nekoliko linija python codea i onda ih sve evaulirati odjednom. Obojani kvadratići na početku linije vam omogućuju da raspoznate evaulirani code, code sa greškom te code koji se još nije evaulirao.

Uspio sam uhvatiti tek nekoliko minuta da se poigram s njim (što će reći da nisam ni stigao da pogledam kako sve to izgleda iznutra i da sam više potrošio vremena na pisanje ovog posta nego na samo igranje sa Reinteractom) ali nadam se da me cijela stvar u budućnosti neće previše razočarati te ćete na www.binarni.net moći pronaći neka moja proširenja istoga.