一个简单的基于microhttpd的httpd,有目录遍历问题。

#include <stdio.h>
#include <stdlib.h>
#include <microhttpd.h>
#include <cstring>
#include <string>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

/**
 * Simple HTTP Server
 * 编译: g++ -std=c++11 -o tt tt.cpp -lmicrohttpd
 */

class SimpleHttpServer {
public:
    SimpleHttpServer(const std::string& rootDir, const std::string& defaultDoc, int port)
        : root_dir_(rootDir), default_doc_(defaultDoc), port_(port), daemon_(nullptr) {}

    ~SimpleHttpServer() {
        Stop();
    }

    bool Start() {
        daemon_ = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION, port_,
                                   nullptr, nullptr,
                                   &requestHandler, this,
                                   MHD_OPTION_END);
        if (daemon_ == nullptr) {
            std::cerr << "Failed to start the HTTP server." << std::endl;
            return false;
        }
        return true;
    }

    void Stop() {
        if (daemon_ != nullptr) {
            MHD_stop_daemon(daemon_);
            daemon_ = nullptr;
        }
    }

private:
    static MHD_Result requestHandler(void* cls, struct MHD_Connection* connection,
                                     const char* url, const char* method,
                                     const char* version, const char* upload_data,
                                     size_t* upload_data_size, void** con_cls) {
        SimpleHttpServer* self = static_cast<SimpleHttpServer*>(cls);
        std::string full_path;
        if (url[strlen(self->root_dir_.c_str()) - 1] == '/') {
            full_path = self->root_dir_ + url;
        } else {
            full_path = self->root_dir_ + "/" + url;
        }
        struct stat file_stat;
        if (stat(full_path.c_str(), &file_stat) != 0) {
            return MHD_NO;
        }
        if (S_ISDIR(file_stat.st_mode)) {
            if (url[strlen(url) - 1] == '/') {
                full_path += self->default_doc_;
            } else {
                full_path += "/" + self->default_doc_;
            }
            if (stat(full_path.c_str(), &file_stat) != 0) {
                return MHD_NO;
            }
        }
        struct MHD_Response *response;
        MHD_Result ret;
        if (strcmp(method, "GET") == 0) {
            response = MHD_create_response_from_fd(file_stat.st_size, open(full_path.c_str(), O_RDONLY));
            if (response != nullptr) {
                ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
                MHD_destroy_response(response);
            } else {
                ret = MHD_queue_response(connection, MHD_HTTP_INTERNAL_SERVER_ERROR, nullptr);
            }
        } else {
            ret = MHD_queue_response(connection, MHD_HTTP_METHOD_NOT_ALLOWED, nullptr);
        }
        return ret;
    }
    std::string root_dir_;
    std::string default_doc_;
    int port_;
    struct MHD_Daemon* daemon_;
};

int main() {
    int port = 8701;
    SimpleHttpServer server("~/publish/www", "index.html", port);
    if (server.Start()) {
        printf("Server started on port %d\n", port);
        while (true) {
            sleep(1);
        }
    }
    return 0;
}