C - стрток и стркмп

У меня возникли проблемы с использованием strtok с strcmp.

//Handles the header sent by the browser
char* handleHeader(char *header){
        //Method given by browser (will only take GET, POST, and HEAD)
        char *method,*path, *httpVer;

        method = (char*)malloc(strlen(header)+1);
        strcpy(method,header);
        method = strtok(method," ");


        path = strtok(NULL," ");
        httpVer = strtok(NULL, " ");
        printf("\nMethod: %s\nPath: %s\nHTTP: %s\n",method,path,httpVer);


        printf("\nc1: %d\nc2: %d\n",strcmp(httpVer,"HTTP/1.0"),strcmp(httpVer,"HTTP/1.1"));

        if(!(!strcmp(httpVer,"HTTP/1.0") || (!strcmp(httpVer,"HTTP/1.1")))){
                printf("\ngive a 400 error\n");
                return "400 foo";
        }


        if(!strcmp(method,"GET")){
                //char *path = strtok(NULL," ");

                //If they request the root file, change the path to index.html
                if(!strcmp(path,"/")){
                        path = (char*)malloc(strlen(BASE_DIR) + strlen("/index.html")+1);
                        strcpy(path,"/index.html");
                }
                 return readPage(path,2);
        }
}

Если я дам ему следующий заголовок

GET / HTTP/1.0

Я получаю этот вывод:

Method: GET
Path: /
HTTP: HTTP/1.0


c1: 1
c2: -1

give a 400 error

Как видите, strtok() правильно анализирует строку, но значения c1 и c2 не имеют смысла (c1 должен возвращать 0, но вместо этого возвращает 1).

Что тут происходит?


person Señor Reginold Francis    schedule 19.09.2009    source источник


Ответы (4)


Я предполагаю, что вы не даете ему это:

GET / HTTP/1.0

а скорее вот это:

GET / HTTP/1.0\n

или, возможно, это:

GET / HTTP/1.0\r\n

Глядя на ваш код, между строкой вывода «HTTP» и строкой «c1» должна быть одна пустая строка, но у вас их две, что означает, что само значение «HTTP» содержит новую строку.

Выведите несколько кавычек вокруг значений — держу пари, вы видите это:

HTTP: "HTTP/1.0
"
person RichieHindle    schedule 19.09.2009
comment
Только что подумал об этом. @ Steven1350, попробуйте strstr вместо strcmp, чтобы увидеть, произойдет ли это. - person Zed; 20.09.2009
comment
Заменив strcmp на strstr, я получил следующее, c1:163160734 c2:0 - person Señor Reginold Francis; 20.09.2009
comment
Тот факт, что c1 не равен нулю, означает, что строка HTTP/1.0 появляется внутри httpVer. - person RichieHindle; 20.09.2009
comment
Вы правы, в конце HTTP/1.0 есть \n. Спасибо, вроде работает. - person Señor Reginold Francis; 20.09.2009
comment
Поскольку strstr() возвращает адрес, с которого в токене начинается строка (HTTP/1.0), это считается успешным, и диагноз RichieHindle верен. - person Jonathan Leffler; 20.09.2009

Как вы можете видеть из пустых строк в вашем выводе (и как уже сказали несколько человек), в конце вашего HTTP/1.0 есть управляющие символы. Вы можете исправить это.

Но почему вы пишете новый парсер HTTP-запросов на C? Это 2009 год! Их уже существует множество, некоторые из них даже правильны, многие из них лицензированы. И даже если вам по какой-то причине нужно написать свой собственный, вы должны использовать безопасный язык (Python, Java, Lua, C#, Perl, что-то), чтобы в случае тривиальной ошибки при подсчете символов , вы не столкнетесь с большой дырой в безопасности вашей программы. (И даже если вам каким-то образом придется использовать C, strtok — особенно вопиющая функция C.)

person Kragen Javier Sitaker    schedule 19.09.2009

Судя по вашему выводу, в конце строки HTTP/1.0 может быть «/n»? Ричи слишком быстр для меня ;)

Попробуйте обрезать/удалить все пробелы во входной строке перед ее токенизацией.

person simon    schedule 19.09.2009

Попробуйте использовать

strncmp(httpVer, "HTTP/1.0", 8)

так что вы игнорируете завершающие пробелы.

person Karl Voigtland    schedule 19.09.2009
comment
strncmp() будет сравнивать только указанное количество символов. Так что это должно работать до тех пор, пока вы не заинтересованы в том, чтобы что-то могло быть после «1.0». - person Karl Voigtland; 20.09.2009