从Bash中的HTTP Post数据读取和写入文件内容

时间:2014-10-08 18:08:28

标签: bash file-upload http-post cgi

问题陈述:

我正在尝试使用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 个答案:

答案 0 :(得分: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。

希望这有助于其他人遇到同样的问题。如果您有任何问题,请告诉我。