Autor Zpráva
Prefin
Profil
Ahojda všichni.
Prosím o radu co dělám špatně či o zdroj informací v cz.
Píšu script na vygenerování textu placené SMS (Airtoy). Přesně však nevím, jak si poradit s požadavkem na odpověď která má být HTTP 200 OK, musí být text/plain a obsahovat content-lenght.
Příklad odpovědi: Vas pristupovy kod je ASBCDE;1.
Po ověření potřebných věcí vypisuju tohle:
$zprava_OK = "Vas kod je ".$kod.";1";
Header("HTTP/1.1 200 OK");
Header("Content-type: text/plain");
header("Content-Length: ".strlen($zprava_OK));
echo $zprava_OK;
Odpověď testovacího scriptu je ale:
Content-Type: text/html
Content-Length: 3
HTTP Status code: 200
Odpověď serveru: 

Ve zpracování se nic nevypisuje (echo), za začátku stránky mám ob_start().

Moc díky za radu.

Celý scriptík (je tam balast která ještě odstraním):
<?php
ob_start();
include "sql_pripojeni.php";
if($HTTP_SERVER_VARS["REMOTE_ADDR"]!="195.47.87.164" or $HTTP_SERVER_VARS["REMOTE_ADDR"]!="193.86.73.148") {
    exit();
} else {
    // Zjištění zda jde o volání na základě zaslání SMS
    if(isset($_GET["phone"]) and isset($_GET["sms"]) and isset($_GET["ts"]) and isset($_GET["uid"]) and isset($_GET["sc"]) and isset($_GET["o"])) {
        // Kontrola tvaru zaslané SMS a tel. čísla pro zasílání SMS
        /*$v = mysql_fetch_assoc(mysql_query("SELECT * FROM nastaveni_sms WHERE id_nastaveni_sms='1'"));
        if(($_GET["sms"])!=$v["text_nastaveni_sms"]) {
            Header("HTTP/1.1 204 NO_CONTENT");
            exit;
        }
        if($_GET["sc"]!=$v["cislo_nastaveni_sms"]) {
            Header("HTTP/1.1 204 NO_CONTENT");
            exit;
        }*/
        // Vygenerování kodu pro SMS
        $kod = rand(1,9).rand(1,9).rand(1,9).rand(1,9).rand(1,9).rand(1,9).rand(1,9).rand(1,9);
        // Uložení záznamu o vygenerovaném kódu do tabulky s informacemi o generovaných a ověřených SMS
        if(mysql_query("INSERT INTO sms VALUES ('','".$kod."','".$_GET["phone"]."','0','".$_GET["ts"]."','".$_GET["uid"]."','".$_GET["sms"]."','','0')")) {
            // Odeslání odpovědi
            $zprava_OK = "Vas kod je ".$kod.";1";
            Header("HTTP/1.1 200 OK");
            Header("Content-type: text/plain");
            header("Content-Length: ".strlen($zprava_OK));
            echo $zprava_OK;
            /*exit;*/
        }
    } elseif(isset($_GET["ds"]) and isset($_GET["dt"])) { // Zjištění zda volání je doručení statusu zprávy
        // Návratové hodnoty ds - status
        $ds["DELIVERED"] = "SMS byla doručena";
        $ds["UNDELIVERED"] = "SMS nebyla a nebude doručena";
        $ds["WAITING"] = "SMS čeká na doručení";
        $ds["PENDING"] = "SMS je nevyřízena (dojde k jejímu pozdějšímu vyřízení)";
        $ds["UNKNOWN"] = "Stav SMS není možné zjistit";
        $ds["EXPIRED"] = "Platnost SMS vypršela (již nedojde k jejímu doručení)";
        // Návratové hodnoty dm - zpráva
        $dm["INTERNAL_ERROR"] = "Vnitřní chyba operátora";
        $dm["NOT_ENOUGHT_CREDIT"] = "Uživatel nemá dostatečný kredit";
        $dm["SERVICE_NOT_ALLOWED"] = "Uživatel má blokovanou službu PREMIUM SMS";
        $dm["NO_OPERATOR_CUSTOMER"] = "Uživatel není zákazníkem operátora, ke kterému byla SMS zaslána";
        $dm["USAGE_RATE_EXCEEDED"] = "Uživatel překročil povolený limit svého účtu";
        $dm["MT_SERVICE_NOT_ALLOWED"] = "Uživatel má blokované MT biling zprávy";
        $dm["CUSTOMER_IS_BLOCKED"] = "Uživatel je operátorem blokován";
        $dm["DAILY_LIMIT_EXCEEDED"] = "Uživatel překročil denní limit pro platby PR SMS";
        $dm["UNKNOWN"] = "Důvod nedoručení je neznámý";
        $dm["USER_BLACKLISTED"] = "Uživatel je operátorem blokován pro nehrazení služeb";
        $status = $_GET["ds"];
        $zprava = $_GET["dm"];
        // Uložení statusu do db
        // Tvar záznamu v buňce status_sms: Doručena/Nedoručena;pokud ne tak dúvod;čas doručení; číslo doručenky; Request ID
        $sql = "UPDATE sms SET ";
        if($status == "UNDELIVERED") {
            $sql .= "status_sms='".$ds[$status].";".$dm[$zprava].";".$_GET["dt"].";".$_GET["dn"].";".$_GET["rid"]."'";
        } else {
            $sql .= "status_sms='".$ds[$status].";;".$_GET["dt"].";".$_GET["dn"].";".$_GET["rid"]."',overeni_sms='1'";
        }
        $sql .= " WHERE ident_airtoy_sms='".$_GET["rid"]."'";
        //echo $sql;
        @mysql_query($sql);
        exit;
    } else { // Nebyly předány všechny parametry
        Header("HTTP/1.1 204 NO_CONTENT");
        Header("Content-type: text/plain");
        exit;
    }
}

?>
Majkl578
Profil
Ty tři podivné znaky na výstupu jsou BOM.
Seš si jistý, že se ti to dostane do bloku, kde předpokládáš výstup? Dále na prvni pohled (kromě nepřehledného kódu náchylného k SQL injection) vidím ob_start, ale už nikde nevidím ob_flush/ob_end_flush.
Davex
Profil
Majkl578:
nikde nevidím ob_flush/ob_end_flush
Není nutné je používat. Obsah bufferu se odešle při ukončení skriptu.

Prefin:
V závislosti na verzi a nastavení PHP nemusí existovat pole $HTTP_SERVER_VARS. V nových PHP verzích vydaných za posledních 10 let by se mělo používat pole $_SERVER.
Prefin
Profil
Já nejsem žádný programátor, jenom si stavím sám co potřebuju protože mě to baví.
Injection ještě spravím, to by bylo při GETu fakt blbý.
Fakt je, že s tím co jsem popsal nemám žádné zkušenosti.
Takže zkusím prohodit $_SERVER za $HTTP_SERVER_VARS (už jsem to párkrát dělal a vždycky se zase nachytám) a zkusím co to provede.
Co se týče odpovědi serveru, tak je to v podstatě status (?), který se pošle volané stránce v HTTP. Pak by se měly vypsat důležité hlavičky a poté text.
Je to tedy takhle správně?
Header("HTTP/1.1 200 OK");
Header("Content-type: text/plain");
Header("Content-Length: ".strlen($zprava_OK));
echo $zprava_OK;
Díky
Amunak
Profil
Pokud vím, content-length většina serverů posílá automaticky, nemusíš to dělat ručně. To samé platí pro kód 200. Co se týče content-type, je v pořádku. A ano, hlavičky obsahují různé info o serveru, vlastnostech obsahu a tak.
Prefin
Profil
Amunak:
Pokud vím, content-length většina serverů posílá automaticky, nemusíš to dělat ručně. To samé platí pro kód 200. Co se týče content-type, je v pořádku. A ano, hlavičky obsahují různé info o serveru, vlastnostech obsahu a tak.

Znamená to tedy že by stačilo:
$zprava_OK = "Vas pristupovy kod je ASBCDE;1";
echo $zprava_OK;
aby se vrátilo:

Content-Type: text/plain
Content-Length: (pocet znaků $zprava_OK)
HTTP Status code: 200
Odpověď serveru: Vas pristupovy kod je ASBCDE;1

Dík
Amunak
Profil
Prefin:
Stačí prakticky něco jako
header('Content-Type: text/plain');
echo 'Vas kod je '.$kod.';1';

Ale můžeš použít třeba i něco jako
header('Content-Type: text/plain; charset=UTF-8');
echo 'Váš kód je '.$kod.';1';


A jinak nevím proč máš na konci zprávy ten středník a jedničku, ale uživatele by to mohlo mást. Udělej to tak, ať to nevypadá jako součást kódu.

Hlavičky si můžeš i sám prohlížet - použij FireBug (ve FF) nebo ve chrome klikni na stránku pravým, pak zkontrolovat prvek. Potom vyber kartu network a tam si rozklikni první položku (stránku). Vpravo uvidíš request i response hlavičky.
Prefin
Profil
Moc díky za info. Strávil bych na tom týden než bych to pochopil (možná).
Ta jednička na konci zprávy je přesně podle požadovaného formátu - Airtoy tak má označen cenový level (lze měnit podle typu služby). Ke klientovi se odešle pouze to co je před středníkem.


Pomohlo to, odpověď je správná.
Teď zase musím zjistit jak správně poslat 204, protože
Header("HTTP/1.1 204 NO_CONTENT");
odpoví pořád stejně
Content-Type: text/html 
Content-Length: 3 
HTTP Status code: 200 
Odpověď serveru: 
Amunak
Profil
Prefin:
protože tam pořád ještě máš BOM. Zkontroluj, jestli .php souboty opravdu ukládáš v UTF-8 a ideálně si v editoru vypni vkládání BOM. Pak všechny soubory "přeulož" ať to zmizí. PHP má prostě někdy problém když na BOM narazí, takže se dějí různé nepředvídatelné věci. Jinak na té hlavičce není nic špatného.
Prefin
Profil
No to je, ale nevím proč. Zásadně všechno dělám v utf-8 a BOM mám vypnutý, s tím jsem se vycukal už dřív při jiné situaci.
Fakt je, že dělám v interním editoru Krusaderu (Linux).
Zkusím to přehodit do woken a prověřit v pspadu.
Mimo to, přestože se pokusím vypsat 204, pošle to 200.
Prefin
Profil
Ještě bych požádal o drobnost.
Dočetl jsem se, že 204 NO_CONTENT odpoví server vždy, když neprovede žádnou akci - tedy neodešle žádnou odpověď.
To znamená, že běh scriptu skončí bez bez výpisu.
Musím v takovém případě upravovat hlavičky pomocí header()? Záleží na Content-type?
Protože odpověď serveru je i v tomto případě pořád 200.
Keeehi
Profil
http://web-sniffer.net/ je pro vás velmi užitečný nástroj.
Prefin
Profil
Moc díky. Bezva věc.
Ale pořád nevím, proč mi server posílá i při nevypisování ničeho 200.
Nebo co musím udělat aby odpověď byla 204.
Díky
Keeehi
Profil
Řekl bych, že
header("HTTP/1.1 204 No Content");
by mělo stačit i když jsem to nezkoušel.
Prefin
Profil
No právě že ne.
Když vypíšu
header("HTTP/1.1 204 No Content");
header('Content-Type: text/plain; charset=UTF-8');
exit;
Tak je odpověď:
Chybný navrácený content-type. Musí být text/plain
Chybný navrácený content-length. Musí být uveden a větší 0.
Chybný formát odpovědi Vašeho serveru.
Neplatný navrácený status kód. Musí být 200 nebo 204.

Takže to rozhodí veškeré serverem posílané hlavičky.
Když odstraním header("HTTP/1.1 204 No Content");
Tak je vše v pořádku, jenom to vrací pořád 200.

Asi si z toho už šlehnu.
Keeehi
Profil
Prefin:
Spíš by bylo dobré říct, ukazuje web-sniffer. Ten totiž řekne co bylo doopravdy vráceno a ne jen co by mělo být vráceno.

Na
<?php
header("HTTP/1.1 204 No Content");
header('Content-Type: text/plain; charset=UTF-8');
exit;
To mně vrací:
Status:          HTTP/1.1 204 No Content
Date:            Sat, 25 Aug 2012 09:40:14 GMT    
Server:          Apache    
Content-Length:  0    
Connection:      close    
Content-Type:    text/plain; charset=UTF-8
Což vypadá jako to co chcete.
Prefin
Profil
To je pravda.
Když pošlu dotaz z web-snifferu na toto:
<?php
header("HTTP/1.1 204 No Content");
header('Content-Type: text/plain; charset=UTF-8');
exit;
?>
Ale když to pošlu na svůj script tak to vrátí nesmysl i když větvením scriptu se vrátí to samé:
 .............
} else {
    header("HTTP/1.1 204 No Content");
    header('Content-Type: text/plain; charset=UTF-8');
    exit;
}
To by tedy mohlo asi znamenat, že se tam něco někde vypisuje ještě dřív?
Proč to tedy odešle v případě úspěchu všechno správně.

Konkrétně:
Správné volání scriptu je s těmito parametry
?phone=6e11b2559c9360d23d7d0b4481d1132b&sms=KPP+499&ts=2012-08-25T12%3A04%3A42&uid=134&o=TM_CZ&sc=90333&t=1

Chybné když v sms je něco jiného než KPP+(499/399/299) nebo chybí parametry apod.
Tahle validace je ok, nicméně nevrací to 204 ani na web-snaffu.
Tady je script:
ob_start();
include "sql_pripojeni.php";
include "funkce.php";
// Kontrola IP
if($_SERVER["REMOTE_ADDR"]=="195.86.73.148") { // Testovací adresa Airtoy
    $x = 1;
} else {
    $ip = explode(".",$_SERVER["REMOTE_ADDR"]); // Běžný rozsah ip Airtoy
    if($ip[0]=="195" and $ip[1]=="47" and $ip[2]=="87" and $ip[3]>="160" and $ip[3]<="191") $x = 1;
}

if($x!=1) { // Konec při nesprávné ip
    ZapisDoLogu("!!!! Pokus o vygenerování kódu k SMS z nepovolené IP adresy: ".$_SERVER["REMOTE_ADDR"].",");
    exit();
} else {
    // Zjištění zda jde o volání na základě zaslání SMS
    if($_GET["phone"]!="" and $_GET["sms"]!="" and $_GET["ts"]!="" and $_GET["uid"]!="" and $_GET["sc"]!="") {
        // kontrola zaslaného textu sms
        $text = substr($_GET["sms"],-3);
        if(strlen($_GET["sms"])==7 and ($text=="299" or $text=="399" or $text=="499")) {
            // Vygenerování kodu pro SMS
            $kod = rand(1,9).rand(1,9).rand(1,9).rand(1,9).rand(1,9).rand(1,9).rand(1,9).rand(1,9);
            // Uložení záznamu o vygenerovaném kódu do tabulky s informacemi o generovaných a ověřených SMS
            if(mysql_query("INSERT INTO sms VALUES ('','".$kod."','".$_GET["phone"]."','0','".$_GET["ts"]."','".$_GET["uid"]."','".$_GET["sms"]."','','0')")) {
                // Nastavení cenových levelů
                $level[299] = "37";$level[399] = "34";$level[499] = "36";
                // Odeslání odpovědi
                $zprava_OK = "Vas kod je ".$kod.";".$level[$text];
                header('Content-Type: text/plain; charset=UTF-8');
                echo $zprava_OK;
                exit;
            }
        } else {
            header("HTTP/1.1 204 No Content");
            header('Content-Type: text/plain; charset=UTF-8');
            exit;
        }
    } elseif($_GET["ds"]!="") { // Zjištění zda volání je doručení statusu zprávy
        // Návratové hodnoty ds - status
        $ds["DELIVERED"] = "SMS byla doručena";
        $ds["UNDELIVERED"] = "SMS nebyla a nebude doručena";
        $ds["WAITING"] = "SMS čeká na doručení";
        $ds["PENDING"] = "SMS je nevyřízena (dojde k jejímu pozdějšímu vyřízení)";
        $ds["UNKNOWN"] = "Stav SMS není možné zjistit";
        $ds["EXPIRED"] = "Platnost SMS vypršela (již nedojde k jejímu doručení)";
        // Návratové hodnoty dm - zpráva
        $dm["INTERNAL_ERROR"] = "Vnitřní chyba operátora";
        $dm["NOT_ENOUGHT_CREDIT"] = "Uživatel nemá dostatečný kredit";
        $dm["SERVICE_NOT_ALLOWED"] = "Uživatel má blokovanou službu PREMIUM SMS";
        $dm["NO_OPERATOR_CUSTOMER"] = "Uživatel není zákazníkem operátora, ke kterému byla SMS zaslána";
        $dm["USAGE_RATE_EXCEEDED"] = "Uživatel překročil povolený limit svého účtu";
        $dm["MT_SERVICE_NOT_ALLOWED"] = "Uživatel má blokované MT biling zprávy";
        $dm["CUSTOMER_IS_BLOCKED"] = "Uživatel je operátorem blokován";
        $dm["DAILY_LIMIT_EXCEEDED"] = "Uživatel překročil denní limit pro platby PR SMS";
        $dm["UNKNOWN"] = "Důvod nedoručení je neznámý";
        $dm["USER_BLACKLISTED"] = "Uživatel je operátorem blokován pro nehrazení služeb";
        $status = $_GET["ds"];
        $zprava = $_GET["dm"];
        // Uložení statusu do db
        // Tvar záznamu v buňce status_sms: Doručena/Nedoručena;pokud ne tak dúvod;čas doručení; číslo doručenky; Request ID
        $sql = "UPDATE sms SET ";
        if($status == "UNDELIVERED") {
            $sql .= "status_sms='".$ds[$status].";".$dm[$zprava].";".$_GET["dt"].";".$_GET["dn"].";".$_GET["rid"]."'";
        } else {
            $sql .= "status_sms='".$ds[$status].";;".$_GET["dt"].";".$_GET["dn"].";".$_GET["rid"]."'";
        }
        if($status == "DELIVERED") $sql .= ",overeni_sms='1'";
        $sql .= " WHERE ident_airtoy_sms='".$_GET["rid"]."'";
        //echo $sql;
        @mysql_query($sql);
        exit;
    } else { // Nebyly předány všechny parametry
        header('Content-Type: text/plain; charset=UTF-8');
        exit;
    }
}
Keeehi
Profil
zkuste vynechat ob_start()
Prefin
Profil
To jsem už zkoušel.
Když ho vynechám, tak to pošle BOM:
Vas kod je 87926922;36
a server nepošle lenght, tudíž zase blbě a to i správné volání.
Kód je v utf-8 a ukládání BOM mám vypnuté.
Keeehi
Profil
Bom může být i v těch includovaných scriptech.
Mike8748
Profil
Prefin:
hlavně je třeba znovu vytvořit (tím nemyslim uložit) ten soubor. jak už v něm jednou BOM je, tak vypnutí vkládání v editoru nepomůže (pokud tam BOM je tak ji editor sám od sebe nevymaže)
Keeehi
Profil
Mike8748:
jak už v něm jednou BOM je, tak vypnutí vkládání v editoru nepomůže
Toto nemusí být pravda. Například PSPad BOM aktivně maže.
Prefin
Profil
Už jsem na to přišel a jako vždy - chyba je mezi židlí a klávesnicí.
Žádné vypisování před hlavičkou, žádný BOM jenom moje blbost.
1. Když jsem to testoval z web-snifferu tak jsem zapoměl povolit další ip takže mi to padalo do větve, kde jsem ještě header(...204) neměl.
2. Testovací script Airtoy asi neumí validovat odpovědi jiné než 200 - povolenou chybu 204 označuje pravděpodobně za chybný status. Takže to pořád mátlo ze dvou stran, přitom to běží správně.
Díky za pomoc.

Vaše odpověď

Mohlo by se hodit

Odkud se sem odkazuje


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: