Thread: Cgi Query (no pun intended)

  1. #1
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708

    Cgi Query (no pun intended)

    Hello, all. I have a couple of questions regarding how arguments are parsed for a cgi program (for "GET" methods only, that is, where the query is included in the uri). For instance, let's say we have the string:

    "net/stuff/pre%20process.cgi?type=my%20type&length=40"

    Now then, am I correct that the hex values SHOULD NOT be decoded for the cgi application? Such that after parsing I would end up with:

    File: "net/stuff/pre process.cgi"
    CGI pre-parsed string = "type=my%20type&length=40"

    Also, am I correct that the above example should pass:

    argv1: type=my%20type
    argv2: length=40

    Also, any other info or suggestions on this topic are welcome.

    Thanks.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  2. #2
    Registered User
    Join Date
    Feb 2003
    Posts
    265
    Different environments handle url codes in variable names differently. For example, PHP replaces the %20 in the variable name with an underscore in the final variable name (i believe this is always the case but im not positive it). Example: http://www.wrightlinx.com/info/phpin...?my%20var=haha
    This is just a phpinfo script that comes by default with most php installs, i chose a website that wouldnt be hurt by the traffic to demonstrate it. As you can see (scroll down a ways) REQUEST_METHOD = GET ; QUERY_STRING is my%20var=haha ; and the array of variables _SERVER["argv"] Array
    (
    [0] => my%20var=haha
    )
    BUT, when retrieveing the variable, _REQUEST["my_var"] = haha ;
    _GET["my_var"] = haha ; it replaces the %20 with an underscore.

    Im sure you know how to edit the above URL so you can test other instances, but most urlencoded characters are not valid in variable names in many languages so they should probablly be replaced. For example, if a urlencoded period were decoded, that could seriously mess with member function calls in a class, ne? While at the same time some environments wont let you use % in variables either, so they potentially need to be replaced with a non-problematic character. Anyways this is all my best guess, I havent worked on a CGI script for a long long time. I was a perl geek back in the day.
    Last edited by Geolingo; 08-27-2003 at 11:03 AM.

  3. #3
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    OK, thanks, that link was useful. And so the amperstand is what really separates each argument, such that given:

    "http://cboard.cprogramming.com/newreply.php?s=&action=newreply&threadid=43953"

    ...then I would pass the args as:

    argv[1]: s=
    argv[2]: action=newreply
    argv[3]: threadid=43953

    Is that correct?
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  4. #4
    Registered User
    Join Date
    Feb 2003
    Posts
    265
    Correct!

    Although the array should start at 0 and not 1 probablly =P

  5. #5
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Remember that argv[0] is going to be the name of the program running, ie:

    Code:
    int main(int, char * argv[])
    {
     for(int i = 0; argv[i]; ++i) 
      printf("argv[%d]:  %s\n", i, argv[i]); 
    }
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  6. #6
    Registered User
    Join Date
    Feb 2003
    Posts
    265
    Yes but generally (5 years ago when i wrote CGI programs in perl and C with cgilib and uncgi) the query string isnt passed like a commandline application. Im not sure what environment your trying to use to do this, but how the query string is passed is OS and HTTPD specific with C. If this is a windows platform, ISAPI might be more what your looking for. There are various librarys (i just mentioned 2 i used a long time ago) that handle CGI input and output processing for C/C++ applications. Happy coding.

  7. #7
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    I'm pretty sure that the command line is used here. The only exception is with environment variables. I never use this method, but I'm pretty sure it works like this:

    An application makes a call like:

    putenv("SOMETHING=value");

    Now a second application starts up and accesses the string like this:

    char * var = getenv("SOMETHING");

    printf("%s\n", var ? var : "Doesn't exist"); // prints "value"

    Again, I'm merely speculating here, but that should be pretty close to the actual semantics.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  8. #8
    Registered User
    Join Date
    Jan 2002
    Location
    Vancouver
    Posts
    2,212
    Hmm this is weird. I wrote this simple program:

    Code:
    #include <stdio.h>
    
    int printHeader(void);
    
    int main(int argc, char *argv[])
    {
      printHeader();
      
      printf("%d %s %s",argc,argv[0],argv[1]);
      return 0;
    }
    
    int printHeader(void)
    {
      printf("Content-type: text/html\n\n");
      return 0;
    }
    it is here http://www.legcramp.co.uk/cgi-bin/ex (running on gnu/linux/apache). Now it displays the value when the paramater is something like http://www.legcramp.co.uk/cgi-bin/ex?hello or http://www.legcramp.co.uk/cgi-bin/ex?hello&goodbye but of there is an equals sign http://www.legcramp.co.uk/cgi-bin/ex?hello=1 it just displays (null)
    wtf?

    by the way, CGI in C is dangerous to say the least. C is full of buffer overflow opportunities. Be very careful, and check those buffers!
    Last edited by Brian; 08-28-2003 at 10:03 PM.

  9. #9
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Heh. Yeah, it's really not a good idea to do something like:

    >> printf("%d %s %s",argc,argv[0],argv[1]);

    A safer way would be:

    printf("%d %s %s",argc, argv[0], argv[1] ? argv[1] : "(empty)");

    Or better yet:

    Code:
    int main(int argc, char ** argv)
    {
     printf("Args available: %d\n", --argc);
     printf("Args:\n");
     while(*(++argv))
      printf("%s\n", *argv);
    }
    Anyway, that is odd. Only thing I can think is that the "=" sign tells apache to set the environment variable "hello" to the value "1". Try the putenv()/getenv() functions on it?
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  10. #10
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    And try this:

    http://www.legcramp.co.uk/cgi-bin/ex?hello+goodbye

    It prints "3 ex hello", meaning that it counted an extra arg, but doesn't print it.

    And:

    http://www.legcramp.co.uk/cgi-bin/ex?hello&goodbye

    prints: 2 ex hello\&goodbye

    ...so it didn't even split the args as I expected.

    By the way, thanks for writing that program. At least it give me somthing tangible to toy with (even though the results are confusing ).

    Let me know if you have any more revalations.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  11. #11
    Registered User
    Join Date
    Jan 2002
    Location
    Vancouver
    Posts
    2,212
    This updated code is running on the same page now.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int printHeader(void);
    int mergeArgv(char *argv[], int maxlen, char *merged);
    
    int main(int argc, char *argv[])
    {
      char merged[512] = "\0";
      char *env = getenv("hello");
    
      printHeader();
      printf("%s <br>\n",env);  
      if (argc > 1)
      {
        mergeArgv(argv,512, merged);
        printf("%s",merged);
      }
    
      return 0;
    }
    
    
    /* Turns all the argv strings into one */
    
    int mergeArgv(char *argv[], int maxlen, char *merged)
    {
      int i;
      if (strlen(argv[0]) >= maxlen)
      {
        return 0;
      }
      else
      {
        strcpy(merged,argv[0]);
      }
    
      for (i = 1; argv[i]; i++)
      {
        if (strlen(merged) + strlen(argv[i]) + 1 >= maxlen)
        {
          return 0;
        }
        else
        {
          strcat(merged," ");
          strcat(merged,argv[i]);
        } 
      }
      return 0;
    }
    
    int printHeader(void)
    {
      printf("Content-type: text/html\n\n");
      return 0;
    }
    It tries to display the environment variable hello, but as you can see from http://www.legcramp.co.uk/cgi-bin/ex?hello=hi
    it doesn't work.

  12. #12
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Geez, you and pointers.

    Remember, getenv() can quite possibly return null.

    >> printf("%s <br>\n",env);

    See the problem?

    But yeah, I get your point. Apache didn't set an environment variable "hello". I will have to dig a little deeper then. I will definately relay the results as soon as I get to the bottom of it.

    One more nitpick, though:

    >> if (strlen(merged) + strlen(argv[i]) + 1 >= maxlen)

    That shoud be:

    if (strlen(merged) + strlen(argv[i]) > maxlen-1)
    Last edited by Sebastiani; 08-29-2003 at 08:26 AM.
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. query problem
    By arian in forum C# Programming
    Replies: 1
    Last Post: 08-18-2008, 01:49 PM
  2. CGI program help please
    By Lince in forum C Programming
    Replies: 3
    Last Post: 08-01-2007, 01:31 AM
  3. cgi - c++ returns image
    By terracota in forum C++ Programming
    Replies: 1
    Last Post: 08-04-2004, 09:41 PM
  4. testing a cgi script on my computer
    By Bigbio2002 in forum C Programming
    Replies: 1
    Last Post: 12-14-2003, 07:26 PM
  5. wut is the point of pointers (no pun intended)
    By Geo-Fry in forum C++ Programming
    Replies: 2
    Last Post: 03-08-2003, 12:13 PM