Fossil SCM
Attempt to documentation and rationalize the "redirect:" CGI option.
Commit
95010490aad192923a9de0873f1ea0261641630842bc65d6e62ea00d26cb3453
Parent
09908ab05803834…
1 file changed
+46
-6
+46
-6
| --- src/main.c | ||
| +++ src/main.c | ||
| @@ -2031,20 +2031,47 @@ | ||
| 2031 | 2031 | /* If the CGI program contains one or more lines of the form |
| 2032 | 2032 | ** |
| 2033 | 2033 | ** redirect: repository-filename http://hostname/path/%s |
| 2034 | 2034 | ** |
| 2035 | 2035 | ** then control jumps here. Search each repository for an artifact ID |
| 2036 | -** or ticket ID that matches the "name" CGI parameter and for the | |
| 2037 | -** first match, redirect to the corresponding URL with the "name" CGI | |
| 2038 | -** parameter inserted. Paint an error page if no match is found. | |
| 2036 | +** or ticket ID that matches the "name" query parameter. If there is | |
| 2037 | +** no "name" query parameter, use PATH_INFO instead. If a match is | |
| 2038 | +** found, redirect to the corresponding URL. Substitute "%s" in the | |
| 2039 | +** URL with the value of the name query parameter before the redirect. | |
| 2039 | 2040 | ** |
| 2040 | 2041 | ** If there is a line of the form: |
| 2041 | 2042 | ** |
| 2042 | 2043 | ** redirect: * URL |
| 2043 | 2044 | ** |
| 2044 | -** Then a redirect is made to URL if no match is found. Otherwise a | |
| 2045 | -** very primitive error message is returned. | |
| 2045 | +** Then a redirect is made to URL if no match is found. If URL contains | |
| 2046 | +** "%s" then substitute the "name" query parameter. If REPO is "*" and | |
| 2047 | +** URL does not contains "%s" and does not contain "?" then append | |
| 2048 | +** PATH_INFO and QUERY_STRING to the URL prior to the redirect. | |
| 2049 | +** | |
| 2050 | +** If no matches are found and if there is no "*" entry, then generate | |
| 2051 | +** a primitive error message. | |
| 2052 | +** | |
| 2053 | +** USE CASES: | |
| 2054 | +** | |
| 2055 | +** (1) Suppose you have two related projects projA and projB. You can | |
| 2056 | +** use this feature to set up an /info page that covers both | |
| 2057 | +** projects. | |
| 2058 | +** | |
| 2059 | +** redirect: /fossils/projA.fossil /proj-a/info/%s | |
| 2060 | +** redirect: /fossils/projB.fossil /proj-b/info/%s | |
| 2061 | +** | |
| 2062 | +** Then visits to the /info/HASH page will redirect to the | |
| 2063 | +** first project that contains that hash. | |
| 2064 | +** | |
| 2065 | +** (2) Use the "*" form for to redirect legacy URLs. On the Fossil | |
| 2066 | +** website we have an CGI at http://fossil.com/index.html (note | |
| 2067 | +** ".com" instead of ".org") that looks like this: | |
| 2068 | +** | |
| 2069 | +** #!/usr/bin/fossil | |
| 2070 | +** redirect: * https://fossil-scm.org/home | |
| 2071 | +** | |
| 2072 | +** Thus requests to the .com website redirect to the .org website. | |
| 2046 | 2073 | */ |
| 2047 | 2074 | static void redirect_web_page(int nRedirect, char **azRedirect){ |
| 2048 | 2075 | int i; /* Loop counter */ |
| 2049 | 2076 | const char *zNotFound = 0; /* Not found URL */ |
| 2050 | 2077 | const char *zName = P("name"); |
| @@ -2068,11 +2095,24 @@ | ||
| 2068 | 2095 | db_close(1); |
| 2069 | 2096 | } |
| 2070 | 2097 | } |
| 2071 | 2098 | } |
| 2072 | 2099 | if( zNotFound ){ |
| 2073 | - cgi_redirectf(zNotFound /*works-like:"%s"*/, zName); | |
| 2100 | + Blob to; | |
| 2101 | + const char *z; | |
| 2102 | + if( strstr(zNotFound, "%s") ){ | |
| 2103 | + cgi_redirectf(zNotFound /*works-like:"%s"*/, zName); | |
| 2104 | + } | |
| 2105 | + if( strchr(zNotFound, '?') ){ | |
| 2106 | + cgi_redirect(zNotFound); | |
| 2107 | + } | |
| 2108 | + blob_init(&to, zNotFound, -1); | |
| 2109 | + z = P("PATH_INFO"); | |
| 2110 | + if( z && z[0]=='/' ) blob_append(&to, z, -1); | |
| 2111 | + z = P("QUERY_STRING"); | |
| 2112 | + if( z && z[0]!=0 ) blob_appendf(&to, "?%s", z); | |
| 2113 | + cgi_redirect(blob_str(&to)); | |
| 2074 | 2114 | }else{ |
| 2075 | 2115 | @ <html> |
| 2076 | 2116 | @ <head><title>No Such Object</title></head> |
| 2077 | 2117 | @ <body> |
| 2078 | 2118 | @ <p>No such object: <b>%h(zName)</b></p> |
| 2079 | 2119 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -2031,20 +2031,47 @@ | |
| 2031 | /* If the CGI program contains one or more lines of the form |
| 2032 | ** |
| 2033 | ** redirect: repository-filename http://hostname/path/%s |
| 2034 | ** |
| 2035 | ** then control jumps here. Search each repository for an artifact ID |
| 2036 | ** or ticket ID that matches the "name" CGI parameter and for the |
| 2037 | ** first match, redirect to the corresponding URL with the "name" CGI |
| 2038 | ** parameter inserted. Paint an error page if no match is found. |
| 2039 | ** |
| 2040 | ** If there is a line of the form: |
| 2041 | ** |
| 2042 | ** redirect: * URL |
| 2043 | ** |
| 2044 | ** Then a redirect is made to URL if no match is found. Otherwise a |
| 2045 | ** very primitive error message is returned. |
| 2046 | */ |
| 2047 | static void redirect_web_page(int nRedirect, char **azRedirect){ |
| 2048 | int i; /* Loop counter */ |
| 2049 | const char *zNotFound = 0; /* Not found URL */ |
| 2050 | const char *zName = P("name"); |
| @@ -2068,11 +2095,24 @@ | |
| 2068 | db_close(1); |
| 2069 | } |
| 2070 | } |
| 2071 | } |
| 2072 | if( zNotFound ){ |
| 2073 | cgi_redirectf(zNotFound /*works-like:"%s"*/, zName); |
| 2074 | }else{ |
| 2075 | @ <html> |
| 2076 | @ <head><title>No Such Object</title></head> |
| 2077 | @ <body> |
| 2078 | @ <p>No such object: <b>%h(zName)</b></p> |
| 2079 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -2031,20 +2031,47 @@ | |
| 2031 | /* If the CGI program contains one or more lines of the form |
| 2032 | ** |
| 2033 | ** redirect: repository-filename http://hostname/path/%s |
| 2034 | ** |
| 2035 | ** then control jumps here. Search each repository for an artifact ID |
| 2036 | ** or ticket ID that matches the "name" query parameter. If there is |
| 2037 | ** no "name" query parameter, use PATH_INFO instead. If a match is |
| 2038 | ** found, redirect to the corresponding URL. Substitute "%s" in the |
| 2039 | ** URL with the value of the name query parameter before the redirect. |
| 2040 | ** |
| 2041 | ** If there is a line of the form: |
| 2042 | ** |
| 2043 | ** redirect: * URL |
| 2044 | ** |
| 2045 | ** Then a redirect is made to URL if no match is found. If URL contains |
| 2046 | ** "%s" then substitute the "name" query parameter. If REPO is "*" and |
| 2047 | ** URL does not contains "%s" and does not contain "?" then append |
| 2048 | ** PATH_INFO and QUERY_STRING to the URL prior to the redirect. |
| 2049 | ** |
| 2050 | ** If no matches are found and if there is no "*" entry, then generate |
| 2051 | ** a primitive error message. |
| 2052 | ** |
| 2053 | ** USE CASES: |
| 2054 | ** |
| 2055 | ** (1) Suppose you have two related projects projA and projB. You can |
| 2056 | ** use this feature to set up an /info page that covers both |
| 2057 | ** projects. |
| 2058 | ** |
| 2059 | ** redirect: /fossils/projA.fossil /proj-a/info/%s |
| 2060 | ** redirect: /fossils/projB.fossil /proj-b/info/%s |
| 2061 | ** |
| 2062 | ** Then visits to the /info/HASH page will redirect to the |
| 2063 | ** first project that contains that hash. |
| 2064 | ** |
| 2065 | ** (2) Use the "*" form for to redirect legacy URLs. On the Fossil |
| 2066 | ** website we have an CGI at http://fossil.com/index.html (note |
| 2067 | ** ".com" instead of ".org") that looks like this: |
| 2068 | ** |
| 2069 | ** #!/usr/bin/fossil |
| 2070 | ** redirect: * https://fossil-scm.org/home |
| 2071 | ** |
| 2072 | ** Thus requests to the .com website redirect to the .org website. |
| 2073 | */ |
| 2074 | static void redirect_web_page(int nRedirect, char **azRedirect){ |
| 2075 | int i; /* Loop counter */ |
| 2076 | const char *zNotFound = 0; /* Not found URL */ |
| 2077 | const char *zName = P("name"); |
| @@ -2068,11 +2095,24 @@ | |
| 2095 | db_close(1); |
| 2096 | } |
| 2097 | } |
| 2098 | } |
| 2099 | if( zNotFound ){ |
| 2100 | Blob to; |
| 2101 | const char *z; |
| 2102 | if( strstr(zNotFound, "%s") ){ |
| 2103 | cgi_redirectf(zNotFound /*works-like:"%s"*/, zName); |
| 2104 | } |
| 2105 | if( strchr(zNotFound, '?') ){ |
| 2106 | cgi_redirect(zNotFound); |
| 2107 | } |
| 2108 | blob_init(&to, zNotFound, -1); |
| 2109 | z = P("PATH_INFO"); |
| 2110 | if( z && z[0]=='/' ) blob_append(&to, z, -1); |
| 2111 | z = P("QUERY_STRING"); |
| 2112 | if( z && z[0]!=0 ) blob_appendf(&to, "?%s", z); |
| 2113 | cgi_redirect(blob_str(&to)); |
| 2114 | }else{ |
| 2115 | @ <html> |
| 2116 | @ <head><title>No Such Object</title></head> |
| 2117 | @ <body> |
| 2118 | @ <p>No such object: <b>%h(zName)</b></p> |
| 2119 |