[Implemented] A CGI library compatible cross OS
Posted: Tue Jan 20, 2004 5:02 pm
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.
http://www.purebasic.com
https://www.purebasic.fr/english/
I have been looking for an alternative but no luck. It really is needed.griz wrote: Does anyone have alternate suggestions?
PrintN/Print and getenv_ are the whole needed commandsgriz 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?
Does anyone have alternate suggestions?
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