Fossil SCM
Add the "redirect:" option to CGI, to scan multiple repositories and redirect to the one that contains the requested artifact ID.
Commit
ef6e364866d76ce9114fc4281d464f023ceeecbc
Parent
2c8ea5ff2cc7b11…
1 file changed
+64
-3
+64
-3
| --- src/main.c | ||
| +++ src/main.c | ||
| @@ -1024,11 +1024,13 @@ | ||
| 1024 | 1024 | ** the values of standard CGI environment variables. |
| 1025 | 1025 | */ |
| 1026 | 1026 | void cmd_cgi(void){ |
| 1027 | 1027 | const char *zFile; |
| 1028 | 1028 | const char *zNotFound = 0; |
| 1029 | - Blob config, line, key, value; | |
| 1029 | + char **azRedirect = 0; /* List of repositories to redirect to */ | |
| 1030 | + int nRedirect = 0; /* Number of entries in azRedirect */ | |
| 1031 | + Blob config, line, key, value, value2; | |
| 1030 | 1032 | if( g.argc==3 && fossil_strcmp(g.argv[1],"cgi")==0 ){ |
| 1031 | 1033 | zFile = g.argv[2]; |
| 1032 | 1034 | }else{ |
| 1033 | 1035 | zFile = g.argv[1]; |
| 1034 | 1036 | } |
| @@ -1078,17 +1080,76 @@ | ||
| 1078 | 1080 | } |
| 1079 | 1081 | if( blob_eq(&key, "localauth") ){ |
| 1080 | 1082 | g.useLocalauth = 1; |
| 1081 | 1083 | continue; |
| 1082 | 1084 | } |
| 1085 | + if( blob_eq(&key, "redirect:") && blob_token(&line, &value) | |
| 1086 | + && blob_token(&line, &value2) ){ | |
| 1087 | + nRedirect++; | |
| 1088 | + azRedirect = fossil_realloc(azRedirect, 2*nRedirect*sizeof(char*)); | |
| 1089 | + azRedirect[nRedirect*2-2] = mprintf("%s", blob_str(&value)); | |
| 1090 | + azRedirect[nRedirect*2-1] = mprintf("%s", blob_str(&value2)); | |
| 1091 | + blob_reset(&value); | |
| 1092 | + blob_reset(&value2); | |
| 1093 | + continue; | |
| 1094 | + } | |
| 1083 | 1095 | } |
| 1084 | 1096 | blob_reset(&config); |
| 1085 | - if( g.db==0 && g.zRepositoryName==0 ){ | |
| 1097 | + if( g.db==0 && g.zRepositoryName==0 && nRedirect==0 ){ | |
| 1086 | 1098 | cgi_panic("Unable to find or open the project repository"); |
| 1087 | 1099 | } |
| 1088 | 1100 | cgi_init(); |
| 1089 | - process_one_web_page(zNotFound); | |
| 1101 | + if( nRedirect ){ | |
| 1102 | + redirect_web_page(nRedirect, azRedirect); | |
| 1103 | + }else{ | |
| 1104 | + process_one_web_page(zNotFound); | |
| 1105 | + } | |
| 1106 | +} | |
| 1107 | + | |
| 1108 | +/* If the CGI program contains one or more lines of the form | |
| 1109 | +** | |
| 1110 | +** redirect: repository-filename http://hostname/path/%s | |
| 1111 | +** | |
| 1112 | +** then control jumps here. Search each repository for an artifact ID | |
| 1113 | +** that matches the "name" CGI parameter and for the first match, | |
| 1114 | +** redirect to the corresponding URL with the "name" CGI parameter | |
| 1115 | +** inserted. Paint an error page if no match is found. | |
| 1116 | +** | |
| 1117 | +** If there is a line of the form: | |
| 1118 | +** | |
| 1119 | +** redirect: * URL | |
| 1120 | +** | |
| 1121 | +** Then a redirect is made to URL if no match is found. Otherwise a | |
| 1122 | +** very primative error message is returned. | |
| 1123 | +*/ | |
| 1124 | +void redirect_web_page(int nRedirect, char **azRedirect){ | |
| 1125 | + int i; /* Loop counter */ | |
| 1126 | + const char *zNotFound = 0; /* Not found URL */ | |
| 1127 | + const char *zName = P("name"); | |
| 1128 | + if( zName && validate16(zName, strlen(zName)) ){ | |
| 1129 | + for(i=0; i<nRedirect; i++){ | |
| 1130 | + if( strcmp(azRedirect[i*2],"*")==0 ){ | |
| 1131 | + zNotFound = azRedirect[i*2+1]; | |
| 1132 | + continue; | |
| 1133 | + } | |
| 1134 | + db_open_repository(azRedirect[i*2]); | |
| 1135 | + if( db_exists("SELECT 1 FROM blob WHERE uuid GLOB '%s*'", zName) ){ | |
| 1136 | + cgi_redirectf(azRedirect[i*2+1], zName); | |
| 1137 | + return; | |
| 1138 | + } | |
| 1139 | + db_close(1); | |
| 1140 | + } | |
| 1141 | + } | |
| 1142 | + if( zNotFound ){ | |
| 1143 | + cgi_redirectf(zNotFound, zName); | |
| 1144 | + }else{ | |
| 1145 | + printf( | |
| 1146 | + "Status: 200 Ok\r\n\r\n" | |
| 1147 | + "<p>No such object: %s</p>\n", | |
| 1148 | + zName | |
| 1149 | + ); | |
| 1150 | + } | |
| 1090 | 1151 | } |
| 1091 | 1152 | |
| 1092 | 1153 | /* |
| 1093 | 1154 | ** If g.argv[2] exists then it is either the name of a repository |
| 1094 | 1155 | ** that will be used by a server, or else it is a directory that |
| 1095 | 1156 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -1024,11 +1024,13 @@ | |
| 1024 | ** the values of standard CGI environment variables. |
| 1025 | */ |
| 1026 | void cmd_cgi(void){ |
| 1027 | const char *zFile; |
| 1028 | const char *zNotFound = 0; |
| 1029 | Blob config, line, key, value; |
| 1030 | if( g.argc==3 && fossil_strcmp(g.argv[1],"cgi")==0 ){ |
| 1031 | zFile = g.argv[2]; |
| 1032 | }else{ |
| 1033 | zFile = g.argv[1]; |
| 1034 | } |
| @@ -1078,17 +1080,76 @@ | |
| 1078 | } |
| 1079 | if( blob_eq(&key, "localauth") ){ |
| 1080 | g.useLocalauth = 1; |
| 1081 | continue; |
| 1082 | } |
| 1083 | } |
| 1084 | blob_reset(&config); |
| 1085 | if( g.db==0 && g.zRepositoryName==0 ){ |
| 1086 | cgi_panic("Unable to find or open the project repository"); |
| 1087 | } |
| 1088 | cgi_init(); |
| 1089 | process_one_web_page(zNotFound); |
| 1090 | } |
| 1091 | |
| 1092 | /* |
| 1093 | ** If g.argv[2] exists then it is either the name of a repository |
| 1094 | ** that will be used by a server, or else it is a directory that |
| 1095 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -1024,11 +1024,13 @@ | |
| 1024 | ** the values of standard CGI environment variables. |
| 1025 | */ |
| 1026 | void cmd_cgi(void){ |
| 1027 | const char *zFile; |
| 1028 | const char *zNotFound = 0; |
| 1029 | char **azRedirect = 0; /* List of repositories to redirect to */ |
| 1030 | int nRedirect = 0; /* Number of entries in azRedirect */ |
| 1031 | Blob config, line, key, value, value2; |
| 1032 | if( g.argc==3 && fossil_strcmp(g.argv[1],"cgi")==0 ){ |
| 1033 | zFile = g.argv[2]; |
| 1034 | }else{ |
| 1035 | zFile = g.argv[1]; |
| 1036 | } |
| @@ -1078,17 +1080,76 @@ | |
| 1080 | } |
| 1081 | if( blob_eq(&key, "localauth") ){ |
| 1082 | g.useLocalauth = 1; |
| 1083 | continue; |
| 1084 | } |
| 1085 | if( blob_eq(&key, "redirect:") && blob_token(&line, &value) |
| 1086 | && blob_token(&line, &value2) ){ |
| 1087 | nRedirect++; |
| 1088 | azRedirect = fossil_realloc(azRedirect, 2*nRedirect*sizeof(char*)); |
| 1089 | azRedirect[nRedirect*2-2] = mprintf("%s", blob_str(&value)); |
| 1090 | azRedirect[nRedirect*2-1] = mprintf("%s", blob_str(&value2)); |
| 1091 | blob_reset(&value); |
| 1092 | blob_reset(&value2); |
| 1093 | continue; |
| 1094 | } |
| 1095 | } |
| 1096 | blob_reset(&config); |
| 1097 | if( g.db==0 && g.zRepositoryName==0 && nRedirect==0 ){ |
| 1098 | cgi_panic("Unable to find or open the project repository"); |
| 1099 | } |
| 1100 | cgi_init(); |
| 1101 | if( nRedirect ){ |
| 1102 | redirect_web_page(nRedirect, azRedirect); |
| 1103 | }else{ |
| 1104 | process_one_web_page(zNotFound); |
| 1105 | } |
| 1106 | } |
| 1107 | |
| 1108 | /* If the CGI program contains one or more lines of the form |
| 1109 | ** |
| 1110 | ** redirect: repository-filename http://hostname/path/%s |
| 1111 | ** |
| 1112 | ** then control jumps here. Search each repository for an artifact ID |
| 1113 | ** that matches the "name" CGI parameter and for the first match, |
| 1114 | ** redirect to the corresponding URL with the "name" CGI parameter |
| 1115 | ** inserted. Paint an error page if no match is found. |
| 1116 | ** |
| 1117 | ** If there is a line of the form: |
| 1118 | ** |
| 1119 | ** redirect: * URL |
| 1120 | ** |
| 1121 | ** Then a redirect is made to URL if no match is found. Otherwise a |
| 1122 | ** very primative error message is returned. |
| 1123 | */ |
| 1124 | void redirect_web_page(int nRedirect, char **azRedirect){ |
| 1125 | int i; /* Loop counter */ |
| 1126 | const char *zNotFound = 0; /* Not found URL */ |
| 1127 | const char *zName = P("name"); |
| 1128 | if( zName && validate16(zName, strlen(zName)) ){ |
| 1129 | for(i=0; i<nRedirect; i++){ |
| 1130 | if( strcmp(azRedirect[i*2],"*")==0 ){ |
| 1131 | zNotFound = azRedirect[i*2+1]; |
| 1132 | continue; |
| 1133 | } |
| 1134 | db_open_repository(azRedirect[i*2]); |
| 1135 | if( db_exists("SELECT 1 FROM blob WHERE uuid GLOB '%s*'", zName) ){ |
| 1136 | cgi_redirectf(azRedirect[i*2+1], zName); |
| 1137 | return; |
| 1138 | } |
| 1139 | db_close(1); |
| 1140 | } |
| 1141 | } |
| 1142 | if( zNotFound ){ |
| 1143 | cgi_redirectf(zNotFound, zName); |
| 1144 | }else{ |
| 1145 | printf( |
| 1146 | "Status: 200 Ok\r\n\r\n" |
| 1147 | "<p>No such object: %s</p>\n", |
| 1148 | zName |
| 1149 | ); |
| 1150 | } |
| 1151 | } |
| 1152 | |
| 1153 | /* |
| 1154 | ** If g.argv[2] exists then it is either the name of a repository |
| 1155 | ** that will be used by a server, or else it is a directory that |
| 1156 |