Avatar billede emileej Nybegynder
30. august 2000 - 10:08 Der er 4 kommentarer og
1 løsning

CGI - QueryString dekodning

Jeg har MEGET længe forsøgt, at lave en funktion, der kunne opdele en QueryString i et array med strenge, der indeholdte variabelnavnene, og et, der indeholdte verdierne.

Her er mit sidste nye forsøg. Hvad er galt?


Vis variabler .cpp:

#include \"Include\\String.h\"
#include \"Include\\CGI.h\"

void main(void){
    char *QueryString=GetCGIRequest();
    int AntalOg=-1,AntalLigm=-1,Pos=-1, *OgPositioner, *LigmPositioner, I;
    char **Variabler, **Verdier;
    int *VarLengder, *VerLengder;

    SendHTMLHeader();
    printf(\"Analyserer CGI-anmodningen: \\\"%s\\\"...\\n\\n\",QueryString);
    Pos=FindCharFirst(QueryString,\'&\');
    while(Pos!=-1){
        AntalOg++;
        Pos=FindCharNext();
    }
    Pos=FindCharFirst(QueryString,\'=\');
    while(Pos!=-1){
        AntalLigm++;
        Pos=FindCharNext();
    }

    OgPositioner=(int *)calloc(AntalOg,sizeof(int));
    Pos=FindCharFirst(QueryString,\'&\');
    for(I=0;I<=AntalOg;I++){
        OgPositioner[I]=Pos;
        Pos=FindCharNext();
    }
    LigmPositioner=(int *)calloc(AntalLigm,sizeof(int));
    Pos=FindCharFirst(QueryString,\'=\');
    for(I=0;I<=AntalLigm;I++){
        LigmPositioner[I]=Pos;
        Pos=FindCharNext();
    }


    printf(\"Liste over tegn positioner:\\n\\n\");
    for(I=0;I<=AntalOg;I++)
        printf(\"&-tegn nr. %i paa position %i (%c)\\n\",I+1,OgPositioner[I]+1,QueryString[OgPositioner[I]]);
    for(I=0;I<=AntalLigm;I++)
        printf(\"=-tegn nr. %i paa position %i (%c)\\n\",I+1,LigmPositioner[I]+1,QueryString[LigmPositioner[I]]);
    printf(\"\\n\\n\");

   

    VarLengder=(int *)calloc(AntalLigm,sizeof(int));
    printf(\"\\n10%\");
    VerLengder=(int *)calloc(AntalLigm,sizeof(int));
    printf(\"\\b\\b\\b30%%\");

    Variabler=(char **)calloc(AntalLigm,sizeof(char *));
    printf(\"\\b\\b\\b40%%\");
    Verdier=(char **)calloc(AntalLigm,sizeof(char *));
    printf(\"\\b\\b\\b60%%\");
    char *S, *S1;
    printf(\"\\b\\b\\b70%%\");

    for(I=0;I<=AntalLigm;I++){
        printf(\"\\b\\b\\b90%% (%i)(30%%)\",I);
        S=SubString(QueryString,OgPositioner[I]+1,LigmPositioner[I]-1);
        printf(\"\\b\\b\\b90%% (%i)(60%%)\",I);
        S1=SubString(QueryString,LigmPositioner[I]+1,OgPositioner[I]-1);
        printf(\"\\b\\b\\b90%% (%i)(100%%)\",I);
        printf(\"\\nVariablen %s har verdien %s.\\n\",S,S1);
    }
    printf(\"\\n\\n100%%\");
}

Cgi.h:

#include <stdio.h>
#include <stdlib.h>

void SendHTMLHeader(void){
    printf(\"Content-type: text/html\\n\\n\");
}

void SendDocument(char Path[]){
    printf(\"Location: %s\\n\\n\",Path);
}

char *GetCGIRequest(){
    return getenv(\"QUERY_STRING\");
}


String.h:

#include <string.h>
#include <stdlib.h>

char FindChar;
char *FindString;
int LastFindPos, OldLastFindPos;


int LastCharFound(void){
    return OldLastFindPos;
}


int FindCharNext(void){
    OldLastFindPos=LastFindPos;
    int I;
    for(I=(LastFindPos+1);I<=(int)strlen(FindString);I++){
        if(FindString[I]==FindChar){
            LastFindPos=I;
            return I;
        }
    }
    LastFindPos=-1;
    return -1;
}

int FindCharFirst(char String[], char Tegn){
    FindString=String;
    FindChar=Tegn;
    LastFindPos=0;
    FindCharNext();
    return LastFindPos;
}

char *SubString(char *Source, int Start, int End){
        char *ReturnString;
        ReturnString=(char *)calloc((End-Start)-4, sizeof(char));
        int i=Start, j=0;

        while(i<=End){
                  ReturnString[j]=Source[i];
                  i++;
                  j++;
        }
        return ReturnString;
}
Avatar billede tuxen Nybegynder
30. august 2000 - 16:28 #1
Gider ikke kigge hele din kode (i øvrigt fuldstændig ukommenteret) igennem for at finde dine syntaksfejl o.s.v, men jeg har et eksempel jeg har lavet som virker.
Jeg er på kursus i øjeblikket, men kan cut´n paste det fra work på fredag hvis det har nogen interesse ?

M.V.H    Thue
Avatar billede emileej Nybegynder
31. august 2000 - 09:00 #2
Hej Thue!

Jeg er meget interesseret i din kode, da jeg sidder midt i en projektopgave, hvor den behøves.

M.V.H Emil
Avatar billede tuxen Nybegynder
01. september 2000 - 11:19 #3
Hej Emil.
Her kommer så min kode og jeg var lidt hurtig til at kritisere dig for manglende kommentarer da jeg efter at ha kigget i gemmerne fandt dette eksempel der heller ikke er vildt godt kommenteret.

Jeg bruger en hægtet liste til at holde styr på name-value pairs. Databasedelen af programmet er ikke interessant for dig, så det kan du skippe.
Det der sker kan du følge i de første par linier i main.
Der bliver lavet en liste og en parser, parseren returnerer den færdige liste ind i liste pointeren.
Den liste har så metoder til at returnere value af et givent name.
I tilfældet med babeprogrammet her taster brugeren et navn ind som bliver sendt som querystring og opl. om navnet findes i en DB og der skrives så lidt til skærmen.

#include<iostream.h>
#include<stdlib.h>
#include<string.h>
#include<stdio.h>

//Deklaration af globale variable, konstanter og andre strukturer til brug
//i begge moduler: CGI, Oracle & SQL

const int MAXARRAY = 80;                //Bruges i CGI delen.

EXEC SQL BEGIN DECLARE SECTION;
 
  VARCHAR aName[20];
 
  struct TBabe
    {
      VARCHAR Id[7];
      VARCHAR Navn[80];
      int Alder;
      int Points;
    } Babes;
   
EXEC SQL END DECLARE SECTION;

EXEC SQL INCLUDE SQLCA.H;
//
//END
//

class TPair
{
private:

public:
char Name[MAXARRAY];
char Value[MAXARRAY];

TPair* Next;

TPair(char*, char*);
};

//TPair methods

TPair::TPair(char* aName, char* aValue)
{
    strcpy(Name, aName);
  strcpy(Value, aValue);

    Next = NULL;
}


class TPairList
{
private:

public:

TPair* First;

TPairList();
void NewPair(char*, char*);      //startes fra TParser og modtager
char* GetValue(char*);            //Name og Value fra TParser, til
                                  //initaialisering af nyt TPair.
};

//TPairlist methods

TPairList::TPairList()
{
First = NULL;                    //kommer til at pege på par 1.
}

char* TPairList::GetValue(char* aName)
{
int Flag = 1;                  //sat til sandt
TPair* hjelpepeger = First;

while(Flag)
{
  if(First == NULL)
  {
  return NULL;
  }

  else
  {
    if(strcmp(First -> Name, aName) == 0)
    {
    return First -> Value;
    }

      else
      {
          if(hjelpepeger -> Next != NULL)
          {
              if(strcmp(hjelpepeger -> Next -> Name, aName) == 0)
              {return hjelpepeger -> Next -> Value;}

                else
                {
                hjelpepeger = hjelpepeger -> Next; //ryk en frem
                }

        }

                else
                {
                char* error=\"Navnet kunne ikke findes ... \";
                cout<<\"\\nSøgt navneværdi: \"<<aName<<endl;
                return error;
                }

      }

  }//slut yderste else
}    //slut while - løkke
}


void TPairList::NewPair(char* aName, char* aValue)
{
int True  = 1;
int False = 0;
if(First == NULL)
First = new TPair(aName, aValue);
else
{
    TPair* hjelpepeger = First;
    while(True)
  {
    if(hjelpepeger -> Next == NULL)
      {
      hjelpepeger -> Next = new TPair(aName, aValue);
        True = False;                                  //stop løkke
      }
        else
      hjelpepeger = hjelpepeger -> Next;            //ryk én frem
  }
}
}


class TParser
{
private:

char* Query;                  //Peger på starten af QUERYSTRING
char* Method;
int  Length;                  //længden af Query
char* Source;                  //Source rykker frem gennem Query
char* Name;                    //Name og Value sendes til Liste
char* Value;

public:
TPairList* PairList;

TParser();                    //Konstruktøren indlæser \"QUERY_STRING\"
char* GetValue(char*);        //sender forespørgsel til Pairlist
void InsertSpaces();
TPairList* Parse();        //Parser og returnerer liste
};

//TParser methods

TParser::TParser()
{
PairList = new TPairList();

Query  = getenv(\"QUERY_STRING\");
Method = getenv(\"REQUEST_METHOD\");

Length  = strlen(Query);              //bruges i for - løkke
Name    = NULL;
Value  = NULL;
}


void TParser::InsertSpaces()
{
char* IndexPeger = Query;

    for(int a=0;a < Length;a++)
    {
    if(IndexPeger[a] == \'+\')
    Query[a] = \' \';
    }
}


char* TParser::GetValue(char* aName)
{
return PairList -> GetValue(aName);
}


TPairList* TParser::Parse()
{

InsertSpaces();

char  aName[MAXARRAY];
char aValue[MAXARRAY];
int Kontakt = 1;                //0 for \'=\', 1 for \'&\'
int Count_Name  = 0;
int Count_Value = 0;


for(int a=0;a <= Length;a++)
{
  if(Query == NULL)
  {cout<<\"Stoppet! Query er NULL\"<<endl;break;}

      else
  {
        switch(Query[a])
      {
      case \'\\0\':
          //opret sidste par her !
        aValue[Count_Value] = \'\\0\'; //case: kun et par ialt !

        Name  = aName;    //adressen på array
        Value = aValue;

        PairList -> NewPair(Name, Value);
            a = a + Length;        //kør over MAX i for - løkke
        break;                  //ikke flere par

      case \'=\':
        aName[Count_Name] = \'\\0\';

        Count_Name  = 0;              //initialiser igen
        Count_Value = 0;
          Kontakt = 0;
       
        break;

      case \'&\':;
        Kontakt = 1;
        aValue[Count_Value] = \'\\0\';

        Name  = aName;
        Value = aValue;

        PairList -> NewPair(Name, Value);

            Count_Name  = 0;              //initialiser igen
        Count_Value = 0;

          break;

      default :
        if(Kontakt == 1)
        {aName[Count_Name] = Query[a];
        Count_Name++;
        }
        else
        {aValue[Count_Value] = Query[a];
        Count_Value++;
        }

      }

  }  //end else
}    //end For

return PairList;            //send listen med pair´s til main

}      //end Funktion

//
//end deklaration af klasser til cgi-delen: TPair, TPairList & TParser.    END
//
//
//START på deklaration af klasser til Databaseconnecting & SQL - processing.
//

class Exceptions {
  private:
    char theMessage[80];
  public:
    Exceptions();
    Exceptions(char *);
    friend ostream &operator << (ostream &, Exceptions &);
  };
 
void err() {
  throw Exceptions(sqlca.sqlerrm.sqlerrmc);
  }

class Databases {
  private:
    EXEC SQL BEGIN DECLARE SECTION;
      VARCHAR db_userid[40];
      VARCHAR db_password[40];
    EXEC SQL END DECLARE SECTION;
  public:
    Databases(char *, char *);
    ~Databases();
  };

// Methods for Databases

Databases::Databases(char *uid, char *pwd)
{
  db_userid.len = strlen(strcpy((char *)db_userid.arr, uid));
  db_password.len = strlen(strcpy((char *)db_password.arr, pwd));
  EXEC SQL WHENEVER SQLERROR DO err();
  EXEC SQL CONNECT :db_userid IDENTIFIED BY :db_password;
}

Databases::~Databases()
{
EXEC SQL WHENEVER SQLERROR CONTINUE;
EXEC SQL COMMIT WORK RELEASE;
}

//Methods for Exceptions

Exceptions::Exceptions()
{
strcpy(theMessage, \"Undefined exception\");
}

Exceptions::Exceptions(char *m)
{
strcpy(theMessage, m);
}

ostream &operator << (ostream &o, Exceptions &E)
{
o << E.theMessage;
return o;
}

//END

void main()
{
TPairList* List;                      //oprettelse af instanser
TParser* Parser = new TParser();
List = Parser -> Parse();            //parse og returnér liste


//START DB & SQL

Databases* db;
  try
  {
    db = new Databases(\"d97529\", \"d97529\");


    strcpy((char*)aName.arr, List -> GetValue(\"navn\"));    //initialiser til navnet fra cgi
    aName.len = strlen(List -> GetValue(\"navn\"));    //altså navnet fra hjemmesiden

    EXEC SQL WHENEVER SQLERROR DO err();
    EXEC SQL
      SELECT ID, NAVN, ALDER, POINTS
      INTO :Babes
      FROM BABES
      WHERE NAVN = :aName;

    Babes.Id.arr[Babes.Id.len] = \'\\0\';
    Babes.Navn.arr[Babes.Navn.len] = \'\\0\';
   
    delete db;
    }

  catch (Exceptions E)
  {
    EXEC SQL WHENEVER SQLERROR CONTINUE;
    cout << E;
    EXEC SQL ROLLBACK RELEASE;
  }

//END SQL & DB


//START output til Browseren

cout<<\"content-type: text/html\"<<endl<<endl;  //header med 2 newlines
cout<<\"<html><head></head><body bgcolor=\\\"blue\\\">\";

cout << \"Babe´n med navnet: \" <<(char *)Babes.Navn.arr<<\" er \";
cout << (char *)Babes.Alder << \" år og har \";
cout << (char *)Babes.Points << \" point\";


cout<<\"</body></html>\";

//END output

}


Med venlig hilsen Thue
Avatar billede emileej Nybegynder
04. september 2000 - 09:51 #4
Tak for koden Thue!

Jeg har tilpasset den mine behov, og har et spørgsmål i den anledning.

Check venligst spørgsmålet \"CGI - QueryString dekodning - 2\"

Emil
Avatar billede stringbuffer Nybegynder
25. september 2002 - 15:06 #5
Det afhænger selvfølgelig af antallet af parametre i din query string, men det kunne måske være værd at overveje at bruge en hash-tabel til at gemme parametrene i "key" => "value" par, og dekode din query string (dvs. dekode URL-encoding) med et enkelt gennemløb af strengen.
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