新入职的公司须要我在公司的板卡上开发一个CGI网页用于配置系统参数,减小了客户直接配置内核文件的复杂过程,html
主要功能要包括:java
1.CGI登陆(只有密码校验),linux
2.配置文件传输(CGI文件传输)浏览器
3.打开网页要读取本地文件显示当前配置参数服务器
4.下拉框动态显示当前选用的协议文件网络
5.CGI网页跳转,即登陆完成须要跳转至系统设置页面ui
作好的效果以下:this
登陆界面spa
系统配置页面,即登陆完成跳转页面以下:.net
下面详细描述具体实现
step1:
对于BOA服务器的移植网络上有众多文章,这里不在赘述,只晒出BOA.conf文件供参考,BOA.conf文件位于usr/local/boa
上图中代表了BOA文件夹位置以及咱们的索引网页维index,即若是配置好了BOA服务器,若是在浏览器输入开发板IP,将直接访问usr/local/boa/index.html文件
step2:第一个网页制做:登陆界面
登陆界面CGI程序只要捕获服务器发过来的密码数据便可,而后校验实现跳转,html代码以下:
皮肤代码设计CSS代码未上传,上图中采用的是GET通信,传输数据少于2k可用GET,CGI程序以下
#include <stdio.h> #include <stdlib.h> #include <string.h> int main( int argc, char *argv[] ) { char *UserInput = NULL; // index the user input data. char *request_method = NULL; //index the html transfer type. int data_len = 0; // index the input data's length. printf("Content-type:text/html;charset=utf-8\n\n"); //response header. printf("\n"); // HTML page header. printf("<html><head>"); printf("<title>%s</title></head>", "Login Err"); printf("<body>"); if( ! getenv("REQUEST_METHOD") ) { printf("No client request from user !\n"); return -1; } request_method = getenv("REQUEST_METHOD"); // trans-type. // trans-type : GET if( ! strcmp( request_method, "GET" ) ) { if( getenv( "QUERY_STRING" ) ) { UserInput = getenv( "QUERY_STRING" ); } data_len = strlen( UserInput ); if( NULL == UserInput || 0 == data_len ) { printf( "There's no input data !\n" ); return -1; } UserInput[data_len] = '\0'; //printf("method = %s, data_len = %d<br>", request_method, data_len); //printf("data: %s", UserInput); if(!strcmp(&UserInput[7],"1357")) { printf("<meta http-equiv=\"Refresh\" content=\"0;URL=config.cgi\"> "); } else { printf("key err<BR>\nyou input key is:<BR>\n %s",&UserInput[7]); } } printf("</body></html>"); fflush( stdout ); return 0; }上图中,经过获取通信字串判断具体字符,而后实现跳转,登录成功则跳转至config.cgi页面,不然提示错误
step3:
对于登陆界面简单的数据处理不必用到CGIC库,可是对于配置界面须要进行复杂数据处理的页面,须要借助CGIC库的代码
1.移植CGIC库:http://blog.csdn.net/tiantang46800/article/details/7530930,具体见博客,不在赘述
咱们整个配置界面须要读取/data目录下的CONFIG文件,而后解析文件中的IP,PORT等一系列参数显示在网页上,因此HTML是动态的,须要每次启动浏览器读取CONFIG文件更新数据,在用户输入配置参数后咱们须要将用户设置信息回写到CONFIG文件而且下拉菜单须要动态显示当前/data文件夹底下有多少so协议文件,而后根据用户操做写入,具体流程图以下
这一步骤所有使用CGIC模拟网页,不在使用HTML语言编辑网页,具体代码以下
#include <stdio.h> #include "cgic.h" #include <string.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> #include<linux/reboot.h> #define SOFILENUM 10 #define SOFILELEN 20 char Ip[20]={0}; char Port[20]={0}; char Rs232[20]={0}; char Rs485[20]={0}; char HardVersion[20]={0}; char SoftVersion[20]={0}; char IMEI[20]={0}; char MAC[20]={0}; char Baudrate[20]={0}; char Lib[20]={0}; char Porttype[20]={0}; char TotleSoFile[10][20]; char TotleSoNum=0; const char *BaudrateTable[] = { "2400", "4800", "9600", "14400", "19200", "38400", "57600", "115200", "230400", "460800", "921600" }; char *porttable[]= { "1", "2" }; enum ErrLog { ErrSucceed, ErrOpenField, ErrNoFile }; char *ErrSoNews[]= { "", "通信文件上载失败", "" }; char *ErrUpNews[]= { "", "升级文件上载失败", "" }; char *ErrMD5News[]= { "", "MD5文件上载失败", "" }; /* Find the '=' pos and get the config dat */ static int DatPos(char *dat , int index ) { int i=0; if(index==0)//find the config file { while((*dat++)!='=') { i++; } return i; } else //find the *.so file { while(*dat&&*(dat+1)) { if(*dat=='s'&&*(dat+1)=='o') { return 1; } dat++; } return 0; } } /*Find How many So file */ void GetFileOfSo(void) { FILE *stream; FILE *wstream; char buf[1024]; memset( buf,0,sizeof(buf)); stream = popen( " ls /data/*.so", "r" ); wstream = fopen( "/data/Numberso.txt", "w+"); chmod(wstream ,777); fread( buf, sizeof(char), sizeof(buf), stream); fwrite( buf, 1, sizeof(buf), wstream ); pclose( stream ); fclose( wstream ); } void GetMAC(void) { FILE *stream; stream = popen( "cat /etc/mac", "r" ); fread( MAC, sizeof(char), sizeof(MAC), stream); pclose( stream ); } void GetSoFileList(void) { FILE *fd; TotleSoNum=0; char StrLine[1024]; int i; if((fd = fopen("/data/Numberso.txt","r")) == NULL) { return; } while (!feof(fd)) { fgets(StrLine,1024,fd); i=DatPos(StrLine,1); if(i==1) //find a so file { strcpy(TotleSoFile[TotleSoNum++], &StrLine[6]); } else { break; } } fclose(fd); } /*When open html we should read configfile to fix it*/ void ReadTandaConf(void) { FILE *fd; char StrLine[1024]; char ptr[20]; int i=0; if((fd = fopen("/data/Tanda.conf","r")) == NULL) { return; } while (!feof(fd)) { fgets(StrLine,1024,fd); if(StrLine[0]=='#'||StrLine[0]==' ') { continue; } else { i=DatPos(StrLine , 0); memset(ptr , 0 , sizeof(ptr)); strncpy(ptr , StrLine , 3); ptr[3]='\0'; if(!strcmp(ptr , "Har")) { strncpy(HardVersion,&StrLine[i+1],sizeof(HardVersion)); HardVersion[sizeof(HardVersion)-1]='\0'; continue; } if(!strcmp(ptr , "Sof")) { strncpy(SoftVersion,&StrLine[i+1],sizeof(SoftVersion)); SoftVersion[sizeof(SoftVersion)-1]='\0'; continue; } if(!strcmp(ptr , "IME")) { strncpy(IMEI,&StrLine[i+1],sizeof(IMEI)); IMEI[sizeof(IMEI)-1]='\0'; continue; } if(!strcmp(ptr , "ip=")) { strncpy(Ip,&StrLine[i+1],sizeof(Ip)); Ip[sizeof(Ip)-1]='\0'; continue; } if(!strcmp(ptr , "por")&&StrLine[4]=='=') { strncpy(Port,&StrLine[i+1],sizeof(Port)); Port[sizeof(Port)-1]='\0'; continue; } #if 1 if(!strcmp(ptr , "rs2")) { strncpy(Rs232,&StrLine[i+1],sizeof(Rs232)); Rs232[sizeof(Rs232)-1]='\0'; continue; } if(!strcmp(ptr , "rs4")) { strncpy(Rs485,&StrLine[i+1],sizeof(Rs485)); Rs485[sizeof(Rs485)-1]='\0'; continue; } #endif if(!strcmp(ptr , "bau")) { strncpy(Baudrate,&StrLine[i+1],sizeof(Baudrate)); Baudrate[sizeof(Baudrate)-1]='\0'; continue; } if(!strcmp(ptr , "pro")) { strncpy(Lib,&StrLine[i+3],sizeof(Lib)); Lib[sizeof(Lib)-1]='\0'; continue; } if(!strcmp(ptr , "por")&&StrLine[4]=='t')//porttype { strncpy(Porttype,&StrLine[i+1],sizeof(Porttype)); Porttype[sizeof(Porttype)-1]='\0'; continue; } } } fclose(fd); } void WriteConfDat(void) { FILE *fd; int SoChoice; int bauChoice; int portchoice; int i; ReadTandaConf(); cgiFormStringNoNewlines("ip", Ip, sizeof(Ip)); cgiFormStringNoNewlines("port", Port, sizeof(Port)); cgiFormRadio("porttype", porttable, 2, &portchoice, 0); cgiFormSelectSingleNormal("bau", BaudrateTable, 11, &bauChoice, 0); //printf("<p>bau=%s ,%d<p>\n",BaudrateTable[bauChoice],bauChoice); GetSoFileList(); cgiFormSelectSingle("net", TotleSoFile, TotleSoNum, &SoChoice, 0); fd=fopen("/data/Tanda.conf" ,"w"); if(fd) { fputs("###################################\n",fd); fputs("# Tanda Adapter Config File #\n",fd); fputs("###################################\n\n",fd); fputs("#HardVersion\nHardVersion=",fd); fputs(HardVersion, fd); fputs("\n\n",fd); fputs("#SoftVersion\nSoftVersion=",fd); fputs(SoftVersion, fd); fputs("\n\n",fd); fputs("#IMEI\nIMEI=",fd); fputs(IMEI, fd); fputs("\n\n",fd); fputs("Service IP\nip=",fd); fputs(Ip , fd); fputs("\n\n",fd); fputs("#Service Port\nport=",fd); fputs(Port , fd); fputs("\n\n",fd); fputs("#rs232port=/dev/ttymxc\nrs232port=",fd); fputs(Rs232, fd); fputs("\n\n",fd); fputs("#rs485port=/dev/ttymxc\nrs485port=",fd); fputs(Rs485, fd); fputs("\n\n",fd); fputs("#Baudrate\nbaudrate=",fd); if(bauChoice==0) fputs(Baudrate, fd); else fputs(BaudrateTable[bauChoice], fd); fputs("\n\n",fd); fputs("#protocolName\nprotocolName=./",fd); fputs(TotleSoFile[SoChoice] , fd); fputs("\n\n",fd); fputs("#Connect Port Select\nporttype=",fd); fputs(porttable[portchoice], fd); fputs("\n\n",fd); fclose(fd); } else { printf("err"); } } /*上载通信文件*/ enum ErrLog UpLoadsoFile(void) { cgiFilePtr file; FILE *fd; char name[1024]; char path[50]; char contentType[1024]; int size; unsigned int got; char *tmp = NULL; if (cgiFormFileName("sofile", name, sizeof(name)) != cgiFormSuccess) { return ErrNoFile; } //fprintf(cgiOut, "The filename submitted was: "); //cgiHtmlEscape(name); //fprintf(cgiOut, "<p>\n"); cgiFormFileSize("sofile", &size); //fprintf(cgiOut, "The file size was: %d bytes<p>\n", size); cgiFormFileContentType("sofile", contentType, sizeof(contentType)); //fprintf(cgiOut, "The alleged content type of the file was: "); //cgiHtmlEscape(contentType); //fprintf(cgiOut, "<p>\n"); //fprintf(cgiOut, "Of course, this is only the claim the browser made when uploading the file. Much like the filename, it cannot be trusted.<p>\n"); //fprintf(cgiOut, "The file's contents are shown here:<p>\n"); if (cgiFormFileOpen("sofile", &file) != cgiFormSuccess) { return ErrNoFile; } /*write file */ tmp=(char *)malloc(sizeof(char)*size); strcpy(path , "/data/"); strcat(path, name); fd=fopen(path ,"w+"); if(fd==NULL) { return ErrOpenField; } //fprintf(cgiOut, "<pre>\n"); while (cgiFormFileRead(file, tmp, size, &got) == cgiFormSuccess) { fwrite(tmp, size, sizeof(char), fd); //cgiHtmlEscapeData(tmp, size); } //fprintf(cgiOut, "</pre>\n"); cgiFormFileClose(file); free(tmp); fclose(fd); return ErrSucceed; } enum ErrLog UpLoadUpdateFile(void) { cgiFilePtr file; FILE *fd; char name[1024]; char path[50]; char contentType[1024]; int size; unsigned int got; char *tmp = NULL; if (cgiFormFileName("updatefile", name, sizeof(name)) != cgiFormSuccess) { return ErrNoFile; } cgiFormFileSize("updatefile", &size); cgiFormFileContentType("updatefile", contentType, sizeof(contentType)); if (cgiFormFileOpen("updatefile", &file) != cgiFormSuccess) { return ErrNoFile; } /*write file */ tmp=(char *)malloc(sizeof(char)*size); strcpy(path , "/data/update/"); strcat(path, name); fd=fopen(path ,"w+"); if(fd==NULL) { return ErrOpenField; } while (cgiFormFileRead(file, tmp, size, &got) == cgiFormSuccess) { fwrite(tmp, size, sizeof(char), fd); } cgiFormFileClose(file); free(tmp); fclose(fd); return ErrSucceed; } enum ErrLog UpLoadMD5File(void) { cgiFilePtr file; FILE *fd; char name[1024]; char path[50]; char contentType[1024]; int size; unsigned int got; char *tmp = NULL; if (cgiFormFileName("MD5file", name, sizeof(name)) != cgiFormSuccess) { return ErrNoFile; } //fprintf(cgiOut, "The filename submitted was: "); //cgiHtmlEscape(name); //fprintf(cgiOut, "<p>\n"); cgiFormFileSize("MD5file", &size); //fprintf(cgiOut, "The file size was: %d bytes<p>\n", size); cgiFormFileContentType("MD5file", contentType, sizeof(contentType)); //fprintf(cgiOut, "The alleged content type of the file was: "); //cgiHtmlEscape(contentType); //fprintf(cgiOut, "<p>\n"); //fprintf(cgiOut, "Of course, this is only the claim the browser made when uploading the file. Much like the filename, it cannot be trusted.<p>\n"); //fprintf(cgiOut, "The file's contents are shown here:<p>\n"); if (cgiFormFileOpen("MD5file", &file) != cgiFormSuccess) { return ErrNoFile; } /*write file */ tmp=(char *)malloc(sizeof(char)*size); strcpy(path , "/data/update/"); strcat(path, name); fd=fopen(path ,"w+"); if(fd==NULL) { return ErrOpenField; } //fprintf(cgiOut, "<pre>\n"); while (cgiFormFileRead(file, tmp, size, &got) == cgiFormSuccess) { fwrite(tmp, size, sizeof(char), fd); //cgiHtmlEscapeData(tmp, size); } //fprintf(cgiOut, "</pre>\n"); cgiFormFileClose(file); free(tmp); fclose(fd); return ErrSucceed; } void SubmitHandle(void) { volatile int i; system("chmod 777 /data"); system("chmod 777 /data/update"); i=UpLoadsoFile(); printf("%s",ErrSoNews[i]); printf("<BR>\n"); i=UpLoadUpdateFile(); printf("%s",ErrUpNews[i]); printf("<BR>\n"); i=UpLoadMD5File(); printf("%s",ErrMD5News[i]); printf("<BR>\n"); } void ShowIndex(void) { FILE *fd; char StrLine[1024]; int i=0; GetFileOfSo(); GetMAC(); ReadTandaConf(); fprintf(cgiOut, "<!-- 2.0: multipart/form-data is required for file uploads. -->"); fprintf(cgiOut, "<form method=\"POST\" enctype=\"multipart/form-data\" "); fprintf(cgiOut, " action=\""); cgiValueEscape(cgiScriptName); fprintf(cgiOut, "\">\n"); fprintf(cgiOut, "<p>\n"); fprintf(cgiOut ,"<table id=\"table\" cellpadding=\"5\" width=\"60%\" border=\"1px\" align=\"center\" border-radius=\"5px\">"); fprintf(cgiOut ,"<tr bgcolor=\"#E0F0F\"></tr><br>"); fprintf(cgiOut ,"<tr><td align=\"center\" width=\"20%\">硬件版本号:</td><td>%s</td></tr>",HardVersion); fprintf(cgiOut ,"<tr><td align=\"center\" width=\"20%\">软件版本号:</td><td>%s</td></tr>",SoftVersion); fprintf(cgiOut ,"<tr><td align=\"center\" width=\"20%\">MAC:</td><td>%s</td></tr>",MAC); fprintf(cgiOut ,"<tr><td align=\"center\" width=\"20%\">IMEI:</td><td>%s</td></tr>",IMEI); fprintf(cgiOut ,"<tr><td align=\"center\" width=\"20%\">服务器IP:</td><td><input name=\"ip\" value=%s size=\"30\"></td></tr>",Ip); fprintf(cgiOut ,"<tr><td align=\"center\" width=\"20%\">端口号:</td><td><input name=\"port\" value=%s size=\"30\"></td></tr>",Port); fprintf(cgiOut ,"<tr><td align=\"center\" width=\"20%\">通信接口选择:</td>"); if(Porttype[0]=='1') { fprintf(cgiOut , "<td><input type=\"radio\" name=\"porttype\" value=\"1\" checked>rs232") ; fprintf(cgiOut , "<input type=\"radio\" name=\"porttype\" value=\"2\">rs485</td></tr>"); } else { fprintf(cgiOut , "<td><input type=\"radio\" name=\"porttype\" value=\"1\">rs232") ; fprintf(cgiOut , "<input type=\"radio\" name=\"porttype\" value=\"2\" checked>rs485</td></tr>"); } fprintf(cgiOut ,"<tr><td align=\"center\" width=\"20%\">波特率:</td><td><select name =\"bau\">"); fprintf(cgiOut ,"<option value=\"%s\">%s",Baudrate,Baudrate); for(i=0 ; i<11 ; i++) { if((Baudrate[0]==BaudrateTable[i][0])&&(Baudrate[1]==BaudrateTable[i][1])) { continue; } fprintf(cgiOut ,"<option value=\"%s\">%s",BaudrateTable[i],BaudrateTable[i]); } fprintf(cgiOut ,"<tr><td align=\"center\" width=\"20%\">通信文件上载:</td>"); fprintf(cgiOut , "<td align=\"left\" width=\"20%\"><div class=\"file-box\"> <input type='text' name='textfield' id='textfield' class='txt' /> "); fprintf(cgiOut , "<input type='button' class='btn' value='浏览' /> <input type=\"file\" name=\"sofile\" class=\"file\" id=\"fileField\" size=\"28\" onchange=\"document.getElementById('textfield').value=this.value\" /> </div> "); fprintf(cgiOut ,"<tr><td align=\"center\" width=\"20%\">通信协议:</td><td><select name =\"net\">"); fprintf(cgiOut ,"<option value=\"%s\">%s",Lib,Lib); if((fd = fopen("/data/Numberso.txt","r")) == NULL) { return; } #if 1 while (!feof(fd)) { fgets(StrLine,1024,fd); i=DatPos(StrLine,1); if(i==1) //find a so file { strcpy(TotleSoFile[TotleSoNum], &StrLine[6]); if(!strcmp(&StrLine[6] , Lib)) { continue; } fprintf(cgiOut ,"<option value=\"%s\">%s",TotleSoFile[TotleSoNum],TotleSoFile[TotleSoNum]); TotleSoNum++; } else { break; } } #endif fclose(fd); fprintf(cgiOut ,"</select></td></tr>"); fprintf(cgiOut ,"<tr><td align=\"center\" width=\"20%\">升级文件上载:</td>"); fprintf(cgiOut , "<td align=\"left\" width=\"20%\"><div class=\"file-box\"> <input type='text' name='textfield1' id='textfield1' class='txt' /> "); fprintf(cgiOut , "<input type='button' class='btn' value='浏览' /> <input type=\"file\" name=\"updatefile\" class=\"file\" id=\"fileField1\" size=\"28\" onchange=\"document.getElementById('textfield1').value=this.value\" /> </div> "); fprintf(cgiOut ,"<tr><td align=\"center\" width=\"20%\">MD5文件上载:</td>"); fprintf(cgiOut , "<td align=\"left\" width=\"20%\"><div class=\"file-box\"> <input type='text' name='textfield2' id='textfield2' class='txt' /> "); fprintf(cgiOut , "<input type='button' class='btn' value='浏览' /> <input type=\"file\" name=\"MD5file\" class=\"file\" id=\"fileField2\" size=\"28\" onchange=\"document.getElementById('textfield2').value=this.value\" /> </div> "); fprintf(cgiOut ,"<tr><td></td><td align=\"left\"><input class =\"button\" input type=\"submit\"name=\"Setting\" value=\"确认\" onclick=\"javaScript:alert('请求已发送')\">"); fprintf(cgiOut, "</table></form>\n"); } int cgiMain() { /* Send the content type, letting the browser know this is HTML */ //cgiHeaderContentType("text/html charset=UTF-8"); printf("Content-type:text/html;charset=utf-8\n\n"); /* Top of the page */ fprintf(cgiOut, "<HTML><HEAD>\n"); fprintf(cgiOut, "<TITLE>适配器配置</TITLE>\n"); fprintf(cgiOut , "<style>#table{border-radius:20px;border:0px;background:#CCCCCC;}#table td{color:##00CED1;font-family:\"仿宋\";color:#666666;border:0px;}#h1{color:#CCCCCC;font-family:\"仿宋\";}"); fprintf(cgiOut, "input{font-family:\"仿宋\";height:30px;color:#0;border : 0;background:#F0FFFF;}.button{margin-right:10px;background:#666666;width:80px;border-radius:5px;color:#FAF0E6;}"); fprintf(cgiOut, ".button:active{background:#666666;}.file-box{ position:relative;width:340px;} .txt{ height:30px;; border:1px solid #CCCCCC; width:180px;} "); fprintf(cgiOut, ".btn{ background-color:#666666; border:1px solid #CDCDCD;height:30px; width:70px;} .file{ position:absolute; top:0; right:80px; height:30px; filter:alpha(opacity:0);opacity: 0;width:260px } </style>"); fprintf(cgiOut, "</HEAD>"); fprintf(cgiOut, "<BODY style=\"background:#666666\"><h1 id = \"h1\"align=\"center\"> </h1>"); if ((cgiFormSubmitClicked("Setting") == cgiFormSuccess)) { SubmitHandle(); WriteConfDat(); system("reboot"); } ShowIndex(); fprintf(cgiOut, "</BODY></HTML>\n"); return 0; }
打开网页须要从这个config文件读取相关信息到网页,同时须要读取/data文件夹底下有多少SO文件而且显示,data底下文件构造以下: