Avatar billede rrm Nybegynder
16. august 2005 - 12:43 Der er 15 kommentarer og
1 løsning

Url parser til c++

Jeg er ved lave et programet, der som inputs får url'er og dertil mangler jeg et stykke kode der kan parse dem. Er der nogen der kender en gratis klasse/funtion bibliotek der kan klarer dette?? Programmet er skrevet i c++.

mvh
rrm
Avatar billede arne_v Ekspert
16. august 2005 - 13:07 #1
for snart 10 år siden lavede jeg denne her URL_to_components:

#include <iostream>

using namespace std;

void URL_to_components(char *url,
                      char *protocol,char *host,int *port,
                      char *path,char *un,char *pw)
{
  char *p = url;
  char *pp,*ppp;
  // find protocol
  if(strstr(p,"telnet:")==p) {
      strcpy(protocol,"telnet");
      p = p + strlen("telnet:");
  } else if(strstr(p,"http:")==p) {
      strcpy(protocol,"http");
      p = p + strlen("http:");
  } else if(strstr(p,"mailto:")==p) {
      strcpy(protocol,"mailto");
      p = p + strlen("mailto:");
  } else if(strstr(p,"gopher:")==p) {
      strcpy(protocol,"gopher");
      p = p + strlen("gopher:");
  } else if(strstr(p,"ftp:")==p) {
      strcpy(protocol,"ftp");
      p = p + strlen("ftp:");
  } else if(strstr(p,"file:")==p) {
      strcpy(protocol,"file");
      p = p + strlen("file:");
  } else if(strstr(p,"news:")==p) {
      strcpy(protocol,"news");
      p = p + strlen("news:");
  }
  // skip "//" if present
  if(strstr(p,"//")==p) p = p + strlen("//");
  // find username and password if present
  pp = strstr(p,"@");
  if(pp!=NULL) {
      ppp = strstr(p,":");
      if(ppp!=NULL) {
        strncpy(un,p,ppp-p);
        un[ppp-p] = '\0';
        strncpy(pw,ppp+1,(pp-ppp)-1);
        pw[(pp-ppp)-1] = '\0';
      } else {
        strncpy(un,p,pp-p);
        un[pp-p] = '\0';
        strcpy(pw,"");
      }
      p = pp + 1;
  } else {
      strcpy(un,"");
      strcpy(pw,"");
  }
  // find host
  pp = strpbrk(p,":/");
  if(pp==NULL) pp = p + strlen(p);
  strncpy(host,p,pp-p);
  host[pp-p] = '\0';
  p = pp;
  // find port if present
  if((*p)==':') {
      p++;
      (*port) = atoi(p);
  } else {
      (*port) = 0;
  }
  // find path if present
  pp = strstr(p,"/");
  if(pp!=NULL) strcpy(path,pp); else strcpy(path,"");
  pp = strstr(path,"#");
  if(pp!=NULL) *pp = '\0';
  return;
}

void test(char *url)
{
    char protocol[10],host[100],path[200],un[20],pw[20];
    int port;
    URL_to_components(url,protocol,host,&port,path,un,pw);
    cout << url << endl;
    cout << protocol << endl;
    cout << host << endl;
    cout << port << endl;
    cout << path << endl;
    cout << un << endl;
    cout << pw << endl;
}

int main()
{
    test("http://www.xxx.dk:80/foobar.php?f1=a&f2=bb");
    test("ftp.xxx.dk/noget.txt"" target="_blank">ftp://arne:hemmeligt@ftp.xxx.dk/noget.txt");
    return 0;
}
Avatar billede arne_v Ekspert
16. august 2005 - 13:18 #2
idag ville man sikkert finde en regex pakke og bruge den ...
Avatar billede Slettet bruger
16. august 2005 - 14:04 #3
Hvad er en regex pakke?
Avatar billede arne_v Ekspert
16. august 2005 - 14:05 #4
et bibliotek som understøtter regular expressions
Avatar billede rrm Nybegynder
16. august 2005 - 17:46 #5
Er der nogen regex pakker du vil foreslå???
Avatar billede arne_v Ekspert
16. august 2005 - 18:02 #6
den eneste jeg kender er PCRE som har et low level C interface og derfor er
noget sværere at bruge end man kender fra ande sprog

men den virker fint
Avatar billede rrm Nybegynder
17. august 2005 - 00:24 #7
ok, det vil jeg prøve at bruge... Tak for hjælpen
Avatar billede rrm Nybegynder
17. august 2005 - 01:09 #8
hmm, jeg forsøgt at bruge PCRE, men synes ikke jeg får noget brugbart resultat fra det, så jeg vil høre om der er nogen fejl i følgende: Det skulle gerne parse f.eks. :000/ men ikke :dfdf0/

Jeg er hellere ikke sikre på at jeg fortolker resultatet rigtig...

Mvh rrm

--- kode ---
    const char *error;
    int  erroffset;
    pcre *re;
    int  rc;
    int  i;
  // char  str[] = ;  /* String to match */
    int  ovector[5];

    re = pcre_compile (
        "^((:[0-9]*//)?)",      /* the pattern *///
        0,                    /* default options */
        &error,              /* for error message */
        &erroffset,          /* for error offset */
        0);
   
    if (!re) {
        errMsg = "Internal error: pcre_compile failed with the error: " + *error;
        errMsg += " at " + intToStr(erroffset);
        return ERR_URL_MALLFORM;
    }

    rc = pcre_exec (
        re,                  /* the compiled pattern */
        0,                    /* no extra data - pattern was not studied */
        url.c_str(),          /* the string to match */
        url.length(),        /* the length of the string */
        0,                    /* start at offset 0 in the subject */
        0,                    /* default options */
        ovector,              /* output vector for substring information */
        5);                        /* number of elements in the output vector */

    if (rc < 0) {
   
        cout << "error" << endl;

        switch (rc) {
          case PCRE_ERROR_NOMATCH:
            errMsg = "Unexpeted port entry. Expected 0 or 1 of :[number]/";
            break;

          default:
            errMsg = "Internal error: pcre_exec failed";
            break;
        }
   
        free(re);
        return ERR_URL_MALLFORM;
    }

    for (i = 0; i < rc; i++) {
   
        cout << ovector[i*3] << endl;
    }
Avatar billede arne_v Ekspert
17. august 2005 - 09:49 #9
til inspiration:

#include <stdio.h>
#include <string.h>
#include <pcre.h>

void test(char *s)
{
    pcre *re;
    int rc;
    int erroffset;
    int ovector[300];
    const char *error;
    const char *p;
    re = pcre_compile("^:([0-9]+)/$",0,&error,&erroffset,NULL);
    rc = pcre_exec(re,NULL,s,strlen(s),0,0,ovector,sizeof(ovector)/sizeof(int));
    if(rc < 0)
    {
        printf("%s does NOT contain a number\n",s);
    }
    else
    {
        pcre_get_substring(s,ovector,rc,1,&p);
        printf("%s does contain a number and it is %s\n",s,p);
    }
}

int main()
{
    test(":000/");
    test(":dfdf0/");
    return 0;
}
Avatar billede rrm Nybegynder
17. august 2005 - 12:36 #10
okey tak for det... Jeg har siddet og eksperimenteret med pcre, men er ikke med på den resultat.

Jeg benytter følgende mønster: ^((:[0-9]+/)?) til at teste for f.eks. udtrykket :25/cxvxcv, hvor den skal kunne godkende :25/ og undlade det sidste.

Når jeg bruger dette mønster på ":0000/" returener pcre_exec værdien 3 og sådan som jeg har forstået det, så findes der så 3 steder der opfylder mønsteret, men der skulle være et sted der macther mønsteret. Hvad er der galt, har jeg misforstået noget???
Avatar billede arne_v Ekspert
19. august 2005 - 20:58 #11
jeg forstår ikke hvorfor du bruger det regex udtryk - det tilføjer vel ikke
noget relevant funktionalitet o forhold til mit

hvis du vil finde flere matches mener jeg at du skal bruge en while
løkke og tælle start offset op
Avatar billede rrm Nybegynder
20. august 2005 - 11:17 #12
Ok, det er ikke meningen at stregen skal matche flere men kun én i starten af stregen. Som jeg forstår regex, så betyder $ at det skal matche i slutningen. Derfor bruger jeg det ikke, men har jeg misforstået noget???

F.eks. skal den godkende
http://www.dr.dk:80/blabla
men ikke
http://ww.dr.dk:80/:80/blabla

Men jeg skal måske hellere starte et regex spm???
Avatar billede arne_v Ekspert
20. august 2005 - 11:21 #13
$ betyder bare at linie slutter der

"^http://[a-z0-9.]+:[0-9]+/[^: ]*$"

vil kun matche den første

mens

"^http://[a-z0-9.]+:[0-9]+/[^: ]*"

vil matche dem begge
Avatar billede rrm Nybegynder
20. august 2005 - 12:07 #14
ok.. Jeg har valgt at dele regex parsingen op i flere dele [protocol](ikke brugt regex her),[host],[port],[path] og skrive regex for hver "gruppe", idet jeg så kan sætte nogle variable.
Samtidigt synes jeg også det bliver nemmere for mig at teste hver del seperat, da der skal bruges et pæn stort regex streng.
Avatar billede rrm Nybegynder
26. august 2005 - 13:53 #15
nå, men tak for hjælpen, vil du ligge et svar Arne V...
Avatar billede arne_v Ekspert
26. august 2005 - 13:57 #16
ok
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester