uncgi.pp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. unit uncgi;
  2. {
  3. $Id$
  4. UNCGI UNIT 2.0.11
  5. ----------------
  6. }
  7. interface
  8. uses
  9. strings
  10. {$ifdef ver1_0}
  11. {$ifdef FreeBSD} {In 1.0 FreeBSD still defines Linux!}
  12. ,Linux
  13. {$else}
  14. {$ifdef linux}
  15. ,Linux
  16. {$endif}
  17. {$endif}
  18. {$else}
  19. {$ifdef Unix}
  20. ,Unix
  21. {$endif}
  22. {$endif}
  23. {$IFDEF OS2}
  24. ,DosCalls
  25. {$ENDIF OS2}
  26. ;
  27. {***********************************************************************}
  28. const
  29. maxquery = 100;
  30. hextable : array[0..15] of char=('0','1','2','3','4','5','6','7',
  31. '8','9','A','B','C','D','E','F');
  32. uncgi_version = 'UNCGI 2.0.11';
  33. uncgi_year = '1999';
  34. maintainer_name = 'Your Name Here';
  35. maintainer_email= '[email protected]';
  36. Type cgi_error_proc = procedure (Const Proc,Err : String);
  37. var
  38. get_nodata : boolean;
  39. query_read : word;
  40. query_array : array[1..2,1..maxquery] of pchar;
  41. uncgi_error : cgi_error_proc;
  42. {***********************************************************************}
  43. { FUNCTION
  44. This function returns the REQUEST METHOD of the CGI-BIN script
  45. Input - Nothing
  46. Output - [GET|POST]
  47. }
  48. function http_request_method: pchar;
  49. { FUNCTION
  50. This function returns the "referring" page. i.e. the page you followed
  51. the link to this CGI-BIN from
  52. Input - Nothing
  53. Output - [http://somewhere.a.tld]
  54. }
  55. function http_referer: pchar;
  56. { FUNCTION
  57. This function returns the users's USER AGENT, the browser name etc.
  58. Input - Nothing
  59. Output - user agent string
  60. }
  61. function http_useragent: pchar;
  62. { FUNCTION
  63. This function returns a value from an id=value pair
  64. Input - The identifier you want the value from
  65. Output - If the identifier was found, the resulting value is
  66. the output, otherwise the output is NIL
  67. }
  68. function get_value(id: pchar): pchar;
  69. { FUNCTION
  70. This function extracts array of values for the
  71. same variable (used in some checkbox forms)
  72. Use like in this example:
  73. cnt:=0;
  74. v[cnt]:=get_value('some_id');
  75. while v[cnt]<>'' do begin
  76. inc(cnt);
  77. v[cnt]:=get_next_value('some_id');
  78. end;
  79. }
  80. function get_next_value(id: pchar): pchar;
  81. { PROCEDURE
  82. This procedure writes the content-type to the screen
  83. Input - The content type in MIME format
  84. Output - Nothing
  85. Example - set_content('text/plain');
  86. set_content('text/html');
  87. }
  88. procedure set_content(ctype: string);
  89. procedure cgi_init;
  90. procedure cgi_deinit;
  91. implementation
  92. {$IFDEF OS2}
  93. function GetEnv (EnvVar: string): PChar;
  94. var P: PChar;
  95. begin
  96. EnvVar := EnvVar + #0;
  97. if DosScanEnv (@EnvVar [1], P) = 0 then GetEnv := P else GetEnv := nil;
  98. end;
  99. {$ENDIF OS2}
  100. {$ifdef win32}
  101. Var EnvP : PChar;
  102. EnvLen : Longint;
  103. OldExitProc : Pointer;
  104. function GetEnvironmentStrings : pchar; external 'kernel32' name 'GetEnvironmentStringsA';
  105. function FreeEnvironmentStrings(p : pchar) : longbool; external 'kernel32' name 'FreeEnvironmentStringsA';
  106. Procedure FInitWin32CGI;
  107. begin
  108. { Free memory }
  109. FreeMem (EnvP,EnvLen);
  110. ExitProc:=OldExitProc;
  111. end;
  112. Procedure InitWin32CGI;
  113. var s : String;
  114. i,len : longint;
  115. hp,p : pchar;
  116. begin
  117. { Make a local copy of environment}
  118. p:=GetEnvironmentStrings;
  119. hp:=p;
  120. envp:=Nil;
  121. envlen:=0;
  122. while hp[0]<>#0 do
  123. begin
  124. len:=strlen(hp);
  125. hp:=hp+len+1;
  126. EnvLen:=Envlen+len+1;
  127. end;
  128. GetMem(EnvP,Envlen);
  129. Move(P^,EnvP^,EnvLen);
  130. FreeEnvironmentStrings(p);
  131. OldExitProc:=ExitProc;
  132. ExitProc:=@FinitWin32CGI;
  133. end;
  134. Function GetEnv(envvar: string): pchar;
  135. { Getenv that can return environment vars of length>255 }
  136. var s : String;
  137. i,len : longint;
  138. hp : pchar;
  139. begin
  140. s:=Envvar+#0;
  141. getenv:=Nil;
  142. hp:=envp;
  143. while hp[0]<>#0 do
  144. begin
  145. len:=strlen(hp);
  146. i:=Longint(strscan(hp,'='))-longint(hp);
  147. if StrLIComp(@s[1],HP,i-1)=0 then
  148. begin
  149. Len:=Len-i;
  150. getmem (getenv,len);
  151. Move(HP[I+1],getenv^,len+1);
  152. break;
  153. end;
  154. { next string entry}
  155. hp:=hp+len+1;
  156. end;
  157. end;
  158. {$endif}
  159. {$ifdef GO32V2}
  160. Function GetEnv(envvar: string): pchar;
  161. var
  162. hp : ppchar;
  163. hs : string;
  164. eqpos : longint;
  165. begin
  166. envvar:=upcase(envvar);
  167. hp:=envp;
  168. getenv:=nil;
  169. while assigned(hp^) do
  170. begin
  171. hs:=strpas(hp^);
  172. eqpos:=pos('=',hs);
  173. if copy(hs,1,eqpos-1)=envvar then
  174. begin
  175. getenv:=hp^+eqpos;
  176. exit;
  177. end;
  178. inc(hp);
  179. end;
  180. end;
  181. {$endif}
  182. var
  183. done_init : boolean;
  184. procedure set_content(ctype: string);
  185. begin
  186. writeln('Content-Type: ',ctype);
  187. writeln;
  188. end;
  189. function http_request_method: pchar;
  190. begin
  191. http_request_method :=getenv('REQUEST_METHOD');
  192. end;
  193. function http_referer: pchar;
  194. begin
  195. http_referer :=getenv('HTTP_REFERER');
  196. end;
  197. function http_useragent: pchar;
  198. begin
  199. http_useragent :=getenv('HTTP_USER_AGENT');
  200. end;
  201. function hexconv(h1,h2: char): char;
  202. var
  203. cnt : byte;
  204. thex : byte;
  205. begin
  206. for cnt :=0 to 15 do if upcase(h1)=hextable[cnt] then thex := cnt * 16;
  207. for cnt :=0 to 15 do if upcase(h2)=hextable[cnt] then thex := thex + cnt;
  208. hexconv := chr(thex);
  209. end;
  210. procedure def_uncgi_error(const pname,perr: string);
  211. begin
  212. set_content('text/html');
  213. writeln('<html><head><title>UNCGI ERROR</title></head>');
  214. writeln('<body>');
  215. writeln('<center><hr><h1>UNCGI ERROR</h1><hr></center><br><br>');
  216. writeln('UnCgi encountered the following error: <br>');
  217. writeln('<ul><br>');
  218. writeln('<li> procedure: ',pname,'<br>');
  219. writeln('<li> error: ',perr,'<br><hr>');
  220. writeln(
  221. '<h5><p><i>uncgi (c) ',uncgi_year,' ',maintainer_name,
  222. { skelet fix }
  223. '<a href="mailto:',maintainer_email,'">',
  224. maintainer_email,'</a></i></p></h5>');
  225. writeln('</body></html>');
  226. halt;
  227. end;
  228. var gv_cnt:word;
  229. function get_next_value(id: pchar): pchar;
  230. var
  231. cnt : word;
  232. begin
  233. if gv_cnt<=query_read then inc(gv_cnt);
  234. get_next_value:=Nil;
  235. if done_init then
  236. for cnt :=gv_cnt to query_read do
  237. if strcomp(strupper(id),strupper(query_array[1,cnt]))=0 then begin
  238. get_next_value := query_array[2,cnt];
  239. gv_cnt:=cnt;
  240. exit;
  241. end;
  242. end;
  243. function get_value(id: pchar): pchar;
  244. begin
  245. gv_cnt:=0;
  246. get_value:=get_next_value(id)
  247. end;
  248. Function UnEscape(QueryString: PChar): PChar;
  249. var
  250. qunescaped : pchar;
  251. sptr : longint;
  252. cnt : word;
  253. qslen : longint;
  254. begin
  255. qslen:=strlen(QueryString);
  256. if qslen=0 then
  257. begin
  258. Unescape:=#0;
  259. get_nodata:=true;
  260. exit;
  261. end
  262. else
  263. get_nodata :=false;
  264. { skelet fix }
  265. getmem(qunescaped,qslen+1);
  266. if qunescaped=nil then
  267. begin
  268. writeln ('Oh-oh');
  269. halt;
  270. end;
  271. sptr :=0;
  272. for cnt := 0 to qslen do
  273. begin
  274. case querystring[cnt] of
  275. '+': qunescaped[sptr] := ' ';
  276. '%': begin
  277. qunescaped[sptr] :=
  278. hexconv(querystring[cnt+1], querystring[cnt+2]);
  279. inc(cnt,2);
  280. end;
  281. else
  282. qunescaped[sptr] := querystring[cnt];
  283. end;
  284. inc(sptr);
  285. { skelet fix }
  286. qunescaped[sptr]:=#0;
  287. end;
  288. UnEscape:=qunescaped;
  289. end;
  290. Function Chop(QunEscaped : PChar) : Longint;
  291. var
  292. qptr : word;
  293. cnt : word;
  294. qslen : longint;
  295. begin
  296. qptr := 1;
  297. qslen:=strlen(QUnescaped);
  298. query_array[1,qptr] := qunescaped;
  299. for cnt := 0 to qslen-1 do
  300. case qunescaped[cnt] of
  301. '=': begin
  302. qunescaped[cnt] := #0;
  303. { save address }
  304. query_array[2,qptr] := @qunescaped[cnt+1];
  305. end;
  306. '&': begin
  307. qunescaped[cnt] := #0;
  308. { Unescape previous one. }
  309. query_array[2,qptr]:=unescape(query_array[2,qptr]);
  310. inc(qptr);
  311. query_array[1,qptr] := @qunescaped[cnt+1];
  312. end;
  313. end; { Case }
  314. { Unescape last one. }
  315. query_array[2,qptr]:=unescape(query_array[2,qptr]);
  316. Chop :=qptr;
  317. end;
  318. procedure cgi_read_get_query;
  319. var
  320. querystring : pchar;
  321. qslen : longint;
  322. begin
  323. querystring :=strnew(getenv('QUERY_STRING'));
  324. if querystring<>NIL then
  325. begin
  326. qslen :=strlen(querystring);
  327. if qslen=0 then
  328. begin
  329. get_nodata :=true;
  330. exit;
  331. end
  332. else
  333. get_nodata :=false;
  334. query_read:=Chop(QueryString);
  335. end;
  336. done_init :=true;
  337. end;
  338. procedure cgi_read_post_query;
  339. var
  340. querystring : pchar;
  341. qslen : longint;
  342. sptr : longint;
  343. clen : string;
  344. ch : char;
  345. begin
  346. if getenv('CONTENT_LENGTH')<>Nil then
  347. begin
  348. clen:=strpas (getenv('CONTENT_LENGTH'));
  349. val(clen,qslen);
  350. if upcase(strpas(getenv('CONTENT_TYPE')))='APPLICATION/X-WWW-FORM-URLENCODED'
  351. then
  352. begin
  353. getmem(querystring,qslen+1);
  354. sptr :=0;
  355. while sptr<>qslen do
  356. begin
  357. read(ch);
  358. pchar(longint(querystring)+sptr)^ :=ch;
  359. inc(sptr);
  360. end;
  361. { !!! force null-termination }
  362. pchar(longint(querystring)+sptr)^ :=#0;
  363. query_read:=Chop(QueryString);
  364. end;
  365. end;
  366. done_init :=true;
  367. end;
  368. procedure cgi_init;
  369. var
  370. rmeth : pchar;
  371. begin
  372. query_read:=0;
  373. rmeth :=http_request_method;
  374. if rmeth=nil then
  375. begin
  376. uncgi_error('cgi_init()','No REQUEST_METHOD passed from server!');
  377. exit;
  378. end;
  379. if strcomp('POST',rmeth)=0 then cgi_read_post_query else
  380. if strcomp('GET',rmeth)=0 then cgi_read_get_query else
  381. uncgi_error('cgi_init()','No REQUEST_METHOD passed from server!');
  382. end;
  383. procedure cgi_deinit;
  384. begin
  385. done_init :=false;
  386. query_read :=0;
  387. fillchar(query_array,sizeof(query_array),0);
  388. end;
  389. begin
  390. {$ifdef win32}
  391. InitWin32CGI;
  392. {$endif}
  393. uncgi_error:=@def_uncgi_error;
  394. done_init :=false;
  395. fillchar(query_array,sizeof(query_array),0);
  396. end.
  397. {
  398. HISTORY
  399. $Log$
  400. Revision 1.2 2002-03-01 10:57:03 peter
  401. * get_next_value patch from Skelet
  402. Revision 1.1 2002/01/29 17:55:23 peter
  403. * splitted to base and extra
  404. Revision 1.7 2001/07/08 13:21:12 marco
  405. * Unit linux was imported twice under FreeBSD (1.0 still defines Linux!)
  406. Revision 1.6 2001/04/08 12:27:55 peter
  407. * made it compilable with both 1.0.x and 1.1
  408. Revision 1.5 2001/01/23 20:54:18 hajny
  409. * OS/2 GetEnv correction
  410. Revision 1.4 2001/01/21 21:38:52 marco
  411. * renamefest in packages
  412. Revision 1.3 2000/12/19 00:47:11 hajny
  413. + OS/2 support added
  414. Revision 1.2 2000/07/13 11:33:32 michael
  415. + removed logs
  416. }