2014-09-30 53 views
0

這是用於Web服務器分配的,這是我希望實現的一個額外功能。我想確保客戶端無法在服務器根目錄之上指定文件。確定兩個目錄之間的相對位置

例如,假設我有一個文件夾「上方」,並且在「上面」中,我有www。我在服務器中將根目錄設置爲/above/www,因此服務器應該能夠訪問/above/www內的任何內容。也讓我說above,所以/above/a1.txt,我不希望客戶端能夠執行GET /../a1.txt HTTP/1.0並獲得該文件的訪問權限。

我有90%的服務器實現,我只需要確定一個文件是否在文件系統樹中給定的目錄之上或者是否在下面。除了計算../字符串以外,我想不出一個超級簡單的方法,如果有更多的字符串比文件夾更多,我就在我的根目錄之上。

我正在運行linux,並且C++ 11是可以接受的。

+0

所以,總而言之,你想要的東西比計數更容易* – 2014-09-30 22:50:52

+0

我只是想知道是否有一個函數存在,在我執行它之前就做了我想要的。 – Evan 2014-09-30 22:53:01

+0

我以爲例如Apache已經這樣做了? – 2014-09-30 22:55:50

回答

0

使用boost::filesystem::path(relativePath).absolute().parent_path().string()獲取relativePath所代表的文件所在目錄的絕對路徑。現在,您可以簡單地檢查"/above/www"是該目錄的前綴。

0

我完成任務的方法是使用兩個for循環和strtok。 這可能不是最C++的答案,但它的工作原理。

bool within_dir(const char* path, const char* root_dir) 
{ 

    assert(path != NULL); 
    assert(root_dir != NULL); 
    char *fname_dup, *root_dup, *token; 
    int root_value, path_value; 

    // Duplicate char arrays so strtok doesn't damage the originals 
    fname_dup = (char*)malloc(sizeof(char) * strlen(path) + 1); 
    assert(fname_dup != NULL); 
    bzero(fname_dup, sizeof(char) * strlen(path) +1); 
    strncpy (fname_dup, path, sizeof(char) * strlen(path)); 

    root_dup = (char*)malloc(sizeof(char) * strlen(root_dir) + 1); 
    assert(root_dup != NULL); 
    bzero(root_dup, sizeof(char) * strlen(root_dir)+ 1); 
    strncpy(root_dup, root_dir, sizeof(char) * strlen(root_dir)); 

    // Count root directory 
    for (root_value = 0, token = strtok(root_dup, "/"); 
        token != NULL; 
        token = strtok(NULL, "/")) 
    {           
      if (strcmp(token, "..") == 0) 
        root_value--; 
      else 
        root_value++; 
    } 

    // Count and compare path value to root value 
    for (path_value = 0, token = strtok(fname_dup, "/"); 
        token != NULL; 
        token = strtok(NULL, "/")) 
    { 
      if (strcmp(token, "..") == 0) 
      { 
        path_value--; 
        if (path_value < root_value) 
        { 
          free(root_dup); 
          free(fname_dup); 
          return false; 
        } 
      } 
      else 
        path_value++; 
    } 
    free(root_dup); 
    free(fname_dup); 
    return true; 

} 

基本上,代碼貫穿並計算根的「正面」或「負面」方式。上升到一個水平是負面的,下降是積極的。一旦知道根的值,如果文件路徑的值永遠低於根的值,我們知道文件路徑必須在根目錄之上至少一層,因此是無效的。因爲我們實際上並不關心實際值,所以只有當它從根目錄上層時,我們立即停止並返回false。如果文件路徑始終保持比根更積極的狀態,那麼filetree上的文件路徑將始終較低。不保證鏈接。