Internet Info, s.r.o. Lupa Měšec Podnikatel Root Zdroják DigiZone Slunečnice Vitalia TopDrive KupDnes Navrcholu NovýTarif Dobrý web Weblogy Woko Jagg Computer.cz SK: MojeLinky

Hlavní navigace

PHP okénko: Eurotel SMS

Třetí díl PHP okénka na konkrétním příkladě odesílání SMS zpráv ukazuje, jak lze využít nové, nepříliš známé vlastnosti PHP 5 pro práci s kontextem a funkce PHP pro práci s obrázky.

Tweetni to Twitter Jaggni to! Jagg Del.icio.us Delicious

Eurotel má na svých stránkách SMS bránu sloužící k posílání esemesek zdarma. Brána je kvůli případnému zneužití chráněna jednoduchým Turingovým testem – uživatel musí opsat text ze zobrazeného obrázku. Já bránu zneužívat nehodlám, ale otravuje mě opisování textu z obrázku a navíc na něj často zapomínám. Proto jsem si napsal skriptík, který text z obrázku opíše za mě.

Nejprve si ujasněme, jak celé rozhraní funguje:

  1. Při přístupu na stránku SMS brány se nastaví cookie.
  2. Na základě této cookie se stáhne obrázek.
  3. Při odeslání zprávy metodou POST se podle cookie ověří, jestli byl zadán správný kód.

Z toho plyne, že na vyřešení úkolu budeme potřebovat tři schopnosti: přijímat a odesílat cookies, odesílat formulářová data metodou POST a zpracovávat obrázky. S využitím funkce fsockopen se první dva problémy dají se znalostí protokolu HTTP vyřešit i v PHP 4, mnohem pohodlnější řešení ale nabízí PHP 5 díky podpoře kontextů. Načrtněme si tedy, jak bude kód vypadat:

<?php
/** poslání SMS na Eurotel
@param int $cislo devítimístné telefonní číslo
@param string $zprava text zprávy dlouhý maximálně 60 znaků
@return void vypíše stránku s informací o výsledku
*/
function eurotel_sms($cislo, $zprava)
{
    // získání cookies
    $fp = fopen("http://www2.eurotel.cz/sms/SMSGWChargingClient?action=edit&lang=cs", "r");
    $cookies = array();
    $meta_data = stream_get_meta_data($fp);
    foreach ($meta_data["wrapper_data"] as $val) {
        if (preg_match('~Set-Cookie: ([^;]+)~i', $val, $matches)) {
            $cookies[] = $matches[1];
        }
    }
    fclose($fp);
    $context = stream_context_create(array('http' => array('header' => "Cookie: " . implode("; ", $cookies) . "\r\n")));

    // získání obrázku
    $soubor = tempnam($_ENV["TEMP"], "eurotel");
    $obrazek = file_get_contents("http://www2.eurotel.cz/sms/SMSGWChargingClient?action=image", false, $context);
    file_put_contents($soubor, $obrazek);
    $code = eurotel_code($soubor);
    unlink($soubor);

    // potvrzení zprávy
    $content = array(
        "action=confirm", "reply=0", "replyEmail=", "intruder=0", "lang=cs",
        "ccndc=". urlencode("+420") . substr($cislo, 0, 3),
        "sn=" . substr($cislo, 3),
        "code=$code",
        "msgText=". urlencode($zprava),
    );
    $context_post = $context;
    stream_context_set_option($context_post, 'http', 'method', 'POST');
    stream_context_set_option($context_post, 'http', 'content', implode("&", $content));
    $fp = fopen("http://www2.eurotel.cz/sms/SMSGWChargingClient", "r", false, $context_post);
    fclose($fp);

    // odeslání zprávy
    readfile("http://www2.eurotel.cz/sms/SMSGWChargingClient?action=send&lang=cs", false, $context);
}
?> 

V kódu je použito hned několik zajímavých funkcí: stream_get_me­ta_data, stream_contex­t_create nebo tempnam. Hlavním obratem je ale využití dalších parametrů u běžných funkcí fopen, file_get_contents a readfile.

K implementaci zbývá funkce eurotel_code, která přeloží obrázek na řetězec. Univerzální řešení by samozřejmě bylo přes OCR, to ale není úplně jednoduché. Protože brána používá pouze omezenou množinu znaků, přišlo mi jednodušší si je vyzobat do souboru a jako zdroj pro překlad používat tento soubor. abeceda.png tedy obsahuje všechny používané znaky – nejprve čísla, pak písmena. Funkce eurotel_code načte tento soubor do jednotlivých znaků a následně načte obrázek s kódem a hledá v něm jednotlivé znaky.

TIB2012

       
<?php
/** překlad kontrolního obrázku služby Eurotel SMS na text
@param string $image název souboru s obrázkem
@return string kontrolní kód
*/
function eurotel_code($image)
{
    $chars = array();
    $im = imagecreatefrompng("abeceda.png");
    for ($index=0; $index < 36; $index++) {
        $pixels = array();
        for ($x=0; $x < 8; $x++) {
            for ($y=0; $y < 15; $y++) {
                $pixels[$x][$y] = imagecolorat($im, $x + 8*$index, $y);
            }
        }
        $chars[$index] = $pixels;
    }
    imagedestroy($im);

    $return = "";
    $im = imagecreatefromgif($image);
    for ($index=0; $index < 5; $index++) {
        $pixels = array();
        for ($x=0; $x < 8; $x++) {
            for ($y=0; $y < 15; $y++) {
                $pixels[$x][$y] = imagecolorat($im, $x + 8*$index, $y);
            }
        }
        $i = array_search($pixels, $chars);
        $return .= ($i < 10 ? $i : chr($i - 10 + ord('a')));
    }
    imagedestroy($im);

    return $return;
}
?> 

K celkové funkčnosti uvedeného kódu chybí již jen soubor abeceda.png. Nezlobte se na mě, že ho nedám volně k dispozici, přeci jen si nemohu být jist tím, že by to někdo nezneužil pro nevyžádané rozesílání zpráv. Jako příklad ne zcela tradičního využití PHP ale příklad myslím posloužil dobře.


Podobně laděné texty můžete najít i na autorově weblogu PHP triky.

Jakub Vrána

Jakub Vrána

Autor se živí programováním v PHP, podílí se na jeho oficiální dokumentaci, vyučuje ho na MFF UK a vede odborná školení. Poznámky si zapisuje na weblog PHP triky.

Školení: GIT správce zdrojových kódů

 

Seznamte se s možnosti systému správy verzí zdrojových kódů GIT, který používají i vývojáři linuxového jádra.

  • Proč správa verzí
  • Architektura GITu
  • GIT v praxi
  • a další

Podrobnější informace o školení a přihláška

Ohodnoťte jako ve škole:
Průměrná známka 2,98

Přehled názorů

Uz zas neco propagujete?
L$D 4. 4. 2005 01:14
Nový
pěkné
Fanda 4. 4. 2005 08:24
Nový
├ 
Re: pěkné
dogmatix 4. 4. 2005 08:50
Nový
└ 
Re: pěkné
shMoula 4. 4. 2005 09:12
Nový
jste bůh
martin 4. 4. 2005 08:46
Nový
├ 
Re: jste bůh
NaiL 4. 4. 2005 13:54
Nový
└ 
Re: jste bůh
Deda Jabko 4. 4. 2005 15:02
Nový
nápad super
Lukoko 4. 4. 2005 09:26
Nový
└ 
Re: nápad super
HKMaly 4. 4. 2005 17:07
Nový
naivita
paranoiq 4. 4. 2005 10:46
Nový
Kdy to změní
Tex 4. 4. 2005 10:47
Nový
├ 
Re: Kdy to změní
acidofil 4. 4. 2005 12:35
Nový
│
└ 
Re: Kdy to změní
petr_p 4. 4. 2005 14:16
Nový
└ 
Re: Kdy to změní
Pinky 4. 4. 2005 15:40
Nový
 
└ 
Re: Kdy to změní
Milan Kvasnica 9. 4. 2005 00:18
Nový
 
 
└ 
Re: Kdy to změní
Tex 3. 5. 2005 12:07
Nový
Každý názor musí mít titulek.
Vac 4. 4. 2005 13:19
Nový
└ 
Re: Každý názor musí mít titulek.
HKMaly 4. 4. 2005 22:48
Nový
 
└ 
Re: Každý názor musí mít titulek.
Vac 4. 4. 2005 23:43
Nový
 
 
├ 
Re: Každý názor musí mít titulek.
HKMaly 5. 4. 2005 01:10
Nový
 
 
│
└ 
Re: Každý názor musí mít titulek.
Pavel Zbytovský 5. 4. 2005 20:28
Nový
 
 
│
 
└ 
Re: Každý názor musí mít titulek.
HKMaly 6. 4. 2005 15:14
Nový
 
 
│
 
 
└ 
Re: Každý názor musí mít titulek.
Hever 12. 4. 2005 11:24
Nový
 
 
│
 
 
 
├ 
Re: Každý názor musí mít titulek.
Hever 12. 4. 2005 11:25
Nový
 
 
│
 
 
 
└ 
Re: Každý názor musí mít titulek.
HKMaly 12. 4. 2005 14:08
Nový
 
 
│
 
 
 
 
└ 
Re: Každý názor musí mít titulek.
Hever 13. 4. 2005 22:55
Nový
 
 
└ 
Re: Každý názor musí mít titulek.
+420608116277 4. 5. 2005 11:26
Nový
maji ruzne uvozovky nejaky vyznam ?
teddy 4. 4. 2005 18:13
Nový
└ 
Re: maji ruzne uvozovky nejaky vyznam ?
martin 4. 4. 2005 20:32
Nový
Snazsi reseni ?
Indigo 4. 4. 2005 23:12
Nový
Pěkné ..
Hever 4. 4. 2005 23:24
Nový
└ 
Re: Pěkné ..
608116277 4. 5. 2005 11:29
Nový
Vrána je vtipálek
Nailen 13. 4. 2005 11:59
Nový
TOHLE NENAPSAL INTELIGENTI CLOVEK
xxx 14. 4. 2005 15:00
Nový
├ 
Re: TOHLE NENAPSAL INTELIGENTI CLOVEK
Jakub Vrána 14. 4. 2005 15:08
Nový
│
└ 
Re: TOHLE NENAPSAL INTELIGENTI CLOVEK
xxx 15. 4. 2005 16:19
Nový
└ 
Re: TOHLE NENAPSAL INTELIGENTI CLOVEK
lim 14. 4. 2005 17:50
Nový
uvolnenie obrazku abeceda.png?
jakub 3. 7. 2007 13:18
Nový
       

Tento text je již více než dva měsíce starý. Chcete-li na něj reagovat v diskusi, pravděpodobně vám již nikdo neodpoví. Pro řešení aktuálních problémů doporučujeme využít naše diskusní fórum.

Zasílat nově přidané příspěvky e-mailem