[Implemented] A CGI library compatible cross OS

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
NelsonN
User
User
Posts: 12
Joined: Mon Dec 22, 2003 1:38 am
Location: Puerto Rico

[Implemented] A CGI library compatible cross OS

Post by NelsonN »

This is a seriously needed addition. I can program descent Windows CGI tools but not with the Linux version because of a lack of a CGI library for Linux.
User avatar
griz
Enthusiast
Enthusiast
Posts: 167
Joined: Sun Jun 29, 2003 7:32 pm
Location: Canada

Post by griz »

I too would like to learn how to create CGIs with the Linux version of PB.

Perhaps El_Choni will port his CGI library? :wink:

Does anyone have alternate suggestions?
NelsonN
User
User
Posts: 12
Joined: Mon Dec 22, 2003 1:38 am
Location: Puerto Rico

Post by NelsonN »

griz wrote: Does anyone have alternate suggestions?
I have been looking for an alternative but no luck. It really is needed.

But to be fare, perhaps it is us who are lacking. :)

Maybe El_Choni will port it to Linux. Where is El_Choni these days, anyway?
El_Choni
TailBite Expert
TailBite Expert
Posts: 1007
Joined: Fri Apr 25, 2003 6:09 pm
Location: Spain

Post by El_Choni »

I'm not dead, but I can't port it to Linux since I don't know the Linux API and I don't even have Linux installed anywhere. But it must be piece of cake to code these functions in C and build a library with the Library SDK in the PureBasic for Linux version (I guess it includes a SDK, right?)

Cya,
El_Choni
NelsonN
User
User
Posts: 12
Joined: Mon Dec 22, 2003 1:38 am
Location: Puerto Rico

Post by NelsonN »

Yes, the Linux version has an SDK.

But I am not that advanced of a programmer, especially in Linux. Which is why I am willing to hand over a few bucks :)
El_Choni
TailBite Expert
TailBite Expert
Posts: 1007
Joined: Fri Apr 25, 2003 6:09 pm
Location: Spain

Post by El_Choni »

That's nice to hear but, as I said, I don't have enough knowledge to code anything for Linux different than php or perl. But if some Linux code offers to help you, I'll help him to port the functions (for free).

Regards,
El_Choni
Triskelios
New User
New User
Posts: 1
Joined: Sat Jan 24, 2004 5:56 pm

Post by Triskelios »

Well, NelsonN ended up contacting me on freenode (IRC) about it, and I agreed to give a shot at writing a POSIX version of the library in C (more motivated by possible payment, since I'm certain that this isn't the right way to approach server-side scripting at all... =P). Since I can't read intel asm at all, I'll take that offer of assistance.
El_Choni
TailBite Expert
TailBite Expert
Posts: 1007
Joined: Fri Apr 25, 2003 6:09 pm
Location: Spain

Post by El_Choni »

Ok, let's do it: mcalderon_inicia.es

I can't start with this until Thursday. Maybe you can have a look at the Readme.txt file included in the lib so you know each function's job. Probably, I'll update the Windows version, too.

Cya,
El_Choni
FloHimself
Enthusiast
Enthusiast
Posts: 229
Joined: Wed May 14, 2003 3:38 pm
Location: Lüneburg - Germany

Post by FloHimself »

any news on this one?
My favorite numbers: 09 F9 11 02 9D 74 E3 5B D8 41 56 C5 63 56 88 C0
DarkDragon
Addict
Addict
Posts: 2344
Joined: Mon Jun 02, 2003 9:16 am
Location: Germany
Contact:

Post by DarkDragon »

griz wrote:I too would like to learn how to create CGIs with the Linux version of PB.

Perhaps El_Choni will port his CGI library? :wink:

Does anyone have alternate suggestions?
PrintN/Print and getenv_ are the whole needed commands ;) .
bye,
Daniel
ricardo
Addict
Addict
Posts: 2438
Joined: Fri Apr 25, 2003 7:06 pm
Location: Argentina

Post by ricardo »

Any news?
ARGENTINA WORLD CHAMPION
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Post by blueznl »

i guess waiting for pb4 for linux may solve your issues?
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
Nik
Addict
Addict
Posts: 1017
Joined: Fri May 13, 2005 11:45 pm
Location: Germany
Contact:

Post by Nik »

The fact is there isn't a issue since Linux has no graphical console the normal console commands + getenv_ are everything you need on Linux, nor problem in sight
StanDan
User
User
Posts: 57
Joined: Sun Feb 26, 2006 3:43 am
Location: Missouri, United States

Purebasic CGI Library

Post by StanDan »

I know this thread is old but I might as well post this. I was looking for the exact same thing, so I wrote my own. It's based loosely on the Perl 1.x cgi-lib.pl code. So it should work in most situations. It's not blazingly fast for PB code, it just works. It's also very easy to use. It's as simple as:

Code: Select all

XIncludeFile "cgi.pb"
ReadParse()
; To print all arguments
ForEach CGIArgs()
  PrintN("<tr>")
  PrintN("<td>"+CGIArgs()\name+"</td>")
  PrintN("<td>"+CGIArgs()\value+"</td>")
  PrintN("</tr>")
Next
; To get a specific form argument
someArg.s = GetCGIArg("someArg")
It just reads the arguments into a linked list called CGIArgs(), each element is a structure with attributes called name and value. Very simple. Comments, patches, suggestions are very welcome. I have tested this with Apache 2 on Linux. Haven't tried IIS yet but it should work. I'm declaring this code public domain, use it however you want.

Code: Select all

OpenConsole()

Structure CGIArg
  name.s
  value.s
EndStructure

Global NewList CGIArgs.CGIArg(), CGIMaxPostSize = 10000, CGIHeaderFlag = 0

Procedure Header()
  If CGIHeaderFlag = 0
    PrintN("Content-type: text/html"+Chr(10)+Chr(10))
    CGIHeaderFlag = 1
  EndIf
EndProcedure

Procedure CGIError(error.s)
  Header()
  PrintN("<h3 class='cgiError'>"+error+"</h3>")
  End
EndProcedure

Procedure CGIAssert(val.l)
  If val = 0
    Debug "Dying on CGIAssert statement."
    CGIError("Error 500: Internal Server Error")
  EndIf
EndProcedure

; Return the binary number corresponding to the character 0-9a-f, 1-15
Procedure.l GetNum(thechar.l)
  ; Handle 0-9
  If thechar >= 48 And thechar <= 57
    ProcedureReturn thechar - 48

  ; Handle a-f
  ElseIf thechar >= 97 And thechar <= 102
    ProcedureReturn 10 + (thechar - 97)
    
  ; Handle A-F
  ElseIf thechar >= 65 And thechar <= 70
    ProcedureReturn 10 + (thechar - 65)
   
  Else
    Debug "Non hex character passed to GetNum()"
    ProcedureReturn -1
  EndIf
EndProcedure

; Convert a hexidecimal character string into its binary representation.
Procedure.l ValH(nums.s)
  Define.l strlen = 0, pos =0, answer = 0
  strlen = Len(nums)
  pos = strlen
  
  While pos > 0
    answer = answer + Pow(16, pos -1) * GetNum(Asc(Mid(nums, strlen - pos+1, 1)))
    pos = pos - 1
  Wend
  
  ProcedureReturn answer
EndProcedure

; Check if a character is valid hexidecimal.
Procedure.l IsHex(thechar.l)
  If (thechar >= 48 And thechar <= 57) Or (thechar >= 97 And thechar <= 102) Or (thechar >= 65 And thechar <= 70) 
    ProcedureReturn 1
  Else
    ProcedureReturn 0
  EndIf 
EndProcedure

; Decode URL ecoding %20 = ' ' etc.
Procedure.s URLDecode(str.s)
  Define.s ret = str, temp = ""
  Define.l currentPos = 1, prevPos = 1
  Define.s byte
  
  ReplaceString(str, "+", " ", 2)
  currentPos = FindString(str, "%", currentPos)
  While currentPos > 0
    temp = temp + Mid(str, prevPos, currentPos - prevPos)
    Debug temp
    byte = Mid(str, currentPos+1, 2)
    Debug "'"+byte+"'"
    If Len(byte) <> 2
      Break
    EndIf
    If IsHex(Asc(Mid(byte, 1, 1))) And IsHex(Asc(Mid(byte, 2, 1))) And byte <> "00"
      temp = temp + Chr(ValH(LCase(byte)))
      Debug "'"+Chr(ValH(LCase(byte)))+"'"
      currentPos = currentPos + 3
    Else
      temp = temp + "%" + byte
      currentPos = currentPos + 3
    EndIf 
    prevPos = currentPos
    currentPos = FindString(str, "%", currentPos)
  Wend
  If temp <> ""
    temp = temp + Mid(str, prevPos, Len(str))
    ret = temp
  EndIf
  ProcedureReturn ret
EndProcedure

Procedure ReadParse()
  Define.s method = GetEnvironmentVariable("REQUEST_METHOD")
  Define.s type = GetEnvironmentVariable("CONTENT_TYPE")
  Define.s query = ""
  
  If method="" Or method = "GET" Or method = "HEAD" Or type = "application/x-www-form-urlencoded"
    If method = "GET"
      query = GetEnvironmentVariable("QUERY_STRING")
    ElseIf method = "POST"
      Define.l length, *ptr, res
      length = Val(GetEnvironmentVariable("CONTENT_LENGTH"))
      If length < CGIMaxPostSize
        *ptr = AllocateMemory(length)
        res = ReadConsoleData(*ptr, length)
        If res <> length
          Debug "CONTENT_LENGTH does not match input"
        EndIf
        query = PeekS(*ptr)
        FreeMemory(*ptr)
      Else
        Debug "Skipping since CONTENT_LENGTH exceeds CGIMaxPostSize"
      EndIf
      ProcedureReturn
    Else
      Debug "Uknown request method."
      ProcedureReturn
    EndIf
    
    Define.l args = 0, i = 0    
    args = CountString(query, "&") + 1
    While i < args
      Define.s temp
      i = i + 1
      temp = StringField(query, i, "&")
      AddElement(CGIArgs())
      CGIArgs()\name = URLDecode(StringField(temp, 1, "="))
      CGIArgs()\value = URLDecode(StringField(temp, 2, "="))
    Wend
  EndIf
EndProcedure

Procedure.s GetCGIArg(name.s)
  ForEach CGIArgs()
    If CGIArgs()\name = name
      ProcedureReturn CGIArgs()\value
    EndIf
  Next
  ProcedureReturn ""
EndProcedure

Procedure PrintCGIArgs()
  Header()
  PrintN("<table><tr><td>Name</td><td>Value</td></tr>")
  ReadParse()
  ForEach CGIArgs()
    PrintN("<tr>")
    PrintN("<td>"+CGIArgs()\name+"</td>")
    PrintN("<td>"+CGIArgs()\value+"</td>")
    PrintN("</tr>")
  Next
  PrintN("</table>")
EndProcedure
One thing I'm going to do when I get around to it is write the parser for CONTENT_TYPE = "multipart/form-data". I'll post it when I get a project that requires file upload.
Post Reply