Hlavní navigace

PHP okénko: Eurotel SMS

Jakub Vrána

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.

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.

<?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.

Našli jste v článku chybu?

4. 4. 2005 9:26

Lukoko (neregistrovaný)
Je to fakt dobry napad a samotnyho by me to nenapadlo, ale preci jenom ziskavani dat z webu pres fopen (priznavam ze o stream_get_meta_data() jsem do dneska nevedel) mi prijde takove nedokonale. Uz dlouho na takovedle veci pouzivam cURL a nemuzi si stezovat. Jaky je vas nazor na cURL?
Lupa.cz: Proč firmy málo chrání data? Chovají se logicky

Proč firmy málo chrání data? Chovají se logicky

Vitalia.cz: 7 druhů hotových těst na vánoční cukroví

7 druhů hotových těst na vánoční cukroví

Vitalia.cz: Láska na vozíku: Přitažliví jsme pro tzv. pečovatelky

Láska na vozíku: Přitažliví jsme pro tzv. pečovatelky

Podnikatel.cz: Přehledná titulka, průvodci, responzivita

Přehledná titulka, průvodci, responzivita

Lupa.cz: Kdo pochopí vtip, může jít do ČT vyvíjet weby

Kdo pochopí vtip, může jít do ČT vyvíjet weby

Podnikatel.cz: Udávání kvůli EET začalo

Udávání kvůli EET začalo

Lupa.cz: Co se dá měřit přes Internet věcí

Co se dá měřit přes Internet věcí

Podnikatel.cz: K EET. Štamgast už peníze na stole nenechá

K EET. Štamgast už peníze na stole nenechá

Lupa.cz: Teletext je „internetem hipsterů“

Teletext je „internetem hipsterů“

Měšec.cz: Zdravotní a sociální pojištění 2017: Připlatíte

Zdravotní a sociální pojištění 2017: Připlatíte

Měšec.cz: Jak vymáhat výživné zadarmo?

Jak vymáhat výživné zadarmo?

Měšec.cz: U levneELEKTRO.cz už reklamaci nevyřídíte

U levneELEKTRO.cz už reklamaci nevyřídíte

120na80.cz: Na ucho teplý, nebo studený obklad?

Na ucho teplý, nebo studený obklad?

Podnikatel.cz: Chaos u EET pokračuje. Jsou tu další návrhy

Chaos u EET pokračuje. Jsou tu další návrhy

Měšec.cz: mBank cenzuruje, zrušila mFórum

mBank cenzuruje, zrušila mFórum

DigiZone.cz: Rádio Šlágr má licenci pro digi vysílání

Rádio Šlágr má licenci pro digi vysílání

Vitalia.cz: 9 největších mýtů o mase

9 největších mýtů o mase

DigiZone.cz: ČRa DVB-T2 ověřeno: Hisense a Sencor

ČRa DVB-T2 ověřeno: Hisense a Sencor

Vitalia.cz: Spor o mortadelu: podle Lidlu falšovaná nebyla

Spor o mortadelu: podle Lidlu falšovaná nebyla

Vitalia.cz: Proč vás každý zubař posílá na dentální hygienu

Proč vás každý zubař posílá na dentální hygienu