[Implemented] A CGI library compatible cross OS
[Implemented] A CGI library compatible cross OS
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.
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,
Cya,
El_Choni
-
- New User
- Posts: 1
- Joined: Sat Jan 24, 2004 5:56 pm
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.
-
- Enthusiast
- Posts: 229
- Joined: Wed May 14, 2003 3:38 pm
- Location: Lüneburg - Germany
-
- Addict
- Posts: 2344
- Joined: Mon Jun 02, 2003 9:16 am
- Location: Germany
- Contact:
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... )
( The path to enlightenment and the PureBasic Survival Guide right here... )
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
Visit www.sceneproject.org
Purebasic CGI Library
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:
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.
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.
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")
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