问题:
几个问题:
1、lighttpd作为服务器,如何实现CGI程序对开发板的IP、子网掩码等进行配置。
2、CGI登录怎么实现。
3、模版文件如何实现。通过CGI程序读取html文件后,动态替换其中的模板参数。
交叉编译:
./configure CC=arm-rockchip830-linux-uclibcgnueabihf-gcc --host=arm-openwrt-linux-muslgnueabi target=arm-linux --enable-utf8 --enable-unicode-properties --prefix=$(pwd)/install --without-pcre2 --without-zlib
修改modules.conf配置CGI
## ## plain old CGI (mod_cgi) ## include conf_dir + "/conf.d/cgi.conf"
修改/conf.d/cgi.conf
cgi.assign = ( ".pl" => "/usr/bin/perl", ".rb" => "/usr/bin/ruby", ".cgi" => "", ".erb" => "/usr/bin/eruby", ".py" => "/usr/bin/python" )
网页保存路径:lighttpd.conf 注释掉用户名配置
#server.username = "lighttpd" #server.groupname = "lighttpd" ## ## Document root ## server.document-root = server_root + "/htdocs"
启动:将install目录修改为lighttpd
/lighttpd/sbin/lighttpd -f /lighttpd/config/lighttpd.conf -m /lighttpd/lib
CGI程序保存路径,这个问题其实也好理解,http服务的网页根路径下,存放一个cgi-bin的路径,然后将cgi程序拷贝的这个路径下。
问题2:登录如何实现。
网页侧:
<div class="layui-container" style="margin-top: 20px;"> <form class="layui-form" action="/cgi-bin/login.cgi" method="POST"> <div class="layui-form-item"> <label class="layui-form-label">用户名</label> <div class="layui-input-block"> <input type="text" name="username" required lay-verify="required" placeholder="请输入用户名" autocomplete="off" class="layui-input"> </div> </div> <div class="layui-form-item"> <label class="layui-form-label">密码</label> <div class="layui-input-block"> <input type="password" name="password" id="password" required lay-verify="required" placeholder="请输入密码" autocomplete="off" class="layui-input"> </div> </div> <div class="layui-form-item"> <div class="layui-input-block"> <button class="layui-btn" lay-submit lay-filter="formDemo">登录</button> </div> </div> </form> </div>
CGI侧:login.c 编译命令:arm-openwrt-linux-muslgnueabi-gcc -o login.cgi login.c
#include <stdio.h> #include <stdlib.h> #include <string.h> // 函数:解码 URL 编码的字符串 void url_decode(char *str) { char *src = str; char *dst = str; while (*src) { if (*src == '+') { *dst = ' '; } else if (*src == '%' && src[1] && src[2]) { *dst = (char) strtol(src + 1, NULL, 16); src += 2; } else { *dst = *src; } src++; dst++; } *dst = '\0'; } // 解析 URL 编码的表单数据 void parse_form_data(char *data, char *username, char *password) { char *token; char *key, *value; #if 0 printf("<h1>Received Data:</h1>\n"); printf("<p>%s</p>\n", data); printf("<ul>\n"); printf("</ul>\n"); #endif char *saveptr; token = strtok_r(data, "&", &saveptr); while (token) { key = strtok(token, "="); value = strtok(NULL, "="); if (key && value) { url_decode(key); url_decode(value); //printf("<li><strong>%s:</strong> %s</li>\n", key, value); if (strcmp(key, "username") == 0) { strncpy(username, value, 50); } if (strcmp(key, "password") == 0) { strncpy(password, value, 50); } } token = strtok_r(NULL, "&", &saveptr); } } static char* readFileContents(const char* filename, size_t* fileSize) { if (filename == NULL){ return NULL; } // 打开文件 FILE* file = fopen(filename, "rb"); if (file == NULL) { perror("Failed to open file"); return NULL; } // 移动文件指针到末尾,获取文件大小 fseek(file, 0, SEEK_END); long size = ftell(file); if (size < 0) { perror("Failed to determine file size"); fclose(file); return NULL; } // 重置文件指针到文件开头 rewind(file); // 分配内存缓冲区 char* buffer = (char*)malloc(size + 128); // +1 是为了存储结尾的 '\0' if (buffer == NULL) { perror("Failed to allocate memory"); fclose(file); return NULL; } // 读取文件内容到缓冲区 size_t bytesRead = fread(buffer, 1, size, file); if (bytesRead != size) { perror("Failed to read the complete file"); free(buffer); fclose(file); return NULL; } // 添加字符串结束符(对于二进制文件可选) buffer[size] = '\0'; if (buffer[size -1] == '\n' || buffer[size -2] == '\n'){ if (buffer[size -2] == '\n'){ buffer[size -2] = '\0'; }else{ buffer[size -1] = '\0'; } } // 关闭文件 fclose(file); // 返回文件大小和内容 if (fileSize != NULL) { *fileSize = size; } return buffer; } int main() { // 获取请求方法 char *request_method = getenv("REQUEST_METHOD"); if (!request_method) { printf("Content-Type: text/html\r\n\r\n"); printf("<h1>Error: No request method.</h1>\n"); return 1; } char username[50] = {0}; char password[50] = {0}; if (strcmp(request_method, "GET") == 0) { // 处理 GET 请求 char *query_string = getenv("QUERY_STRING"); if (!query_string) { printf("Content-Type: text/html\r\n\r\n"); printf("<h1>Error: No form data received.</h1>\n"); return 1; } parse_form_data(query_string, username, password); } else if (strcmp(request_method, "POST") == 0) { // 处理 POST 请求 char *content_length_str = getenv("CONTENT_LENGTH"); if (!content_length_str) { printf("Content-Type: text/html\r\n\r\n"); printf("<h1>Error: No content length.</h1>\n"); return 1; } int content_length = atoi(content_length_str); char *data = malloc(content_length + 1); fread(data, 1, content_length, stdin); data[content_length] = '\0'; parse_form_data(data, username, password); free(data); } else { printf("Content-Type: text/html\r\n\r\n"); printf("<h1>Error: Unsupported request method.</h1>\n"); return 1; } // 简单的用户验证 if (strcmp(username, "admin") == 0 && strcmp(password, "admin") == 0) { // 登录成功,跳转到欢迎页面 //printf("Location: /home.html\r\n\r\n"); //回显home.html界面 char ip[128] = "\0"; char netmask[128] = "\0"; char gateway[128] = "\0"; size_t fileSize = 0; char *fileContent = readFileContents("/lighttpd/htdocs/cgi-bin/ip.config", &fileSize); const char *delimiter = "#"; if (fileContent != NULL){ //sscanf(fileContent, "%s#%s#%s", ip, netmask, gateway); // 使用 strtok 分割字符串 char *token = strtok(fileContent, delimiter); // 输出分割后的字符串 int count = 0; int i=0; while (token != NULL) { //printf("Part %d: %s\n", ++count, token); if (i==0){ sprintf(ip, "%s", token); }else if (i==1){ sprintf(netmask, "%s", token); }else if (i==2){ sprintf(gateway, "%s", token); }else{ } i++; token = strtok(NULL, delimiter); } } printf("Location: /home.html?ip=%s&netmask=%s&gateway=%s\r\n\r\n", ip, netmask, gateway ); if (fileContent!= NULL){ free(fileContent); } if (sipFileContent!= NULL){ free(sipFileContent); } } else { // 登录失败,显示错误信息 printf("Content-Type: text/html\r\n\r\n"); printf("<h1>Login Failed!</h1>\n"); printf("<p>Invalid %s or %s.</p>\n",username,password); printf("<p><a href='/index.html'>Try again</a></p>\n"); } return 0; }
问题3、模版文件如何实现。CGI程序读取html文件后,动态替换其中的模板参数。
html文件侧:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>CGI Form Example</title> </head> <body> <h1>Enter Your Details</h1> <form action="/cgi-bin/echo.cgi" method="post"> <label for="username">Username:</label> <input type="text" id="username" name="username" required><br><br> <label for="email">Email:</label> <input type="email" id="email" name="email" required><br><br> <input type="submit" value="Submit"> </form> </body> </html>
CGI程序侧:
#include <stdio.h> #include <stdlib.h> #include <string.h> // 替换字符串中的占位符 void replace_placeholder(char *str, const char *placeholder, const char *value) { char buffer[4096]; // 更大的缓冲区,防止溢出 char *pos; int placeholder_len = strlen(placeholder); int value_len = strlen(value); while ((pos = strstr(str, placeholder)) != NULL) { // 复制占位符之前的部分 strncpy(buffer, str, pos - str); buffer[pos - str] = '\0'; // 添加替换值 strcat(buffer, value); // 添加占位符之后的部分 strcat(buffer, pos + placeholder_len); // 将结果复制回原字符串 strcpy(str, buffer); } } int main() { // 设置 HTTP 响应头 printf("Content-Type: text/html\r\n\r\n"); // 获取查询字符串(GET 参数) char *query_string = getenv("QUERY_STRING"); if (!query_string) { printf("<h1>Error: No query string.</h1>\n"); return 1; } // 解析查询字符串 char username[50] = {0}; char email[50] = {0}; char *token; token = strtok(query_string, "&"); while (token != NULL) { if (strstr(token, "username=") == token) { strncpy(username, token + 9, 50); } else if (strstr(token, "email=") == token) { strncpy(email, token + 6, 50); } token = strtok(NULL, "&"); } // 读取 HTML 模板文件 FILE *file = fopen("/lighttpd/htdocs/home.html", "r"); if (!file) { printf("<h1>Error: Unable to open template file.</h1>\n"); return 1; } // 读取文件内容 char template[4096] = {0}; fread(template, 1, sizeof(template), file); fclose(file); // 替换占位符 replace_placeholder(template, "{{username}}", username); replace_placeholder(template, "{{email}}", email); // 输出动态生成的 HTML printf("%s", template); return 0; }
-------------------广告线---------------
项目、合作,欢迎勾搭,邮箱:promall@qq.com
本文为呱牛笔记原创文章,转载无需和我联系,但请注明来自呱牛笔记 ,it3q.com