2014-10-08 58 views
0

问题陈述:读写文件内容从HTTP POST数据在bash

我试图使用HTTP POST请求,通过上传一个HTML格式的文件,然后将其写入一个文件名为configuration.xml中在我的本地服务器上。我只能使用服务器的库存功能,因此,尽可能多地使用cURL,PHP,Perl或任何我必须在服务器上安装的服务。我试过的做法是让HTML表单打开一个CGI文件作为表单动作,并且这个CGI文件所做的就是用适当的HTML格式运行Bash脚本。我会直接从HTML表单运行Bash脚本,但是我的研究让我相信,如果不编辑.htaccess或其他hacky替代品,这不是不可能的,但这不是我想要去的道路。 (如果这可以以合理的方式完成,请赐教!)无论如何,我能够成功运行Bash脚本。我知道这是因为我在脚本中放置了“touch configuration.xml”命令,并且每次都会创建它。我的脚本也能够确定它是一个HTTP Post,如浏览器中的回显文本所示,但是我似乎无法正确读取文件中的任何数据。我尝试回显数据并将读取的数据重定向到一个文件,但浏览器中没有出现任何内容,也没有写入我指定的文件。这很好,可能是我不知道Bash脚本编写得不够好,或者是一些愚蠢的东西,但我真的不知道如何从这里开始。

代码:

UploadToServer.html:

<form action="run_script.cgi" method="POST" enctype="multipart/form-data"> 
    <input type="file" name="file" /> 
    <input type="submit" name="submit" value="Submit"> 
</form> 

run_script.c:

注:我编译这一个CGI文件用以下命令:gcc run_script.c -o run_script.cgi

#include <stdlib.h> 
#include <stdio.h> 

int main() { 
    system("./test.sh &"); 
    printf("Content-Type: text/html\r\n\r\n"); 
    printf(""); // print blank line for proper HTML header formatting 
    printf("<html>\n"); 
    printf("</HTML>\n"); 
} 

test.sh:

非注释的代码在第二if语句是从here。评论的代码是从here

#!/bin/bash 

touch configuration.xml 

if [[ $REQUEST_METHOD = 'POST' ]]; then 
echo "this is a post!" 
    if [ "$CONTENT_LENGTH" -gt 0 ]; then 
echo "entered second if statement!" 
#  read -n $CONTENT_LENGTH POST_DATA <&0 
#  echo "$CONTENT_LENGTH" 
     while read line 
      do eval "echo ${line}" 
     done 
    fi 
fi 

我也试过在this post第三代码块的方法,但没有得到任何输出。我也查看了this post,但它似乎并没有像我需要的那样从文件中获取所有数据。我也尝试过使用像这篇文章中建议的CGI文件(_http://blog.purplepixie.org/2013/08/cc-cgi-file-upload/),但是,再次没有输出。当我尝试新事物时,我一直在浏览Apache错误日志,并且没有出现错误。

任何人有什么想法,我可能做错了什么?有不同的方法值得研究吗?任何建议,非常感谢!

+1

请注意bash脚本中的echo语句:它们是在C代码的http头之前发出的,因此您的浏览器会感到困惑。 – 2014-10-09 13:28:32

+0

@glennjackman:我将'printf(“ \ n”);'移到'system'调用之前的行,但是我的浏览器显示内部服务器错误,并且在Apache错误日志中出现以下错误:脚本标题。 Bad header = '。我原来把标签的printf放在相应的结束标签之前,以摆脱这个确切的格式错误的标题错误。有没有更好的/正确的方法来摆脱这个错误,并让我的回声语句被包含在我的C代码的头文件中?这是你指的还是我的方式? – 2014-10-13 21:30:31

+1

“内容类型”标题**必须是**。 – 2014-10-13 23:33:48

回答

0

我想出了如何做到这一点,在朋友的帮助下完成。我最终在CGI脚本中完成了这一切,并且在Bash组件之前。虽然这不是我在原始问题中所要求的,但它为我完成了这项工作,而这正是问题所在。

以下是我现在用成功写入服务器上的文件的C代码:

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 

void print_empty_html_page(); 

int main() { 
    char * req_method_str = getenv("REQUEST_METHOD"); 

    if (req_method_str != NULL) { 
     if (strcmp(req_method_str, "POST") == 0) { 
      // process POST arguments 
      char * len_str = getenv("CONTENT_LENGTH"); 

      if (len_str != NULL) { 
       int len = atoi(len_str); 

       if (len > 0) { 
        FILE * fp; 
        fp = fopen("file.xml", "w"); 

        char * postdata = malloc((len + 1) * sizeof(char)); 
        fread(postdata, sizeof(char), len, stdin); 
        postdata[len] = '\0'; 
        fprintf(fp, "%s\n", postdata); 

        free(postdata); 
        fclose(fp); 
       } 

       system("sed -e '/Content/d' -e '/[-][-][*][*][*][*][*]/d' -e '/^[s]*$/d' -e '/WebKitFormBoundary/d' -e '/Submit/d' <file.xml> file_trimmed.xml"); 
       system("rm file.xml"); 
      } 
     } 
    } 
    print_empty_html_page(); 

    return 0; 
} 

void print_empty_html_page() { 

    // Send the content type, letting the browser know this is HTML 
    printf("Content-type: text/html\r\n\r\n"); 
    // Header information that prevents browser from caching 
    printf(
      "<META HTTP-EQUIV=\"CACHE-CONTROL\" CONTENT=\"NO-CACHE, NO-STORE\">\r\n\r\n"); 
    // Top of the page 
    printf("<html>\n"); 
    printf("<BODY>\n"); 

    // Finish up the page 
    printf("</BODY></html>\n"); 
} 

注:此方法写入整个HTTP POST到文件“file.xml” 。系统对'sed'的调用是从HTTP POST中删除与上传的文件中的实际数据不符的标签。如果您需要检查其他不需要的行,只需在该sed调用中添加另一个-e '/<line_with_expression_to_delete>/d',其中line_with_expression_to_delete是要匹配的表达式,然后删除包含该表达式的所有行。根据我的研究,我无法弄清楚如何删除新上传文件中的所有空白行,即使'/^[s]*$/d'应该这样做。必须考虑更多...

另请注意:此方法仅适用于上传文本文件。它不适用于其他文件类型,如JPEG或OGG。

希望这可以帮助一些其他人有同样的问题。如果您有任何问题,请告诉我。