Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Fix the "fossil all ui" command so that it works on Windows. But also comment out some very confused logic in process_on_web_page() that is associated with "--baseurl" option. This logic needs to be fixed prior to merging with trunk. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | all-ui |
| Files: | files | file ages | folders |
| SHA1: |
da1c769cd236de86ccbc93cf5b5a8bd4 |
| User & Date: | drh 2016-12-01 14:56:34.187 |
Context
|
2016-12-01
| ||
| 15:40 | A cleaner way of dealing with the --baseurl problem. check-in: 8e4b8ba0e4 user: drh tags: all-ui | |
| 14:56 | Fix the "fossil all ui" command so that it works on Windows. But also comment out some very confused logic in process_on_web_page() that is associated with "--baseurl" option. This logic needs to be fixed prior to merging with trunk. check-in: da1c769cd2 user: drh tags: all-ui | |
| 04:32 | Add the "fossil all ui" and "fossil all server" commands. check-in: 98e9fd7352 user: drh tags: all-ui | |
Changes
Changes to src/file.c.
| ︙ | ︙ | |||
1433 1434 1435 1436 1437 1438 1439 |
*/
void file_test_valid_for_windows(void){
int i;
for(i=2; i<g.argc; i++){
fossil_print("%s %s\n", file_is_win_reserved(g.argv[i]), g.argv[i]);
}
}
| > > > > > > > > > > > > > > > | 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 |
*/
void file_test_valid_for_windows(void){
int i;
for(i=2; i<g.argc; i++){
fossil_print("%s %s\n", file_is_win_reserved(g.argv[i]), g.argv[i]);
}
}
/*
** Remove surplus "/" characters from the beginning of a full pathname.
** Extra leading "/" characters are benign on unix. But on Windows
** machines, they must be removed. Example: Convert "/C:/fossil/xyx.fossil"
** into "c:/fossil/xyz.fossil".
*/
const char *file_cleanup_fullpath(const char *z){
#ifdef _WIN32
if( z[0]=='/' && fossil_isalpha(z[1]) && z[2]==':' && z[3]=='/' ) z++;
#else
while( z[0]=='/' && z[1]=='/' ) z++;
#endif
return z;
}
|
Changes to src/main.c.
| ︙ | ︙ | |||
1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 |
Blob base;
int n = 0;
assert( g.db==0 );
if( fossil_strcmp(g.zRepositoryName,"/")==0 ){
/* For the special case of the "repository directory" being "/",
** show all of the repositories named in the ~/.fossil database.
*/
db_open_config(1, 0);
db_multi_exec(
"CREATE TEMP VIEW sfile AS"
" SELECT substr(name,7) AS 'pathname' FROM global_config"
" WHERE name GLOB 'repo:*'"
);
}else{
/* The default case: All repositories under the g.zRepositoryName
** directory.
*/
blob_init(&base, g.zRepositoryName, -1);
sqlite3_open(":memory:", &g.db);
db_multi_exec("CREATE TABLE sfile(pathname TEXT);");
| > > > > > > > > > > > > > | 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 |
Blob base;
int n = 0;
assert( g.db==0 );
if( fossil_strcmp(g.zRepositoryName,"/")==0 ){
/* For the special case of the "repository directory" being "/",
** show all of the repositories named in the ~/.fossil database.
**
** On unix systems, then entries are of the form "repo:/home/..."
** and on Windows systems they are like "repo:C:/Users/...". We want
** to skip the first 6 characters on unix and the first 5 characters
** on Windows.
*/
db_open_config(1, 0);
#ifdef _WIN32
db_multi_exec(
"CREATE TEMP VIEW sfile AS"
" SELECT substr(name,6) AS 'pathname' FROM global_config"
" WHERE name GLOB 'repo:*'"
);
#else
db_multi_exec(
"CREATE TEMP VIEW sfile AS"
" SELECT substr(name,7) AS 'pathname' FROM global_config"
" WHERE name GLOB 'repo:*'"
);
#endif
}else{
/* The default case: All repositories under the g.zRepositoryName
** directory.
*/
blob_init(&base, g.zRepositoryName, -1);
sqlite3_open(":memory:", &g.db);
db_multi_exec("CREATE TABLE sfile(pathname TEXT);");
|
| ︙ | ︙ | |||
1231 1232 1233 1234 1235 1236 1237 |
@ <h1>Available Repositories:</h1>
@ <ol>
db_prepare(&q, "SELECT pathname, substr(pathname,-7,-100000)||'/home'"
" FROM sfile ORDER BY pathname COLLATE nocase;");
while( db_step(&q)==SQLITE_ROW ){
const char *zName = db_column_text(&q, 0);
const char *zUrl = db_column_text(&q, 1);
| | | 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 |
@ <h1>Available Repositories:</h1>
@ <ol>
db_prepare(&q, "SELECT pathname, substr(pathname,-7,-100000)||'/home'"
" FROM sfile ORDER BY pathname COLLATE nocase;");
while( db_step(&q)==SQLITE_ROW ){
const char *zName = db_column_text(&q, 0);
const char *zUrl = db_column_text(&q, 1);
@ <li><a href="%R/%T(zUrl)" target="_blank">%h(zName)</a></li>
}
@ </ol>
}else{
@ <h1>No Repositories Found</h1>
}
@ </body>
@ </html>
|
| ︙ | ︙ | |||
1272 1273 1274 1275 1276 1277 1278 |
** If no suitable webpage is found, try to redirect to zNotFound.
*/
static void process_one_web_page(
const char *zNotFound, /* Redirect here on a 404 if not NULL */
Glob *pFileGlob, /* Deliver static files matching */
int allowRepoList /* Send repo list for "/" URL */
){
| | | > | < < < > > > > > | > > | | | | > > > > > > > > > | > > > | > > > > | | > > > > > > > > > > > > > > > > > > > > > < | > > > > | > > > > > > > > > | | > > > | > > > > > > > > > > > > | | | > > > > > | 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 |
** If no suitable webpage is found, try to redirect to zNotFound.
*/
static void process_one_web_page(
const char *zNotFound, /* Redirect here on a 404 if not NULL */
Glob *pFileGlob, /* Deliver static files matching */
int allowRepoList /* Send repo list for "/" URL */
){
const char *zPathInfo = PD("PATH_INFO", "");
/* const char *zDirPathInfo; **** refactor needed */
char *zPath = NULL;
int i;
const CmdOrPage *pCmd = 0;
const char *zBase = g.zRepositoryName;
/* Handle universal query parameters */
if( PB("utc") ){
g.fTimeFormat = 1;
}else if( PB("localtime") ){
g.fTimeFormat = 2;
}
#if 0 /* Refactor needed */
/* For the PATH_INFO that will be used to help build the final
** g.zBaseURL and g.zTop (only), skip over the initial directory
** portion of PATH_INFO; otherwise, it may be duplicated.
*/
if( g.zTop ){
int nTop = strlen(g.zTop);
if ( strncmp(zDirPathInfo, g.zTop, nTop)==0 ){
zDirPathInfo += nTop;
}
}
#endif
/* If the repository has not been opened already, then find the
** repository based on the first element of PATH_INFO and open it.
*/
if( !g.repositoryOpen ){
char *zRepo; /* Candidate repository name */
char *zToFree = 0; /* Malloced memory that needs to be freed */
const char *zCleanRepo; /* zRepo with surplus leading "/" removed */
const char *zOldScript = PD("SCRIPT_NAME", ""); /* Original SCRIPT_NAME */
char *zNewScript; /* Revised SCRIPT_NAME after processing */
int j, k; /* Loop variables */
i64 szFile; /* File size of the candidate repository */
i = zPathInfo[0]!=0;
if( fossil_strcmp(g.zRepositoryName, "/")==0 ){
zBase++;
#ifdef _WIN32
if( sqlite3_strglob("/[a-zA-Z]:/*", zPathInfo)==0 ) i = 4;
#endif
}
while( 1 ){
while( zPathInfo[i] && zPathInfo[i]!='/' ){ i++; }
/* The candidate repository name is some prefix of the PATH_INFO
** with ".fossil" appended */
zRepo = zToFree = mprintf("%s%.*s.fossil",zBase,i,zPathInfo);
if( g.fHttpTrace ){
@ <!-- Looking for repository named "%h(zRepo)" -->
fprintf(stderr, "# looking for repository named \"%s\"\n", zRepo);
}
/* For safety -- to prevent an attacker from accessing arbitrary disk
** files by sending a maliciously crafted request URI to a public
** server -- make sure the repository basename contains no
** characters other than alphanumerics, "/", "_", "-", and ".", and
** that "-" never occurs immediately after a "/" and that "." is always
** surrounded by two alphanumerics. Any character that does not
** satisfy these constraints is converted into "_".
*/
szFile = 0;
for(j=strlen(zBase)+1, k=0; zRepo[j] && k<i-1; j++, k++){
char c = zRepo[j];
if( fossil_isalnum(c) ) continue;
#ifdef _WIN32
/* Allow names to begin with "/X:/" on windows */
if( c==':' && j==2 && sqlite3_strglob("/[a-zA-Z]:/*", zRepo)==0 ){
continue;
}
#endif
if( c=='/' ) continue;
if( c=='_' ) continue;
if( c=='-' && zRepo[j-1]!='/' ) continue;
if( c=='.' && fossil_isalnum(zRepo[j-1]) && fossil_isalnum(zRepo[j+1])){
continue;
}
/* If we reach this point, it means that the request URI contains
** an illegal character or character combination. Provoke a
** "Not Found" error. */
szFile = 1;
if( g.fHttpTrace ){
@ <!-- Unsafe pathname rejected: "%h(zRepo)" -->
fprintf(stderr, "# unsafe pathname rejected: %s\n", zRepo);
}
break;
}
/* Check to see if a file name zRepo exists. If a file named zRepo
** does not exist, szFile will become -1. If the file does exist,
** then szFile will become zero (for an empty file) or positive.
** Special case: Assume any file with a basename of ".fossil" does
** not exist.
*/
zCleanRepo = file_cleanup_fullpath(zRepo);
if( szFile==0 && sqlite3_strglob("*/.fossil",zRepo)!=0 ){
szFile = file_size(zCleanRepo);
if( g.fHttpTrace ){
@ <!-- file_size(%h(zCleanRepo)) is %lld(szFile) -->
fprintf(stderr, "# file_size(%s) = %lld\n", zCleanRepo, szFile);
}
#if 0
/* This logic for handling --baseurl is confused and needs to be
** completely rethought. */
if( g.zBaseURL && g.zBaseURL[0]!=0 && g.zTop && g.zTop[0]!=0 &&
file_isdir(g.zRepositoryName)==1 ){
if( zPathInfo==zDirPathInfo ){
g.zBaseURL = mprintf("%s%.*s", g.zBaseURL, i, zPathInfo);
g.zTop = mprintf("%s%.*s", g.zTop, i, zPathInfo);
}
}
#endif
}
/* If no file named by zRepo exists, remove the added ".fossil" suffix
** and check to see if there is a file or directory with the same
** name as the raw PATH_INFO text.
*/
if( szFile<0 && i>0 ){
const char *zMimetype;
assert( fossil_strcmp(&zRepo[j], ".fossil")==0 );
zRepo[j] = 0; /* Remove the ".fossil" suffix */
/* The PATH_INFO prefix seen so far is a valid directory.
** Continue the loop with the next element of the PATH_INFO */
if( zPathInfo[i]=='/' && file_isdir(zCleanRepo)==1 ){
fossil_free(zToFree);
i++;
continue;
}
/* If zRepo is the name of an ordinary file that matches the
** "--file GLOB" pattern, then the CGI reply is the text of
** of the file.
**
** For safety, do not allow any file whose name contains ".fossil"
** to be returned this way, to prevent complete repositories from
** being delivered accidently. This is not intended to be a
** general-purpose web server. The "--file GLOB" mechanism is
** designed to allow the delivery of a few static images or HTML
** pages.
*/
if( pFileGlob!=0
&& file_isfile(zCleanRepo)
&& glob_match(pFileGlob, file_cleanup_fullpath(zRepo))
&& sqlite3_strglob("*.fossil*",zRepo)!=0
&& (zMimetype = mimetype_from_name(zRepo))!=0
&& strcmp(zMimetype, "application/x-fossil-artifact")!=0
){
Blob content;
blob_read_from_file(&content, file_cleanup_fullpath(zRepo));
cgi_set_content_type(zMimetype);
cgi_set_content(&content);
cgi_reply();
return;
}
zRepo[j] = '.';
}
/* If we reach this point, it means that the search of the PATH_INFO
** string is finished. Either zRepo contains the name of the
** repository to be used, or else no repository could be found an
** some kind of error response is required.
*/
if( szFile<1024 ){
set_base_url(0);
if( strcmp(zPathInfo,"/")==0
&& allowRepoList
&& repo_list_page() ){
/* Will return a list of repositories */
}else if( zNotFound ){
|
| ︙ | ︙ | |||
1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 |
cgi_set_status(404, "not found");
cgi_reply();
}
return;
}
break;
}
zNewScript = mprintf("%s%.*s", zOldScript, i, zPathInfo);
cgi_replace_parameter("PATH_INFO", &zPathInfo[i+1]);
zPathInfo += i;
cgi_replace_parameter("SCRIPT_NAME", zNewScript);
| > > > > > | > > > > > | < > > > > > > < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 |
cgi_set_status(404, "not found");
cgi_reply();
}
return;
}
break;
}
/* Add the repository name (without the ".fossil" suffix) to the end
** of SCRIPT_NAME and remove the repository name from the beginning
** of PATH_INFO.
*/
zNewScript = mprintf("%s%.*s", zOldScript, i, zPathInfo);
cgi_replace_parameter("PATH_INFO", &zPathInfo[i+1]);
zPathInfo += i;
cgi_replace_parameter("SCRIPT_NAME", zNewScript);
db_open_repository(file_cleanup_fullpath(zRepo));
if( g.fHttpTrace ){
@ <!-- repository: "%h(zRepo)" -->
@ <!-- new PATH_INFO: "%h(zPathInfo)" -->
@ <!-- new SCRIPT_NAME: "%h(zNewScript)" -->
fprintf(stderr,
"# repository: [%s]\n"
"# new PATH_INFO = [%s]\n"
"# new SCRIPT_NAME = [%s]\n",
zRepo, zPathInfo, zNewScript);
}
}
/* At this point, the appropriate repository database file will have
** been opened. Use the first element of PATH_INFO as the page name
** and deliver the appropriate page back to the user.
*/
if( g.zContentType &&
strncmp(g.zContentType, "application/x-fossil", 20)==0 ){
/* Special case: If the content mimetype shows that it is "fossil sync"
** payload, then pretend that the PATH_INFO is /xfer so that we always
** invoke the sync page. */
zPathInfo = "/xfer";
}
set_base_url(0);
if( zPathInfo==0 || zPathInfo[0]==0
|| (zPathInfo[0]=='/' && zPathInfo[1]==0) ){
/* Second special case: If the PATH_INFO is blank, issue a redirect to
** the home page identified by the "index-page" setting in the repository
** CONFIG table, to "/index" if there no "index-page" setting. */
#ifdef FOSSIL_ENABLE_JSON
if(g.json.isJsonMode){
json_err(FSL_JSON_E_RESOURCE_NOT_FOUND,NULL,1);
fossil_exit(0);
}
#endif
fossil_redirect_home() /*does not return*/;
}else{
zPath = mprintf("%s", zPathInfo);
}
/* Make g.zPath point to the first element of the path. Make
** g.zExtra point to everything past that point.
*/
while(1){
g.zPath = &zPath[1];
for(i=1; zPath[i] && zPath[i]!='/'; i++){}
if( zPath[i]=='/' ){
zPath[i] = 0;
g.zExtra = &zPath[i+1];
}else{
g.zExtra = 0;
}
break;
}
#ifdef FOSSIL_ENABLE_JSON
/*
|
| ︙ | ︙ | |||
2226 2227 2228 2229 2230 2231 2232 | ** such as ".txt" or ".html" or ".jpeg" and do not match the pattern ** "*.fossil*" will be served as static content. With the "ui" command, ** the REPOSITORY can only be a directory if the --notfound option is ** also present. ** ** For the special case REPOSITORY name of "/", the list global configuration ** database is consulted for a list of all known repositories. The --repolist | | > | 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 | ** such as ".txt" or ".html" or ".jpeg" and do not match the pattern ** "*.fossil*" will be served as static content. With the "ui" command, ** the REPOSITORY can only be a directory if the --notfound option is ** also present. ** ** For the special case REPOSITORY name of "/", the list global configuration ** database is consulted for a list of all known repositories. The --repolist ** option is implied by this special case. See also the "fossil all ui" ** command. ** ** By default, the "ui" command provides full administrative access without ** having to log in. This can be disabled by turning off the "localauth" ** setting. Automatic login for the "server" command is available if the ** --localauth option is present and the "localauth" setting is off and the ** connection is from localhost. The "ui" command also enables --repolist ** by default. |
| ︙ | ︙ |