C 编写自己的HTTP服务器-如何查找文件的相对路径

C 编写自己的HTTP服务器-如何查找文件的相对路径,c,httpserver,C,Httpserver,我目前正在用C编写一个基于UNIX套接字的HTTP服务器,我将实现GET请求的一部分,该部分检查请求的文件以确保它具有适当的权限 在我了解HTTP服务器之前,我设置了一个Apache服务器,据我所知,HTTP服务器只需查找一个目录即可找到请求的文件。我不知道这是否是因为服务器不知何故在目录外没有权限,或者它是否确实验证了路径以确保它在目录内 现在我要自己实现这个,我不知道如何正确处理这个问题。C中是否有一个函数允许我确定路径是否在给定目录中(例如Isfoo/bar/../../bazinside

我目前正在用C编写一个基于UNIX套接字的HTTP服务器,我将实现GET请求的一部分,该部分检查请求的文件以确保它具有适当的权限

在我了解HTTP服务器之前,我设置了一个Apache服务器,据我所知,HTTP服务器只需查找一个目录即可找到请求的文件。我不知道这是否是因为服务器不知何故在目录外没有权限,或者它是否确实验证了路径以确保它在目录内

现在我要自己实现这个,我不知道如何正确处理这个问题。C中是否有一个函数允许我确定路径是否在给定目录中(例如Is
foo/bar/../../baz
inside
foo/

在python中,我将使用
os.path.relpath
并检查结果是否以
开头,以确保路径不在给定目录之外


例如,如果目录是
/foo/bar/htdocs
,给定路径是
index.html/。/../passwords.txt
,我想要
。/passwords.txt
,因此,我可以从前面的
中看到该文件位于
/foo/bar/htdocs
目录之外。

您会惊讶于Python的I/O功能有多少直接映射到POSIX的功能。:)

换句话说,向上看

当POSIX为一个函数提供了更具描述性的名称,并包含了额外的字母时,这真是太棒了!:)

#包括
#包括
int main()
{ 
字符解析_路径[100];
实路径(“../”,已解析的路径);
printf(“\n%s\n”,解析路径);
返回0;
}

你可以试试。正如同一个ser(unwind)所回答的那样。

它的工作方式要简单得多:一旦服务器收到请求,它只会查看其htdoc(静态内容)目录以检查请求的资源是否存在:

char *htdoc = "/opt/server/htdoc"; // here a sub-directory of the server program
char *request = "GET /index.html"; // the client request
char *req_path = strchr(request, ' ') + 1; // the URI path

char filepath[512]; // build the file-system path
snprintf(filepath, sizeof(filepath) - 1, "%s/%s", htdos, req_path);

FILE *f = fopen(filepath, "r"); // try to open the file
...
请注意,此代码是不安全的,因为它不会通过包含“./”模式(和其他技巧)来检查请求是否进入文件系统。您还应该使用
stat()
确保该文件是常规文件,并且服务器具有读取该文件的权限

作为一个简单(但不完整)的解决方案,我决定写一点代码来检查文件路径中是否有

int is_valid_fname(char *fname) {
    char *it = fname;
    while(TRUE) {
        if (strncmp(it, "..", 2) == 0) {
            return FALSE;
        }
        it = strchr(it, '/');
        if (it == NULL) break;
        it++;
    }
    return TRUE;
}

没有C++?简单的ansi c?@RicardoOrtegaMagaña只是简单的ansi c,我的导师建议在作业中使用Java。我想你误解了我的问题,我想要一个特定目录的相对路径(例如,
htdocs
),这样我就可以确定文件路径是否正确。我需要一个从目录到给定相对路径的相对路径,我猜原来的问题不清楚,我会编辑。你的最后一段正是我试图解决的问题,哈哈。然后,你可以遵循我上面的指导方针,或者找到如何在开源Web服务器中完成。编写这样的代码不是一项简单的任务(特别是如果正确有效地完成的话),因此不能在这里合理地发布(太具体、太长、太复杂)。
int is_valid_fname(char *fname) {
    char *it = fname;
    while(TRUE) {
        if (strncmp(it, "..", 2) == 0) {
            return FALSE;
        }
        it = strchr(it, '/');
        if (it == NULL) break;
        it++;
    }
    return TRUE;
}