src/server/safs/pcheck.c

changeset 116
d7a186cf87f6
child 139
29ac9aed4889
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/safs/pcheck.c	Sun Oct 23 10:52:54 2016 +0200
@@ -0,0 +1,233 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ *
+ * THE BSD LICENSE
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer. 
+ * Redistributions in binary form must reproduce the above copyright notice, 
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution. 
+ *
+ * Neither the name of the  nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without 
+ * specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * open web server code from safs/pcheck.cpp
+ */
+
+#include "pcheck.h"
+
+#include "../util/pblock.h"
+
+/* --------------------------- pcheck_find_path --------------------------- */
+
+
+/*
+ * Takes a given path, and figures out if there is any path_info attached.
+ * If no explicit path_info was provided by nametrans, and the file doesn't 
+ * exist as specified, it tries to find it by groping through the filesystem.
+ * 
+ * This type of implicit path_info cannot be attached to directories. Such
+ * a request will be flagged as not found.
+ * 
+ * pb unused.
+ */
+
+static char* find_param(char *uri, char *param)
+{
+    // Find ;parameters on the end of uri
+    if (param > uri) {
+        if (*param == FILE_PATHSEP) {
+            --param;
+        }
+        while (param > uri && *param != FILE_PATHSEP && *param != ';') {
+            --param;
+        }
+        if (*param == ';') {
+            return param;
+        }
+    }
+
+    return NULL;
+}
+
+static PRBool set_path_info(Request *rq, char *uri, int path_info_depth)
+{
+    // Find trailing path components in uri, e.g. the "/baz;qux/quux" in
+    // "/cgi-bin/foo.pl;bar/baz;qux/quux" (here path_info_depth would be 2)
+    char *path_info = &uri[strlen(uri)];
+    while (path_info > uri && path_info_depth) {
+        --path_info;
+        if (*path_info == FILE_PATHSEP) {
+            --path_info_depth;
+        }
+    }
+
+    if (*path_info) {
+        pblock_nvinsert("path-info", path_info, rq->vars);
+        return PR_TRUE;
+    }
+
+    return PR_FALSE;
+}
+
+int pcheck_find_path(pblock *pb, Session *sn, Request *rq) 
+{
+    char *path = pblock_findkeyval (pb_key_path, rq -> vars);
+    char *path_info   = pblock_findkeyval (pb_key_path_info  , rq -> vars);
+    char *script_name = pblock_findkeyval (pb_key_script_name, rq -> vars);
+    //NSFCFileInfo *finfo = NULL;
+    struct stat *finfo;
+
+    rq->directive_is_cacheable = 1;
+
+    if (path_info != NULL || script_name != NULL || path == NULL)
+	return REQ_NOACTION;// ruslan: bail out right away for performance (no need to go into file cache)
+
+    if (!*path)
+        return REQ_NOACTION;
+
+    /*
+    if ((INTrequest_info_path(path, rq, NULL) == PR_SUCCESS))
+        return REQ_NOACTION;
+    */
+
+    rq->directive_is_cacheable = 0;
+
+    path_info = &path[strlen(path) - 1];
+
+    char *forward = pblock_findkeyval(pb_key_find_pathinfo_forward, rq->vars);
+    char *base = NULL;
+    if (forward) {
+        base   = pblock_findval("ntrans-base"  , rq -> vars);
+        if (!base) forward = NULL;
+    }
+
+    int path_info_depth = 0;
+    
+    if(!forward) {
+        while (1) {
+            /* Change all occurrences of '/' to FILE_PATHSEP for WIN32 */
+            for(  ; path_info != path; --path_info)
+                if (*path_info == FILE_PATHSEP)
+                    break;
+            for(  ; path_info != path; --path_info) {
+                ++path_info_depth;
+                if (*(path_info - 1) != FILE_PATHSEP)
+                    break;
+            }
+
+            if (path_info == path)
+                break;
+
+            *path_info = '\0';
+            //if ((INTrequest_info_path(path, rq, &finfo) == PR_SUCCESS) && finfo) {
+            if((finfo = request_stat_path(path, rq)) != NULL) {
+                //if (finfo->pr.type != PR_FILE_FILE) {
+                if(S_ISDIR(finfo->st_mode)) {
+                    *path_info = FILE_PATHSEP;
+                    if (set_path_info(rq, pblock_findkeyval(pb_key_uri, rq->reqpb), 0)) {
+                        free(finfo);
+                        return REQ_PROCEED;
+                    }
+                    break;
+                } else {
+                    set_path_info(rq, pblock_findkeyval(pb_key_uri, rq->reqpb), path_info_depth);
+                    free(finfo);
+                    return REQ_PROCEED;
+                }
+            } else {
+                *path_info-- = FILE_PATHSEP;
+            }
+        }
+        /* This was changed to support virtual documents */
+        return REQ_NOACTION;
+    } else {
+        int baselen = strlen(base);
+        if (strncmp(path, base, baselen))
+            return REQ_NOACTION;
+
+        path_info = &path[baselen];
+        if (*path_info == '/')
+            path_info++;
+
+        while (1) {
+            for(  ; *path_info; ++path_info)
+                if (*path_info == FILE_PATHSEP)
+                    break;
+
+            if (!*path_info) {
+                if (set_path_info(rq, pblock_findkeyval(pb_key_uri, rq->reqpb), 0)) {
+                    return REQ_PROCEED;
+                }
+                break;
+            }
+
+            *path_info = '\0';
+            //if ((INTrequest_info_path(path, rq, &finfo) == PR_SUCCESS) && finfo) {
+            if((finfo = request_stat_path(path, rq)) != NULL) {
+                //if (finfo->pr.type != PR_FILE_FILE) {
+                if(S_ISDIR(finfo->st_mode)) {
+                    *path_info++ = FILE_PATHSEP;
+                } else {
+                    char *uri = pblock_findkeyval(pb_key_uri, rq->reqpb);
+                    *path_info = FILE_PATHSEP;
+    #ifdef XP_WIN32
+                    char *unmpath = pblock_findval("unmuri", rq->vars);
+                    if (unmpath) {
+                        char *nm = &path_info[strlen(path_info)-1];
+                        char *unm = &unmpath[strlen(unmpath)-1];
+                        while(nm != path_info && unm != unmpath) {
+                            if (*nm != *unm) {
+                                if (*unm == '\\' && *nm == '/')
+                                    *nm = *unm;
+                                else
+                                    PR_ASSERT(0);
+                            }
+                            nm--;
+                            unm--;
+                        }
+                        uri = unmpath;
+                    }
+    #endif
+                    char *t = path_info;
+                    for(; *t; ++t)
+                        if (*t == FILE_PATHSEP)
+                            ++path_info_depth;
+                    *path_info = '\0';
+                    set_path_info(rq, uri, path_info_depth);
+                    free(finfo);
+                    return REQ_PROCEED;
+                }
+                free(finfo);
+            }
+            else {
+               *path_info = FILE_PATHSEP;
+                break;
+            }
+        }
+
+        /* This was changed to support virtual documents */
+        return REQ_NOACTION;
+    }
+}

mercurial