IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

scanf sur "method SP request-target SP HTTP-version CRLF"


Sujet :

C

  1. #1
    Candidat au Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Août 2016
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Août 2016
    Messages : 6
    Points : 4
    Points
    4
    Par défaut scanf sur "method SP request-target SP HTTP-version CRLF"
    Bonjour je suis en plein devoir et je n'arrive pas à comprendre où j'ai faux. Si qqn pourrait me donner une piste, Merci. LE tout compile, mais ne fonctionne pas comme espéré. C'est une fonction dans un programme server.c Mais lors des test ma fonction ne réagit pas comme elle devrait. JE pense que ça vient du scanf que j'ai mal implementé. Un conseil?


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
     
    /**
     * Parses a request-line, storing its absolute-path at abs_path 
     * and its query string at query, both of which are assumed
     * to be at least of length LimitRequestLine + 1.
     */
    bool parse(const char* line, char* abs_path, char* query)
    {
     
        char* temp;
        temp = malloc((LimitRequestLine+1)*sizeof(char*));
     
        char* method;
        method = malloc((LimitRequestLine+1)*sizeof(char*));
     
        abs_path = malloc((LimitRequestLine+1)*sizeof(char*));
     
        query = malloc((LimitRequestLine+1)*sizeof(char*));
     
        char* protocol;
        protocol = malloc((LimitRequestLine+1)*sizeof(char*));
        sscanf(temp, "%s %s?%s %s" , method, abs_path, query, protocol);
     
         for ( int i=0 ; i < strlen(method); i++)
        {
            if (method[i] == "GET"[i])
            {
                respond(405, "405 Method Not Allowed", "405 Method Not Allowed\n", sizeof("405 Method Not Allowed\n"));
                return false;
            }
        }
     
     
        if (abs_path[0] != '/')
        {
            respond(400, "400 Bad Request", "400 Bad Request\n", sizeof("400 Bad Request\n"));
            return false;
        }
     
        for ( int i=0 ; i < strlen(query); i++)
        {
            if (query[i] == '"')
            {
                respond(400, "400 Bad Request", "400 Bad Request\n", sizeof("400 Bad Request\n"));
                return false;
            }
        }
     
        for (int i =0 ; i < 8 ; i++)
        {
            if (protocol[i] != "HTTP/1.1"[i])
            {
                respond(505, "505 HTTP Version Not Supported\n", "505 HTTP Version Not Supported\n", sizeof("505 HTTP Version Not Supported\n"));
                return false;
            }
        }
     
        return true;
    }

  2. #2
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 823
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 823
    Points : 7 119
    Points
    7 119
    Par défaut
    Je dirais que si tu alloues de la mémoire sans penser la libérer, et faire cela assez souvent, tu risques d'avoir des problèmes...
    Le fait d'allouer et de ne pas initialiser en est un autre !

    Peux-tu donner un exemple de ligne à parser, perso si c'est ce que je pense, j'utiliserai la librairie string.h !

    Pour comparer les méthodes j'utiliserai strcmp
    Pour découper la request-line et ses espaces j'utiliserai strtok, mais sscanf semble aussi une bonne idée.
    Pour séparer le Host, plusieurs solutions sont possibles, mais pourquoi pas strstr
    ...

    Au final j'utiliserai une structure de données contenant l'ensemble des chaînes de caractères représentant la ligne à parser, la request-line.
    Dans cette situation, l'utilisation de l'allocation dynamique me semble pas forcément la seule possible, la statique pour ce genre de travail suffit amplement.

    J'espère t'avoir déjà aiguillé un peu.

    EDIT: J'ai eu un peu de temps, voilà comment je voyais la forme de résolution à ta problématique

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    typedef struct{
     
        char method[32];
        char URI[256];
        char protocol[32];
     
    } RequestLine;
     
    RequestLine *init(const char *request);
     
    int main(void){
     
        const char *request_line = "GET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.1";
     
        RequestLine *result = init(request_line);
     
        if (result != NULL){
            printf("method: %s\npath: %s\nprotocol: %s", result->method, result->URI, result->protocol);
            free(result); /* libération de la mémoire allouée */
        }
     
        return 0;
    }
     
    RequestLine *init(const char *request){
     
        int res;
        RequestLine *line = malloc(sizeof(RequestLine));
        if (line == NULL) return line;
     
     
     
        res = sscanf(request, "%s %s %s", line->method, line->URI, line->protocol);
     
        if (res < 3 || res == EOF){
            line->method[0] = '\0';
            line->URI[0] = '\0';
            line->protocol[0] = '\0';
        }
     
        return line;
    }
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  3. #3
    Candidat au Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Août 2016
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Août 2016
    Messages : 6
    Points : 4
    Points
    4
    Par défaut
    Merci,

    tout est beaucoup plus clair et structuré. C'est ce que je cherchais à faire.
    J'avais complétement zappé les free. Excellent rappel.
    Je vais pouvoir m'attaquer à la suite.

    MErci

    Max

  4. #4
    Candidat au Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Août 2016
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Août 2016
    Messages : 6
    Points : 4
    Points
    4
    Par défaut
    Du coup, apres avoir déclaré les déf et le fonctions et le prototype, mon code donne ça.
    Mais j'ai toujours faux. mes tests foirent et je ne suis pas sûr de modifier abs_path et query.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
     
    bool parse(const char* line, char* abs_path, char* query)
    {
         RequestLine *result = init(line);
     
         for ( int i=0 ; i < strlen(result->method); i++)
        {
            if (result->method[i] == "GET"[i])
            {
                respond(405, "405 Method Not Allowed", "405 Method Not Allowed", sizeof("405 Method Not Allowed"));
                return false;
            }
        }
     
     
        if (result->URI[0] != '/')
        {
            respond(400, "400 Bad Request", "400 Bad Request", sizeof("400 Bad Request"));
            return false;
        }
     
        for ( int i=0 ; i < strlen(result->URI); i++)
        {
            if (result->URI[i] == '"')
            {
                respond(400, "400 Bad Request", "400 Bad Request", sizeof("400 Bad Request"));
                return false;
            }
        }
     
        for (int i =0 ; i < 8 ; i++)
        {
            if (result->protocol[i] != "HTTP/1.1"[i])
            {
                respond(505, "505 HTTP Version Not Supported", "505 HTTP Version Not Supported", sizeof("505 HTTP Version Not Supported"));
                return false;
            }
        }
        query = strstr(result->URI,"?");
        strncpy(abs_path, result->URI, strlen(result->URI)-strlen(query));
     
        free(result);
        return true;
    }

  5. #5
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 823
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 823
    Points : 7 119
    Points
    7 119
    Par défaut
    Ok, alors plusieurs questions

    1) On aurait pu prendre en argument de ta fonction d'analyse, y a-t-il une raison de ne pas le faire ?

    Voir une chose du style

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    bool parse(RequestLine *req){
     
     
        /* suite du code */
     
    }
    2) Après je vois respond, une fonction dont je ne vois pas à quoi elle correspond... elle correspond donc à ? Si c'est un affichage, on peut peut-être éviter cette fonction en transformant cette fonction parse par un prototype du style ci-dessous.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void parse(RequestLine *req);
    Et placer nos printf ou mieux: puts

    3) Pourquoi s'évertuer à comparer deux chaînes de caractères de la sorte ? La fonction strcmp évite bien des lignes de code.

    4) Que doit faire exactement la fonction parse ? J'ai l'impression qu'elle ne fait pas le travail qu'elle devrait faire.
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  6. #6
    Candidat au Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Août 2016
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Août 2016
    Messages : 6
    Points : 4
    Points
    4
    Par défaut
    1)Ben en fait j'ai des contraintes et ne peux toucher les définitions qui me sont données. ça doit marcher avec le reste du code.


    2) Quant à respond, elle est dans le source que je dois compléter. Elle etait faite et n'ai pas le droit de la modifier.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
     
    /**
     * Responds to a client with status code, headers, and body of specified length.
     */
    void respond(int code, const char* headers, const char* body, size_t length)
    {
        // determine Status-Line's phrase
        // http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1
        const char* phrase = reason(code);
        if (phrase == NULL)
        {
            return;
        }
     
        // respond with Status-Line
        if (dprintf(cfd, "HTTP/1.1 %i %s\r\n", code, phrase) < 0)
        {
            return;
        }
     
        // respond with headers
        if (dprintf(cfd, "%s", headers) < 0)
        {
            return;
        }
     
        // respond with CRLF
        if (dprintf(cfd, "\r\n") < 0)
        {
            return;
        }
     
        // respond with body
        if (write(cfd, body, length) == -1)
        {
            return;
        }
     
        // log response line
        if (code == 200)
        {
            // green
            printf("\033[32m");
        }
        else
        {
            // red
            printf("\033[33m");
        }
        printf("HTTP/1.1 %i %s", code, phrase);
        printf("\033[39m\n");
    }
    3) J'ai compris et je modifie.

    4)pour le parse, mes ordres sont :

    Complete the implementation of parse in such a way that the function parses (i.e., iterates over) line, extracting its absolute-path and query and storing them at abs_path and query, respectively.
    Here’s how.

    abs_path
    Per 3.1.1 of http://tools.ietf.org/html/rfc7230, a request-line is defined as

    method SP request-target SP HTTP-version CRLF
    wherein SP represents a single space ( ) and CRLF represents \r\n. None of method, request-target, and HTTP-version, meanwhile, may contain SP.

    Per 5.3 of the same RFC, request-target, meanwhile, can take several forms, the only one of which your server needs to support is

    absolute-path [ "?" query ]
    whereby absolute-path (which will not contain ?) must start with / and might optionally be followed by a ? followed by a query, which may not contain ".

    Ensure that request-line (which is passed into parse as line) is consistent with these rules. If it is not, respond to the browser with 400 Bad Request and return false.

    Even if request-line is consistent with these rules,

    if method is not GET, respond to the browser with 405 Method Not Allowed and return false;

    if request-target does not begin with /, respond to the browser with 501 Not Implemented and return false;

    if request-target contains a ", respond to the browser with 400 Bad Request and return false;

    if HTTP-version is not HTTP/1.1, respond to the browser with 505 HTTP Version Not Supported and return false; or

    Odds are you’ll find functions like strchr, strcpy, strncmp, strncpy, and/or strstr of help!

    If all is well, store absolute-path at the address in abs_path (which was also passed into parse as an argument). You may assume that the memory to which abs_path points will be at least of length LimitRequestLine + 1.

    C'est un peu touffou, mais au moins c'est précis.

  7. #7
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 823
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 823
    Points : 7 119
    Points
    7 119
    Par défaut
    Ce que je trouve pas cohérent, c'est qu'une request-line ressemble à ci-dessous

    Hors c'est correct d'écrire http://www.w3.org/pub/WWW/TheProject.html, l'abs_path devrait être parsé pour avoir ce résultat : /pub/WWW/TheProject.html

    À moins qu'il soit déjà analysé ailleurs ? Et si ce n'est pas le cas, il faudra analyser cette ligne (voir ci-dessous) !

    extracting its absolute-path and query and storing them at abs_path and query
    Difficile de reprendre un projet déjà bien avancé

    EDIT: J'ai des doutes du coup sur l'intérêt d'une structure... Avec les indications, je débuterai le code comme ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    #include <stdio.h>
    #include <string.h>
    #include <stdbool.h>
     
    bool parse(const char* line, char* abs_path, char* query);
     
    int main(void){
     
        const char *request_line = "GET http://www.w3.org/pub/WWW/TheProject.html HTTP/1.1";
     
        char path[256] = {0};
        char q[32] = {0};
        bool result = parse(request_line, path, q);
     
        printf("%s", result ? "true" : "false");
     
        return 0;
    }
     
    bool parse(const char* line, char* abs_path, char* query){
     
        char method[32] = {0};
        char URI[256] = {0};
        char protocol[32] = {0};
     
        int res;
        res = sscanf(line, "%s %s %s", method, URI, protocol);
     
        if (res < 3 || res == EOF){
            method[0] = '\0';
            URI[0] = '\0';
            protocol[0] = '\0';
        }
     
        if (strcmp(method, "GET") == 0){
            puts("405 Method Not Allowed");
            return false;
        }
     
        if (strcmp(protocol, "HTTP/1.1") == 0){
            puts("505 HTTP Version Not Supported");
            return false;
        }
     
        /* analyse de line pour trouver abs_path et query */
     
        char *p = strstr(line, "http://");
        if (p == NULL && line[0] == '/'){
            strncpy(abs_path, line, strlen(abs_path));
            return true;
        }
     
        if (p == NULL && line[0] != '/'){
            puts("400 Bad Request");
            return false;
        }
     
        /* analyser pour trouver le query */
        /* analyser pour trouver le host et déterminer abs_path */
     
        /* etc */
     
        return true;
    }
    Au lieu des puts, tu mets ta fonction respond, après j'aide plus, sinon je fais ton boulot

    Bonne continuation...
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  8. #8
    Candidat au Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Août 2016
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux

    Informations forums :
    Inscription : Août 2016
    Messages : 6
    Points : 4
    Points
    4
    Par défaut
    Tu m'as déjà beaucoup aidé. Et aidé à mieux cerner comment travailler avec C, en mettant le doigt sur de grosses erreurs. je t'en remercie. En plus je me rends compte quils nous orientent pas forcément vers la solution la plus simple.

    Merci pour tout.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. des difficultés sur des methodes
    Par bambi98 dans le forum UML
    Réponses: 4
    Dernier message: 12/12/2006, 09h32
  2. Réponses: 2
    Dernier message: 20/10/2006, 15h07
  3. Pb sur la methode waitFor depuis un jar
    Par martin_o dans le forum Général Java
    Réponses: 3
    Dernier message: 06/04/2006, 17h34
  4. Pointeur sur une methode d'une classe
    Par Pe04 dans le forum C++
    Réponses: 2
    Dernier message: 02/03/2006, 13h29
  5. [VBA-E] Question sur la méthode "SaveAs"
    Par Flateric dans le forum Macros et VBA Excel
    Réponses: 7
    Dernier message: 25/04/2005, 14h18

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo