08
29

用pure C寫CGI的輔助工具-CGIC library

如何善用現有的library增快自己開發程式速度是現代工程師的課題,其實從我開始寫程式以來,大部份的動作,都是剪剪貼貼,看到不錯的演算法,就剪貼,看到能解決我問題的方案,也剪貼,我覺得只要能看得懂程式,就不算太嚴重的抄襲,甚至我可以補足這個程式某些沒有的功能,或加強程式的演算法,這些都能提昇我個人程設能力的credit

好了,廢話說太多了,這篇文章主要是介紹如何用c語言快速的寫出CGI程式,而我用的library就是大名鼎鼎的CGIC,這個library簡化了form與cgi溝通時所需要撰寫的複雜程序,工程師只要專注在不同type物件的name及value欄位即可

CGIC library使用方法非常簡單,下載完後,解開壓縮檔會看到兩個檔案分別是cgic.c和cgic.h,把它們跟你要寫的cgi程式擺在同一個資料夾下一起編譯即可,這邊舉個例子,假設我自寫的cgi檔名為test.c,則編譯時要下這樣的指令gcc –o test.cgi cgic.c test.c,test.c的內容如下範例

  1. #include <stdio.h> 
  2. #include "cgic.h" 
  3. #include <string.h> 
  4. #include <stdlib.h> 
  5. int cgiMain() 
  6. { 
  7. }

CGIC library提供很多的API,舉個例子,假設我今天要設定TextBox的值,並且讓cgi程式可把我設定的值印出來,那我的html表單可以設計如下

  1. <form method="post" enctype="multipart/form-data" action="http://192.168.15.26/cgi-bin/test.cgi"> 
  2. <p>Plaintext test:<input name="plaintext" size="80"> 
  3. </form>

而相對應的c程式可設計如下

  1. void handlePlainText() 
  2. { 
  3. char value[81];
  4.  
  5. cgiFormStringNoNewlines("plaintext", value, 81);
  6. fprintf(cgiOut, "Plaintext test:: ");
  7. cgiHtmlEscape(value);
  8. fprintf(cgiOut, "<BR>\n");
  9. }

從上例可以看到,用了CGIC library,我要做的事就很簡單了,只要呼叫3個函式,一切搞定

OK,介紹完基本的,就講比較難一點cookie設定範例,我html表單設計如下

  1. <form method="post" enctype="multipart/form-data" action="http://192.168.15.26/cgi-bin/test.cgi"> 
  2. <p>Cookie test(not work on every browser):
  3. <p>Cookie Name:<input name="cname" value=""> <p> 
  4. <p>Cookie Value:<input name="cvalue" value=""> <p> 
  5. </form>

而c程式可簡單分為兩個function,一個是設定cookie,另外一個是顯示我們所設定的cookie

設定cookie

  1. void CookieSet() 
  2. { 
  3. char cname[1024];
  4. char cvalue[1024];
  5. /* Must set cookies BEFORE calling cgiHeaderContentType */ 
  6. cgiFormString("cname", cname, sizeof(cname));
  7. cgiFormString("cvalue", cvalue, sizeof(cvalue));
  8. if (strlen(cname)) 
  9. { 
  10. /* Cookie lives for one day (or until browser chooses
  11. to get rid of it, which may be immediately),
  12. and applies only to this script on this site. */ 
  13. cgiHeaderCookieSetString(cname, cvalue,86400, cgiScriptName, SERVER_NAME);
  14. } 
  15. }

顯示我們所設定的cookie

  1. void Cookies() 
  2. { 
  3. char **array, **arrayStep;
  4. char cname[1024], cvalue[1024];
  5. fprintf(cgiOut, "Cookies Submitted On This Call, With Values (Many Browsers NEVER Submit Cookies):<p>\n");
  6. if (cgiCookies(&array) != cgiFormSuccess) 
  7. { 
  8. return;
  9. } 
  10. arrayStep = array;
  11. fprintf(cgiOut, "<table border=1>\n");
  12. fprintf(cgiOut, "<tr><th>Cookie<th>Value</tr>\n");
  13. while (*arrayStep) 
  14. { 
  15. char value[1024];
  16. fprintf(cgiOut, "<tr>");
  17. fprintf(cgiOut, "<td>");
  18. cgiHtmlEscape(*arrayStep);
  19. fprintf(cgiOut, "<td>");
  20. cgiCookieString(*arrayStep, value, sizeof(value));
  21. cgiHtmlEscape(value);
  22. fprintf(cgiOut, "\n");
  23. arrayStep++;
  24. } 
  25. fprintf(cgiOut, "</table>\n");
  26. }

不過我覺得CGIC library最強的API是上傳檔案的API,我下面這個範例會把上傳的檔案擺在/tmp資料夾,所以在執行前請確定cgi檔有root權限,html的表單設計如下,記得enctype一定要設為"multipart/form-data"

  1. <form method="post" enctype="multipart/form-data" action="http://192.168.15.26/cgi-bin/test.cgi"> 
  2. <p>File Upload:<input type="file" name="file" value=""> (Select A Local File)<p> 
  3. </form>

而upload函式如下

  1. void File() 
  2. { 
  3. cgiFilePtr file;
  4. char name[1024];
  5. char contentType[1024];
  6. char buffer[1024];
  7. int size;
  8. int got;
  9. FILE *fp;
  10. char temp[256];
  11. int realwrite;
  12.  
  13. if (cgiFormFileName("file", name, sizeof(name)) != cgiFormSuccess) { 
  14. printf("<p>No file was uploaded.<p>\n");
  15. return;
  16. } 
  17. fprintf(cgiOut, "The filename submitted was: ");
  18. cgiHtmlEscape(name);
  19. sprintf(temp,"touch /tmp/%s",name);
  20. system(temp);
  21. fprintf(cgiOut, "<p>\n");
  22. cgiFormFileSize("file", &size);
  23. fprintf(cgiOut, "The file size was: %d bytes<p>\n", size);
  24. cgiFormFileContentType("file", contentType, sizeof(contentType));
  25. fprintf(cgiOut, "The alleged content type of the file was: ");
  26. cgiHtmlEscape(contentType);
  27. fprintf(cgiOut, "<p>\n");
  28. if (cgiFormFileOpen("file", &file) != cgiFormSuccess) 
  29. { 
  30. fprintf(cgiOut, "Could not open the file.<p>\n");
  31. return;
  32. } 
  33. fprintf(cgiOut, "<pre>\n");
  34.  
  35. sprintf(temp,"/tmp/%s",name);
  36. fp=fopen(temp,"w");
  37.  
  38. while (cgiFormFileRead(file, buffer, sizeof(buffer), &got) ==cgiFormSuccess) 
  39. { 
  40.  
  41. fwrite(buffer,1,got,fp);
  42. //cgiHtmlEscapeData(buffer, got);
  43. //cgiHtmlEscapeData(buffer, got);
  44. } 
  45. fclose(fp);
  46. fprintf(cgiOut, "</pre>\n");
  47. cgiFormFileClose(file);
  48. }

我所有的範例請下載這個壓縮包,裡面包含所有的CGIC library API的測試,測試畫面如下圖

標籤: linux
評論: 0 | 引用: 0 | 閱讀: 13528
發表評論
暱 稱: 密 碼:
網 址: E - mail:
驗證碼: 驗證碼圖片 選 項:
頭 像:
內 容: