Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge the latest changes from trunk. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | windows-i18n |
Files: | files | file ages | folders |
SHA1: |
503a0ef555dd376998018d7620db63a5 |
User & Date: | drh 2011-05-04 11:16:53.845 |
Context
2011-05-06
| ||
16:55 | Merge the latest trunk changes into windows-i18n branch. ... (check-in: 59ddd3c8 user: drh tags: windows-i18n) | |
2011-05-04
| ||
11:16 | Merge the latest changes from trunk. ... (check-in: 503a0ef5 user: drh tags: windows-i18n) | |
11:13 | Add a wrapper around all calls to access() that translates UTF8 to MBCS. ... (check-in: 850d3df4 user: drh tags: windows-i18n) | |
2011-05-03
| ||
13:37 | Enable Basic Authorization during sync operations by prepending a single "#" to the password. ... (check-in: c1506adb user: drh tags: trunk) | |
Changes
Changes to src/db.c.
︙ | ︙ | |||
79 80 81 82 83 84 85 | fprintf(stderr, "%s: %s\n\n%s", fossil_nameofexe(), z, zRebuildMsg); } db_force_rollback(); fossil_exit(1); } static int nBegin = 0; /* Nesting depth of BEGIN */ | < > > > > > > > > > > > | 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | fprintf(stderr, "%s: %s\n\n%s", fossil_nameofexe(), z, zRebuildMsg); } db_force_rollback(); fossil_exit(1); } static int nBegin = 0; /* Nesting depth of BEGIN */ static int doRollback = 0; /* True to force a rollback */ static int nCommitHook = 0; /* Number of commit hooks */ static struct sCommitHook { int (*xHook)(void); /* Functions to call at db_end_transaction() */ int sequence; /* Call functions in sequence order */ } aHook[5]; static Stmt *pAllStmt = 0; /* List of all unfinalized statements */ static int nPrepare = 0; /* Number of calls to sqlite3_prepare() */ static int nDeleteOnFail = 0; /* Number of entries in azDeleteOnFail[] */ static char *azDeleteOnFail[3]; /* Files to delete on a failure */ /* ** Arrange for the given file to be deleted on a failure. */ void db_delete_on_failure(const char *zFilename){ assert( nDeleteOnFail<count(azDeleteOnFail) ); azDeleteOnFail[nDeleteOnFail++] = fossil_strdup(zFilename); } /* ** This routine is called by the SQLite commit-hook mechanism ** just prior to each commit. All this routine does is verify ** that nBegin really is zero. That insures that transactions ** cannot commit by any means other than by calling db_end_transaction() ** below. |
︙ | ︙ | |||
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | } } /* ** Force a rollback and shutdown the database */ void db_force_rollback(void){ static int busy = 0; if( busy || g.db==0 ) return; busy = 1; undo_rollback(); while( pAllStmt ){ db_finalize(pAllStmt); } if( nBegin ){ sqlite3_exec(g.db, "ROLLBACK", 0, 0, 0); nBegin = 0; | > < < < < > > > | 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 | } } /* ** Force a rollback and shutdown the database */ void db_force_rollback(void){ int i; static int busy = 0; if( busy || g.db==0 ) return; busy = 1; undo_rollback(); while( pAllStmt ){ db_finalize(pAllStmt); } if( nBegin ){ sqlite3_exec(g.db, "ROLLBACK", 0, 0, 0); nBegin = 0; } busy = 0; db_close(0); for(i=0; i<nDeleteOnFail; i++){ file_delete(azDeleteOnFail[i]); } } /* ** Install a commit hook. Hooks are installed in sequence order. ** It is an error to install the same commit hook more than once. ** ** Each commit hook is called (in order of accending sequence) at |
︙ | ︙ | |||
1042 1043 1044 1045 1046 1047 1048 | void db_create_repository(const char *zFilename){ db_init_database( zFilename, zRepositorySchema1, zRepositorySchema2, (char*)0 ); | | | 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 | void db_create_repository(const char *zFilename){ db_init_database( zFilename, zRepositorySchema1, zRepositorySchema2, (char*)0 ); db_delete_on_failure(zFilename); } /* ** Create the default user accounts in the USER table. */ void db_create_default_users(int setupUserOnly, const char *zDefaultUser){ const char *zUser; |
︙ | ︙ | |||
1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 | } if( !allowNested && db_open_local() ){ fossil_panic("already within an open tree rooted at %s", g.zLocalRoot); } file_canonical_name(g.argv[2], &path); db_open_repository(blob_str(&path)); db_init_database("./_FOSSIL_", zLocalSchema, (char*)0); db_open_local(); db_lset("repository", blob_str(&path)); db_record_repository_filename(blob_str(&path)); vid = db_int(0, "SELECT pid FROM plink y" " WHERE NOT EXISTS(SELECT 1 FROM plink x WHERE x.cid=y.pid)"); if( vid==0 ){ db_lset_int("checkout", 1); | > | 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 | } if( !allowNested && db_open_local() ){ fossil_panic("already within an open tree rooted at %s", g.zLocalRoot); } file_canonical_name(g.argv[2], &path); db_open_repository(blob_str(&path)); db_init_database("./_FOSSIL_", zLocalSchema, (char*)0); db_delete_on_failure("./_FOSSIL_"); db_open_local(); db_lset("repository", blob_str(&path)); db_record_repository_filename(blob_str(&path)); vid = db_int(0, "SELECT pid FROM plink y" " WHERE NOT EXISTS(SELECT 1 FROM plink x WHERE x.cid=y.pid)"); if( vid==0 ){ db_lset_int("checkout", 1); |
︙ | ︙ |
Changes to src/http.c.
︙ | ︙ | |||
60 61 62 63 64 65 66 67 68 69 | zPw = 0; }else{ /* Password failure while doing a sync from the command-line interface */ url_prompt_for_password(); zPw = g.urlPasswd; if( !g.dontKeepUrl ) db_set("last-sync-pw", obscure(zPw), 0); } /* The login card wants the SHA1 hash of the password, so convert the ** password to its SHA1 hash it it isn't already a SHA1 hash. | > > > > > > < < < < < < < < < | < < | 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | zPw = 0; }else{ /* Password failure while doing a sync from the command-line interface */ url_prompt_for_password(); zPw = g.urlPasswd; if( !g.dontKeepUrl ) db_set("last-sync-pw", obscure(zPw), 0); } /* If the first character of the password is "#", then that character is ** not really part of the password - it is an indicator that we should ** use Basic Authentication. So skip that character. */ if( zPw && zPw[0]=='#' ) zPw++; /* The login card wants the SHA1 hash of the password, so convert the ** password to its SHA1 hash it it isn't already a SHA1 hash. */ if( zPw && zPw[0] ) zPw = sha1_shared_secret(zPw, zLogin, 0); blob_append(&pw, zPw, -1); sha1sum_blob(&pw, &sig); blob_appendf(pLogin, "login %F %b %b\n", zLogin, &nonce, &sig); blob_reset(&pw); blob_reset(&sig); blob_reset(&nonce); |
︙ | ︙ | |||
104 105 106 107 108 109 110 111 112 113 114 115 116 117 | zSep = ""; }else{ zSep = "/"; } blob_appendf(pHdr, "POST %s%sxfer/xfer HTTP/1.0\r\n", g.urlPath, zSep); if( g.urlProxyAuth ){ blob_appendf(pHdr, "Proxy-Authorization: %s\n", g.urlProxyAuth); } blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname); blob_appendf(pHdr, "User-Agent: Fossil/" MANIFEST_VERSION "\r\n"); if( g.fHttpTrace ){ blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n"); }else{ blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n"); | > > > > > > > | 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | zSep = ""; }else{ zSep = "/"; } blob_appendf(pHdr, "POST %s%sxfer/xfer HTTP/1.0\r\n", g.urlPath, zSep); if( g.urlProxyAuth ){ blob_appendf(pHdr, "Proxy-Authorization: %s\n", g.urlProxyAuth); } if( g.urlPasswd && g.urlUser && g.urlPasswd[0]=='#' ){ char *zCredentials = mprintf("%s:%s", g.urlUser, &g.urlPasswd[1]); char *zEncoded = encode64(zCredentials, -1); blob_appendf(pHdr, "Authorization: Basic %s\r\n", zEncoded); fossil_free(zEncoded); fossil_free(zCredentials); } blob_appendf(pHdr, "Host: %s\r\n", g.urlHostname); blob_appendf(pHdr, "User-Agent: Fossil/" MANIFEST_VERSION "\r\n"); if( g.fHttpTrace ){ blob_appendf(pHdr, "Content-Type: application/x-fossil-debug\r\n"); }else{ blob_appendf(pHdr, "Content-Type: application/x-fossil\r\n"); |
︙ | ︙ |
Changes to src/xfer.c.
︙ | ︙ | |||
550 551 552 553 554 555 556 557 558 559 560 561 562 563 | int rc = -1; char *zLogin = blob_terminate(pLogin); defossilize(zLogin); if( strcmp(zLogin, "nobody")==0 || strcmp(zLogin,"anonymous")==0 ){ return 0; /* Anybody is allowed to sync as "nobody" or "anonymous" */ } db_prepare(&q, "SELECT pw, cap, uid FROM user" " WHERE login=%Q" " AND login NOT IN ('anonymous','nobody','developer','reader')" " AND length(pw)>0", zLogin ); | > > > | 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 | int rc = -1; char *zLogin = blob_terminate(pLogin); defossilize(zLogin); if( strcmp(zLogin, "nobody")==0 || strcmp(zLogin,"anonymous")==0 ){ return 0; /* Anybody is allowed to sync as "nobody" or "anonymous" */ } if( fossil_strcmp(P("REMOTE_USER"), zLogin)==0 ){ return 0; /* Accept Basic Authorization */ } db_prepare(&q, "SELECT pw, cap, uid FROM user" " WHERE login=%Q" " AND login NOT IN ('anonymous','nobody','developer','reader')" " AND length(pw)>0", zLogin ); |
︙ | ︙ | |||
807 808 809 810 811 812 813 814 815 816 817 818 819 820 | char *zNow; if( strcmp(PD("REQUEST_METHOD","POST"),"POST") ){ fossil_redirect_home(); } g.zLogin = "anonymous"; login_set_anon_nobody_capabilities(); memset(&xfer, 0, sizeof(xfer)); blobarray_zero(xfer.aToken, count(xfer.aToken)); cgi_set_content_type(g.zContentType); if( db_schema_is_outofdate() ){ @ error database\sschema\sis\sout-of-date\son\sthe\sserver. return; } | > | 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 | char *zNow; if( strcmp(PD("REQUEST_METHOD","POST"),"POST") ){ fossil_redirect_home(); } g.zLogin = "anonymous"; login_set_anon_nobody_capabilities(); login_check_credentials(); memset(&xfer, 0, sizeof(xfer)); blobarray_zero(xfer.aToken, count(xfer.aToken)); cgi_set_content_type(g.zContentType); if( db_schema_is_outofdate() ){ @ error database\sschema\sis\sout-of-date\son\sthe\sserver. return; } |
︙ | ︙ |
Changes to www/server.wiki.
︙ | ︙ | |||
13 14 15 16 17 18 19 | </ul> <p> Both of these commands start a Fossil server on port 8080 on the local machine, which can be accessed with the URL: <tt>http://localhost:8080/</tt> using any handy web browser. The difference between the two commands is that "ui", in addition to starting the Fossil server, also starts a web browser and points it | | > > | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | </ul> <p> Both of these commands start a Fossil server on port 8080 on the local machine, which can be accessed with the URL: <tt>http://localhost:8080/</tt> using any handy web browser. The difference between the two commands is that "ui", in addition to starting the Fossil server, also starts a web browser and points it to the URL mentioned above. On the other hand, the "ui" command binds to the loopback IP address only (127.0.0.1) so that the "ui" command cannot be used to serve content to a different machine. </p> <p> NOTES: <ol> <li>The option "--port NNN" will start the server on port "NNN" instead of 8080. <li>If port 8080 is already being used (perhaps by another Fossil server), then Fossil will use the next available port number. |
︙ | ︙ | |||
68 69 70 71 72 73 74 | <p> Once the script is set up correctly, and assuming your server is also set correctly, you should be able to access your repository with a URL like: <tt>http://mydomain.org/cgi-bin/repo</tt> (assuming the "repo" script is accessible under "cgi-bin", which would be a typical deployment on Apache for instance). </p> </blockquote> <h3>Serving multiple repositories with one script</h3><blockquote> <p> | | > > > | | 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | <p> Once the script is set up correctly, and assuming your server is also set correctly, you should be able to access your repository with a URL like: <tt>http://mydomain.org/cgi-bin/repo</tt> (assuming the "repo" script is accessible under "cgi-bin", which would be a typical deployment on Apache for instance). </p> </blockquote> <h3>Serving multiple repositories with one script</h3><blockquote> <p> This scenario is almost identical to the previous one. However, here we will assume you have multiple repositories, in one directory. (Call the directory 'fossils'). All repositories served, in this case, must use the ".fossil" filename suffix. As before, create a script (again, 'repo'): <blockquote><tt> #!/path-to/fossil<br> directory: /path-to-repo/fossils<br> notfound: http://url-to-go-to-if-repo-not-found/ </tt></blockquote> </p> <p> Once deployed, a URL like: <tt>http://mydomain.org/cgi-bin/repo/XYZ</tt> will serve up the repository "fossils/XYX.fossil" (if it exists). This makes serving multiple projects on one server pretty painless. </p> </blockquote> <h2>Securing a repository with SSL</h2><blockquote> <p> Using either of the CGI script approaches, it is trivial to use SSL to secure the server. Simply set up the Fossil CGI scripts etc. as above, but modify the Apache (or IIS, etc.) server to require SSL (that is, a URL with "https://") in order to access the CGI script directory. This may also be accomplished (on Apache, at least) using appropriate ".htaccess" rules. </p> |
︙ | ︙ |