Partage
  • Partager sur Facebook
  • Partager sur Twitter

Regex et PDU en héxadecimale

    25 mai 2018 à 8:49:32

    Bonjour à tous,

    J'ai une chaîne de caractère qui ressemble à celle-ci :

    Il y a donc bien plusieurs espaces au début, des caractères regroupés hexa (bien qu'ils ne sont pas considérés en tant que tel) deux par deux, et leur interprétation ensuite  : .../.... ......

    Et il faudrait que je puisse obtenir ceci :

    Comme vous l'avez remarqué, c'est le contenu d'un paquet SMPP (son PDU donc).

    Je voudrais donc récupérer les caractères qui sont par deux par deux (chiffres et lettres majuscules) précédés d'un espace, dans un premier temps. J'ai donc pensé à la regex suivante :

    " \\[[:alnum:][:alnum:]]{1}"

    Le problème étant que, je ne suis pas même sûr de celle-ci et j'ai vraiment des doutes sur comment m'en servir...

    Merci d'avance pour vos suggestions :)

    -
    Edité par Endast 25 mai 2018 à 16:44:37

    • Partager sur Facebook
    • Partager sur Twitter
      25 mai 2018 à 9:16:13

      Salut,

      L'image n'est pas passée :/ essaie de modifier le lien ou de passer par un autre moyen de partage d'image via url

      • Partager sur Facebook
      • Partager sur Twitter
      Hugo
        25 mai 2018 à 9:39:40

        Salut, tiens c'est bizarre, peut-être parce que je suis l'auteur du topic mais je les vois bien. Il y a deux images. Je viens de vérifier avec un autre compte sur openclassroom, c'est bon aussi
        • Partager sur Facebook
        • Partager sur Twitter
          25 mai 2018 à 9:45:40

          Je ne vois pas non plus les images.

          Edit: J'ai essayé d'afficher l'image depuis le code source et celle-ci est liée a ton compte Google. Nous n'avons pas les droits.

          -
          Edité par thetui 25 mai 2018 à 9:52:13

          • Partager sur Facebook
          • Partager sur Twitter
            25 mai 2018 à 16:43:49

            Oops, au temps pour moi dans ce cas. J'ai modifié, ça devrait être ok :)
            • Partager sur Facebook
            • Partager sur Twitter
              28 mai 2018 à 10:56:05

              Re,

              Quel moteur de Regex est-ce que tu utilises ? Je n'ai jamais vu de chose comme [:alnum:] :/

              Je te propose celle-ci sinon : /([\d|A-F]{2} )/g pour avoir chaque couple de nombre. Tu peux la tester ici. Après il faut encore trouver un moyen d'appliquer cette expression dans le langage que tu veux et en obtenir le résultat pour le stocker dans ton tableau.

              Edit : Explications rapide de la regex.

              • /..../g délimite la regex et spécifie qu'elle s'appliquera à l'ensemble du texte qui lui sera soumis.
              • /(.....)/g spécifie que tout se qui correspondra à la regex dans les parenthèses sera "selctionner", on aura un résultat différé pour chaque occurence/sélection.
              • /([...|...])/g demande de trouver ou bien l'élément de droite, ou bien celui de gauche
              • /([...|...]{2})/g demande de trouver 2 fois ce patterne (puisqu'on a 2 nombre qui se suivent)
              • /([\d|...]{2})/g "\d" correspond à "n'importe quel chiffre"
              • /([\d|A-F]{2})/g cherche les lettre de A à F (majuscule seulement)

              -
              Edité par Insonore 28 mai 2018 à 11:08:30

              • Partager sur Facebook
              • Partager sur Twitter
              Hugo
                29 mai 2018 à 11:06:47

                Salut, c'est top, merci beaucoup.


                Tu n'as jamais vu un truc pareil, pour une raison très très simple, le tuto que j'ai suivi pour écrire cela date de .... 2005, je viens tout juste de m'en rendre compte, j'aurais du checker avant. Je ne savais même pas qu'il existait des moteurs de regex, je le saurais à l'avenir !

                D'ailleurs, tu parles de l'appliquer à ma chaîne, justement, je voudrais le faire en C. Mais il semble que les tuto pour le faire en C ne sont pas légions.  Tu aurais une explication à ce "phénomène" ?

                • Partager sur Facebook
                • Partager sur Twitter
                  29 mai 2018 à 11:38:47

                  Les expressions regulières ne sont pas gérées par le C ANSI. Mais il existe la bibliothèque PCRE qui utilise la meme syntaxe que ce que t'as donné @Indolore.
                  • Partager sur Facebook
                  • Partager sur Twitter
                    7 juin 2018 à 4:32:05

                    Bonjour,  je reviens ici pour poster un début de solution et donner suite au thread.

                    Après avoir regardé la bibliothèque PCRE et les regex classiques et après beaucoup beaucoup de manipulations, je suis arrivé à ce code (en regex classique) :

                    //pdu_connection est une chaîne vide qui va récupérer le résultat
                    //pdu contient une chaine comme ça :
                    /*    00 00 00 2F 00 00 00 09   00 00 00 00 00 00 00 01   .../.... ........
                       73 6D 70 70 63 6C 69 65   6E 74 31 00 70 61 73 73   smppclie nt1.pass
                       77 6F 72 64 00 27 56 4D   41 27 00 34 00 00 00      word.'VM A'.4...*/
                    
                    
                    void pdu_to_hex(char *pdu_connection, char *pdu){
                    
                    	int err;
                    	regex_t preg;
                    	const char *str_request = pdu;
                    	const char *str_regex = "([0-9|A-F]{2} )";
                       
                    	char *result = malloc(100 * sizeof(char));
                    	memset(result, '\0', sizeof(result));
                    
                    	int j=0;
                    
                    	while(strcmp(&str_request[j], "\0")){		
                    		char current[4];
                    		memset(&current, '\0', sizeof(current)); 
                    		current[0] = str_request[j];
                    		current[1] = str_request[j+1];
                    		current[2] = str_request[j+2];
                    		printf("La chaine courante est :%s;\n",current);
                    		printf("j = %d\n",j);
                    		j++;
                    			
                    		err = regcomp (&preg, str_regex, REG_EXTENDED);
                    		if (err == 0)
                    		{
                    			int match;
                    		    size_t nmatch = 0;
                    		    regmatch_t *pmatch = NULL;
                    		      
                    		    nmatch = preg.re_nsub;
                    		    pmatch = malloc (sizeof (*pmatch) * nmatch);
                    		    if (pmatch)
                    		    {
                    				match = regexec (&preg, current, nmatch, pmatch, 0);
                    		        regfree (&preg);
                    		         if (match == 0)
                    		         {
                    		            char *hex = NULL;
                    		            int start = pmatch[0].rm_so;
                    		            int end = pmatch[0].rm_eo;
                    		            size_t size = end - start;
                    		               
                    		            hex = malloc (sizeof (*hex) * (size + 1));
                    		            if (hex)
                    		            {
                    		               strncpy (hex, &current[start], size);
                    		               hex[size] = '\0';
                    		               printf ("%s matched\n", hex);
                    		               strcat(pdu_connection, "\\x");
                    		               strncat(pdu_connection, hex, 2);
                    		               printf("Le resultat concatene est :%s\n\n",pdu_connection);
                    		               free (hex);
                    		            }
                    		         }
                    		         else if (match == REG_NOMATCH)
                    		         {
                    		            printf ("%s ne correspond a deux caracteres hex + un espace\n\n", current);
                    		         }
                    		         else
                    		         {
                    					char *text;
                    		            size_t size;
                    		            size = regerror (err, &preg, NULL, 0);
                    		            text = malloc (sizeof (*text) * size);
                    		            if (text)
                    		            {
                    		               regerror (err, &preg, text, size);
                    		               fprintf (stderr, "%s\n", text);
                    		               free (text);
                    		            }
                    		            else
                    		            {
                    		               fprintf (stderr, "Memoire insuffisante\n");
                    		               exit (EXIT_FAILURE);
                    		            }
                    		         }
                    		      }
                    		      else
                    		      {
                    		         fprintf (stderr, "Memoire insuffisante\n");
                    		         exit (EXIT_FAILURE);
                    		      }
                    		   }
                    		}
                    }

                    J'arrive donc bien à récupérer ma chaîne (c'est juste l'affichage dans un terminal) :

                    pdu_connection :\x00\x00\x00\x2F\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x01\x73\x6D\x70\x70\x63\x6C\x69\x65\x6E\x74\x31\x00\x70\x61\x73\x73\x77\x6F\x72\x64\x00\x27\x56\x4D\x41\x27\x00\x34\x00\x00\x00
                    

                    Le seul souci c'est quand je l'envoie, voilà ce que ma trame contient réellement :

                    En gros j'ai l'impression que la chaine que j'envoie est interprété comme de l'ascii et non comme de l'héxa. Alors que quand j'envoie cette chaîne précisément déclaré comme tel en C :

                    char BindTransceiver[] = "\x00\x00\x00\x2F\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x01\x73\x6D\x70\x70\x63\x6C\x69\x65\x6E\x74\x31\x00\x70\x61\x73\x73\x77\x6F\x72\x64\x00\x27\x56\x4D\x41\x27\x00\x34\x00\x00\x00";

                    ça fonctionne parfaitement :




                    Franchement j'ai essayé pas mal de choses, je dois avoir un problème de format quelque part, mais là je sèche...

                    Merci d'avance.

                    EDIT : le problème se trouve précisément à cet endroit-là selon moi dans la fonction pdu_to_hex

                    strcat(pdu_connection, "\\x");
                    strncat(pdu_connection, hex, 2);

                    Parce que j'ajoute \x comme étant des caractères basiques et non comme étant une représentation hexadécimale de ce qui va suivre.

                    En pseudo-code, il faudrait que je fasse :

                    Concaténer à pdu_connection : '\x' ET hex. Mais de même je sèche toujours....

                    -
                    Edité par Endast 7 juin 2018 à 6:33:21

                    • Partager sur Facebook
                    • Partager sur Twitter
                      7 juin 2018 à 10:52:25

                      Salut,

                      Je n'ai pas bien saisi quel est le nouveau problème. Tu nous montres ce que la trame contient au moment de l'envoi, mais qu'est-ce qui est faux dedans ? à quoi tu t'attends par rapport à ce qu'elle contient ?

                      -
                      Edité par Insonore 7 juin 2018 à 10:52:55

                      • Partager sur Facebook
                      • Partager sur Twitter
                      Hugo
                        7 juin 2018 à 11:01:09

                        En fait, dans ma nouvelle trame, ceci donc :

                        pdu_connection :\x00\x00\x00\x2F\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x01\x73\x6D\x70\x70\x63\x6C\x69\x65\x6E\x74\x31\x00\x70\x61\x73\x73\x77\x6F\x72\x64\x00\x27\x56\x4D\x41\x27\x00\x34\x00\x00\x00

                        Les \x sont également formatés comme caractères et ne servent donc pas indiquer que les deux caractères qui suivent sont en hexa.

                        Au lieu de les interpréter comme '\x', ils sont interprétés comme "\x".

                        Le contenu de la trame n'est pas faux et c'est donc bien tous les caractères que je veux, ils ne sont juste pas au bon format. Et je suis quasiment sûr que ça vient d'ici :

                        strcat(pdu_connection, "\\x");

                        Mais je vois vraiment pas comment je pourrais faire autrement pour lui indiquer héxa et non char.

                        • Partager sur Facebook
                        • Partager sur Twitter
                          7 juin 2018 à 11:09:16

                          La questiion est, en quoi ca te gene?

                          Q'est-ce que ca t'empeches de faire par la suite?

                          • Partager sur Facebook
                          • Partager sur Twitter
                            7 juin 2018 à 11:20:12

                            Le souci est que, quand cette chaine passe dans une socket TCP, elle est pour le réseau composée des caractères suivants :

                            \ puis x puis 0 puis 0 etc...   C'est de l'ASCII pour le réseau, comme le montre la première capture Wireshark plus haut.

                            La pile réseau prend chacun des caractères et le programme qui le reçoit en bout de chaîne reçoit donc l'équivalent hexadécimale de chacun des caractères : \ x 0 0

                            • Partager sur Facebook
                            • Partager sur Twitter
                              7 juin 2018 à 11:24:50

                              Épineux comme problème. Je crois qu'il existe un format pour l'hexa en C : %x. Mais je ne sais pas trop comment l'utiliser dans ce contexte.

                              Je t'invite à créer un nouveau poste propre, dédié à cette question de format, peut être que d'autres personnes auront une solution à ce soucis :)

                              -
                              Edité par Insonore 7 juin 2018 à 11:51:38

                              • Partager sur Facebook
                              • Partager sur Twitter
                              Hugo
                                7 juin 2018 à 11:27:15

                                Dans ce cas pourquoi cherche la représenttion hexadécimale des caractères et pas directement leur représentation ascii?
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  7 juin 2018 à 11:49:15

                                  Merci Insonore pour que ce que tu as fait. Evidemment à thetui aussi mais il semblerait que tu puisses aller plus loin ;)

                                  J'y ai pensé, et j'ai essayé, mais du coup, ça me rajouterait une étape inutile non ?

                                  Si je te suis, ça voudrait dire que je peux prendre chaque couple de caractères, et chercher leur représentation asci ? Parce qu'il faut que je parte d'un caractère hexa pour avoir son ascii correspondant.

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    7 juin 2018 à 12:00:38

                                    C'est juste une idéé mais si tu tente de transmettre un chaine contenant des caractères ASCII ça donne quoi?

                                    Si cela fonctionne il reste le probleme des caracteres n'ayant pas de représentation.

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      7 juin 2018 à 12:27:30

                                      Eh bien par exemple si je tente de transmetre l'équivalent Ascii de la trame plus haut :

                                      .../............smppclient1.password.'VMA'.4...

                                      Le . est considéré comme un vrai point et non comme un caractère NULL (0x00 en hex). Du coup mon programme distant s'affole :p

                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        7 juin 2018 à 13:39:12

                                        //pdu_connection est une chaîne vide qui va récupérer le résultat
                                        //pdu contient une chaine comme ça :
                                        /*    00 00 00 2F 00 00 00 09   00 00 00 00 00 00 00 01   .../.... ........
                                           73 6D 70 70 63 6C 69 65   6E 74 31 00 70 61 73 73   smppclie nt1.pass
                                           77 6F 72 64 00 27 56 4D   41 27 00 34 00 00 00      word.'VM A'.4...*/
                                         
                                         
                                        int pdu_to_hex(char *pdu_connection, char *pdu){
                                         
                                            int err, size_pdu = 0;
                                            regex_t preg;
                                            const char *str_request = pdu;
                                            const char *str_regex = "([0-9|A-F]{2} )";
                                            
                                            char *result = malloc(100 * sizeof(char));
                                            memset(result, '\0', sizeof(result));
                                         
                                            int j=0;
                                         
                                            while(strcmp(&str_request[j], "\0")){      
                                                char current[4];
                                                memset(&current, '\0', sizeof(current));
                                                current[0] = str_request[j];
                                                current[1] = str_request[j+1];
                                                current[2] = str_request[j+2];
                                                printf("La chaine courante est :%s;\n",current);
                                                printf("j = %d\n",j);
                                                j++;
                                                     
                                                err = regcomp (&preg, str_regex, REG_EXTENDED);
                                                if (err == 0)
                                                {
                                                    int match;
                                                    size_t nmatch = 0;
                                                    regmatch_t *pmatch = NULL;
                                                       
                                                    nmatch = preg.re_nsub;
                                                    pmatch = malloc (sizeof (*pmatch) * nmatch);
                                                    if (pmatch)
                                                    {
                                                        match = regexec (&preg, current, nmatch, pmatch, 0);
                                                        regfree (&preg);
                                                         if (match == 0)
                                                         {
                                                            char *hex = NULL;
                                                            int start = pmatch[0].rm_so;
                                                            int end = pmatch[0].rm_eo;
                                                            size_t size = end - start;
                                                                
                                                            hex = malloc (sizeof (*hex) * (size + 1));
                                                            if (hex)
                                                            {
                                                               strncpy (hex, &current[start], size);
                                                               hex[size] = '\0';
                                                               pdu_connection[size_pdu] = strtol(hex, 16);
                                                               size_pdu++;
                                                               free (hex);
                                                            }
                                                         }
                                                         else if (match == REG_NOMATCH)
                                                         {
                                                            printf ("%s ne correspond a deux caracteres hex + un espace\n\n", current);
                                                         }
                                                         else
                                                         {
                                                            char *text;
                                                            size_t size;
                                                            size = regerror (err, &preg, NULL, 0);
                                                            text = malloc (sizeof (*text) * size);
                                                            if (text)
                                                            {
                                                               regerror (err, &preg, text, size);
                                                               fprintf (stderr, "%s\n", text);
                                                               free (text);
                                                            }
                                                            else
                                                            {
                                                               fprintf (stderr, "Memoire insuffisante\n");
                                                               exit (EXIT_FAILURE);
                                                            }
                                                         }
                                                      }
                                                      else
                                                      {
                                                         fprintf (stderr, "Memoire insuffisante\n");
                                                         exit (EXIT_FAILURE);
                                                      }
                                                   }
                                                }
                                                return size_pdu;
                                        }

                                        Et si tu essaies avec ca, en transmettant pdu_connection et en utilisant comme taille de transmission la valeur de retour de la fonction.

                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          7 juin 2018 à 14:24:22

                                          je vais peut etre dire un co***rie, mais tu n'as pas vraiment besoin de rajouter le \x

                                          > \ puis x puis 0 puis 0 etc...   C'est de l'ASCII pour le réseau, comme le montre la première capture Wireshark plus haut.

                                          car en fait ce que tu vois sur le Wireshark c'est à gauche la trame lue en hexa et à droite son interprétation (au mieux), donc toi tout ce que tu à besoin, c'est d'envoyer la donnée brute du buffer genre :

                                          char buffer[] = { 0x00, 0x00, 0x00, 0x2f, ... };
                                          write ( fd, buffer, length );



                                          • Partager sur Facebook
                                          • Partager sur Twitter

                                          la connaissance est une chose qui ne nous appauvrit pas quand on la partage.

                                          Mon GitHub

                                            7 juin 2018 à 14:38:58

                                            Dans mon code plus haut, j'ai oublie deux trucs.

                                            Il faudrait passer le tableau en unsigned char pour gerer les caracteres non représentables, et l'appel à strtol() il faut rajouter NULL ce qui donne strtol(hex, NULL, 16); .

                                            Edit :

                                            A force de recherches, je pense avoir trouve qqch qui pourrait t'intéresser.

                                            #include <stdio.h>
                                            #include <ctype.h>
                                            
                                            int main()
                                            {
                                                const char *src = "0011223344";
                                                char buffer[5];
                                                char *dst = buffer;
                                                char *end = buffer + sizeof(buffer);
                                                unsigned int u;
                                            
                                                while (dst < end && sscanf(src, "%2x", &u) == 1)
                                                {
                                                    *dst++ = u;
                                                    src += 2;
                                                }
                                            
                                                for (dst = buffer; dst < end; dst++)
                                                    printf("%d: %c (%d, 0x%02x)\n", dst - buffer,
                                                           (isprint(*dst) ? *dst : '.'), *dst, *dst);
                                            
                                                return(0);
                                            }



                                            -
                                            Edité par thetui 7 juin 2018 à 14:58:50

                                            • Partager sur Facebook
                                            • Partager sur Twitter

                                            Regex et PDU en héxadecimale

                                            × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                            × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                            • Editeur
                                            • Markdown