這篇文章主要是介紹如何用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的內容如下範例

#include <stdio.h> 
#include "cgic.h" 
#include <string.h> 
#include <stdlib.h> 
int cgiMain() 
{ 
}

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

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

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

void handlePlainText() 
{ 
char value[81];
 
cgiFormStringNoNewlines("plaintext", value, 81);
fprintf(cgiOut, "Plaintext test:: ");
cgiHtmlEscape(value);
fprintf(cgiOut, "<BR>\n");
}

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

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

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

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

設定cookie

void CookieSet() 
{ 
char cname[1024];
char cvalue[1024];
/* Must set cookies BEFORE calling cgiHeaderContentType */ 
cgiFormString("cname", cname, sizeof(cname));
cgiFormString("cvalue", cvalue, sizeof(cvalue));
if (strlen(cname)) 
{ 
/* Cookie lives for one day (or until browser chooses
to get rid of it, which may be immediately),
and applies only to this script on this site. */ 
cgiHeaderCookieSetString(cname, cvalue,86400, cgiScriptName, SERVER_NAME);
} 
}

顯示我們所設定的cookie

void Cookies() 
{ 
char **array, **arrayStep;
char cname[1024], cvalue[1024];
fprintf(cgiOut, "Cookies Submitted On This Call, With Values (Many Browsers NEVER Submit Cookies):<p>\n");
if (cgiCookies(&array) != cgiFormSuccess) 
{ 
return;
} 
arrayStep = array;
fprintf(cgiOut, "<table border=1>\n");
fprintf(cgiOut, "<tr><th>Cookie<th>Value</tr>\n");
while (*arrayStep) 
{ 
char value[1024];
fprintf(cgiOut, "<tr>");
fprintf(cgiOut, "<td>");
cgiHtmlEscape(*arrayStep);
fprintf(cgiOut, "<td>");
cgiCookieString(*arrayStep, value, sizeof(value));
cgiHtmlEscape(value);
fprintf(cgiOut, "\n");
arrayStep++;
} 
fprintf(cgiOut, "</table>\n");
}

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

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

而upload函式如下

void File() 
{ 
cgiFilePtr file;
char name[1024];
char contentType[1024];
char buffer[1024];
int size;
int got;
FILE *fp;
char temp[256];
int realwrite;
 
if (cgiFormFileName("file", name, sizeof(name)) != cgiFormSuccess) { 
printf("<p>No file was uploaded.<p>\n");
return;
} 
fprintf(cgiOut, "The filename submitted was: ");
cgiHtmlEscape(name);
sprintf(temp,"touch /tmp/%s",name);
system(temp);
fprintf(cgiOut, "<p>\n");
cgiFormFileSize("file", &size);
fprintf(cgiOut, "The file size was: %d bytes<p>\n", size);
cgiFormFileContentType("file", contentType, sizeof(contentType));
fprintf(cgiOut, "The alleged content type of the file was: ");
cgiHtmlEscape(contentType);
fprintf(cgiOut, "<p>\n");
if (cgiFormFileOpen("file", &file) != cgiFormSuccess) 
{ 
fprintf(cgiOut, "Could not open the file.<p>\n");
return;
} 
fprintf(cgiOut, "<pre>\n");
 
sprintf(temp,"/tmp/%s",name);
fp=fopen(temp,"w");
 
while (cgiFormFileRead(file, buffer, sizeof(buffer), &got) ==cgiFormSuccess) 
{ 
 
fwrite(buffer,1,got,fp);
//cgiHtmlEscapeData(buffer, got);
//cgiHtmlEscapeData(buffer, got);
} 
fclose(fp);
fprintf(cgiOut, "</pre>\n");
cgiFormFileClose(file);
}

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

最後修改日期: 3 6 月, 2022

作者

留言

撰寫回覆或留言

發佈留言必須填寫的電子郵件地址不會公開。