a48474bc75 2008-05-29 drh: /* a48474bc75 2008-05-29 drh: ** Copyright (c) 2008 D. Richard Hipp a48474bc75 2008-05-29 drh: ** a48474bc75 2008-05-29 drh: ** This program is free software; you can redistribute it and/or a48474bc75 2008-05-29 drh: ** modify it under the terms of the GNU General Public a48474bc75 2008-05-29 drh: ** License version 2 as published by the Free Software Foundation. a48474bc75 2008-05-29 drh: ** a48474bc75 2008-05-29 drh: ** This program is distributed in the hope that it will be useful, a48474bc75 2008-05-29 drh: ** but WITHOUT ANY WARRANTY; without even the implied warranty of a48474bc75 2008-05-29 drh: ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU a48474bc75 2008-05-29 drh: ** General Public License for more details. a48474bc75 2008-05-29 drh: ** a48474bc75 2008-05-29 drh: ** You should have received a copy of the GNU General Public a48474bc75 2008-05-29 drh: ** License along with this library; if not, write to the a48474bc75 2008-05-29 drh: ** Free Software Foundation, Inc., 59 Temple Place - Suite 330, a48474bc75 2008-05-29 drh: ** Boston, MA 02111-1307, USA. a48474bc75 2008-05-29 drh: ** a48474bc75 2008-05-29 drh: ** Author contact information: a48474bc75 2008-05-29 drh: ** drh@hwaci.com a48474bc75 2008-05-29 drh: ** http://www.hwaci.com/drh/ a48474bc75 2008-05-29 drh: ** a48474bc75 2008-05-29 drh: ******************************************************************************* a48474bc75 2008-05-29 drh: ** a48474bc75 2008-05-29 drh: ** This file contains code used to manage SHUN table of the repository a48474bc75 2008-05-29 drh: */ a48474bc75 2008-05-29 drh: #include "config.h" a48474bc75 2008-05-29 drh: #include "shun.h" a48474bc75 2008-05-29 drh: #include <assert.h> a48474bc75 2008-05-29 drh: a48474bc75 2008-05-29 drh: /* 766bec08ce 2009-01-25 drh: ** Return true if the given artifact ID should be shunned. a48474bc75 2008-05-29 drh: */ a48474bc75 2008-05-29 drh: int uuid_is_shunned(const char *zUuid){ a48474bc75 2008-05-29 drh: static Stmt q; a48474bc75 2008-05-29 drh: int rc; a48474bc75 2008-05-29 drh: if( zUuid==0 || zUuid[0]==0 ) return 0; a48474bc75 2008-05-29 drh: db_static_prepare(&q, "SELECT 1 FROM shun WHERE uuid=:uuid"); a48474bc75 2008-05-29 drh: db_bind_text(&q, ":uuid", zUuid); a48474bc75 2008-05-29 drh: rc = db_step(&q); a48474bc75 2008-05-29 drh: db_reset(&q); a48474bc75 2008-05-29 drh: return rc==SQLITE_ROW; a48474bc75 2008-05-29 drh: } a48474bc75 2008-05-29 drh: a48474bc75 2008-05-29 drh: /* a48474bc75 2008-05-29 drh: ** WEBPAGE: shun a48474bc75 2008-05-29 drh: */ a48474bc75 2008-05-29 drh: void shun_page(void){ a48474bc75 2008-05-29 drh: Stmt q; a48474bc75 2008-05-29 drh: int cnt = 0; a48474bc75 2008-05-29 drh: const char *zUuid = P("uuid"); a48474bc75 2008-05-29 drh: int nUuid; a48474bc75 2008-05-29 drh: char zCanonical[UUID_SIZE+1]; a48474bc75 2008-05-29 drh: a48474bc75 2008-05-29 drh: login_check_credentials(); a48474bc75 2008-05-29 drh: if( !g.okAdmin ){ a48474bc75 2008-05-29 drh: login_needed(); a48474bc75 2008-05-29 drh: } 3f6edbc779 2008-11-10 drh: if( P("rebuild") ){ 8040619968 2008-11-27 drh: db_close(); 8040619968 2008-11-27 drh: db_open_repository(g.zRepositoryName); 3f6edbc779 2008-11-10 drh: db_begin_transaction(); 3f6edbc779 2008-11-10 drh: rebuild_db(0,0); 3f6edbc779 2008-11-10 drh: db_end_transaction(0); 0be54823ba 2008-10-18 drh: } a48474bc75 2008-05-29 drh: if( zUuid ){ a48474bc75 2008-05-29 drh: nUuid = strlen(zUuid); a48474bc75 2008-05-29 drh: if( nUuid!=40 || !validate16(zUuid, nUuid) ){ a48474bc75 2008-05-29 drh: zUuid = 0; a48474bc75 2008-05-29 drh: }else{ a48474bc75 2008-05-29 drh: memcpy(zCanonical, zUuid, UUID_SIZE+1); a48474bc75 2008-05-29 drh: canonical16(zCanonical, UUID_SIZE); a48474bc75 2008-05-29 drh: zUuid = zCanonical; a48474bc75 2008-05-29 drh: } a48474bc75 2008-05-29 drh: } a48474bc75 2008-05-29 drh: style_header("Shunned Artifacts"); a48474bc75 2008-05-29 drh: if( zUuid && P("sub") ){ 0be54823ba 2008-10-18 drh: login_verify_csrf_secret(); a48474bc75 2008-05-29 drh: db_multi_exec("DELETE FROM shun WHERE uuid='%s'", zUuid); a48474bc75 2008-05-29 drh: if( db_exists("SELECT 1 FROM blob WHERE uuid='%s'", zUuid) ){ a48474bc75 2008-05-29 drh: @ <p><font color="blue">Artifact a48474bc75 2008-05-29 drh: @ <a href="%s(g.zBaseURL)/artifact/%s(zUuid)">%s(zUuid)</a> is no a48474bc75 2008-05-29 drh: @ longer being shunned.</font></p> a48474bc75 2008-05-29 drh: }else{ a48474bc75 2008-05-29 drh: @ <p><font color="blue">Artifact %s(zUuid)</a> will no longer a48474bc75 2008-05-29 drh: @ be shunned. But it does not exist in the repository. It a48474bc75 2008-05-29 drh: @ may be necessary to rebuild the repository using the a48474bc75 2008-05-29 drh: @ <b>fossil rebuild</b> command-line before the artifact content a48474bc75 2008-05-29 drh: @ can pulled in from other respositories.</font></p> a48474bc75 2008-05-29 drh: } a48474bc75 2008-05-29 drh: } a48474bc75 2008-05-29 drh: if( zUuid && P("add") ){ 0be54823ba 2008-10-18 drh: login_verify_csrf_secret(); a48474bc75 2008-05-29 drh: db_multi_exec("INSERT OR IGNORE INTO shun VALUES('%s')", zUuid); a48474bc75 2008-05-29 drh: @ <p><font color="blue">Artifact a48474bc75 2008-05-29 drh: @ <a href="%s(g.zBaseURL)/artifact/%s(zUuid)">%s(zUuid)</a> has been a48474bc75 2008-05-29 drh: @ shunned. It will no longer be pushed. a48474bc75 2008-05-29 drh: @ It will be removed from the repository the next time the respository a48474bc75 2008-05-29 drh: @ is rebuilt using the <b>fossil rebuild</b> command-line</font></p> a48474bc75 2008-05-29 drh: } a48474bc75 2008-05-29 drh: @ <p>The artifacts listed below have been shunned by this repository. a48474bc75 2008-05-29 drh: @ This means that the artifacts will not be transmitted on a push nor a48474bc75 2008-05-29 drh: @ recieved on a pull. These artifacts are banned from the respository.</p> a48474bc75 2008-05-29 drh: @ <blockquote> a48474bc75 2008-05-29 drh: db_prepare(&q, a48474bc75 2008-05-29 drh: "SELECT uuid, EXISTS(SELECT 1 FROM blob WHERE blob.uuid=shun.uuid)" a48474bc75 2008-05-29 drh: " FROM shun ORDER BY uuid"); a48474bc75 2008-05-29 drh: while( db_step(&q)==SQLITE_ROW ){ a48474bc75 2008-05-29 drh: const char *zUuid = db_column_text(&q, 0); a48474bc75 2008-05-29 drh: int stillExists = db_column_int(&q, 1); a48474bc75 2008-05-29 drh: cnt++; a48474bc75 2008-05-29 drh: if( stillExists ){ a48474bc75 2008-05-29 drh: @ <b><a href="%s(g.zBaseURL)/artifact/%s(zUuid)">%s(zUuid)</a></b><br> a48474bc75 2008-05-29 drh: }else{ a48474bc75 2008-05-29 drh: @ <b>%s(zUuid)</b><br> a48474bc75 2008-05-29 drh: } a48474bc75 2008-05-29 drh: } a48474bc75 2008-05-29 drh: if( cnt==0 ){ a48474bc75 2008-05-29 drh: @ <i>no artifacts are shunned on this server</i> a48474bc75 2008-05-29 drh: } a48474bc75 2008-05-29 drh: db_finalize(&q); a48474bc75 2008-05-29 drh: @ </blockquote> a48474bc75 2008-05-29 drh: @ <hr> 94a93469c8 2008-06-02 drh: @ <a name="addshun"></a> 766bec08ce 2009-01-25 drh: @ <p>To shun an artifact, enter its artifact ID (the 40-character SHA1 766bec08ce 2009-01-25 drh: @ hash of the artifact) in the a48474bc75 2008-05-29 drh: @ following box and press the "Shun" button. This will cause the artifact a48474bc75 2008-05-29 drh: @ to be removed from the repository and will prevent the artifact from being a48474bc75 2008-05-29 drh: @ readded to the repository by subsequent sync operation.</p> 766bec08ce 2009-01-25 drh: @ 766bec08ce 2009-01-25 drh: @ <p>Note that you must enter the full 40-character artifact ID, not 766bec08ce 2009-01-25 drh: @ an abbreviation or a symbolic tag.</p> a48474bc75 2008-05-29 drh: @ a48474bc75 2008-05-29 drh: @ <p>Warning: Shunning should only be used to remove inappropriate content a48474bc75 2008-05-29 drh: @ from the repository. Inappropriate content includes such things as a48474bc75 2008-05-29 drh: @ spam added to Wiki, files that violate copyright or patent agreements, a48474bc75 2008-05-29 drh: @ or artifacts that by design or accident interfere with the processing a48474bc75 2008-05-29 drh: @ of the repository. Do not shun artifacts merely to remove them from a48474bc75 2008-05-29 drh: @ sight - set the "hidden" tag on such artifacts instead.</p> a48474bc75 2008-05-29 drh: @ a48474bc75 2008-05-29 drh: @ <blockquote> a48474bc75 2008-05-29 drh: @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)"> 0be54823ba 2008-10-18 drh: login_insert_csrf_secret(); 94a93469c8 2008-06-02 drh: @ <input type="text" name="uuid" value="%h(PD("shun",""))" size="50"> a48474bc75 2008-05-29 drh: @ <input type="submit" name="add" value="Shun"> a48474bc75 2008-05-29 drh: @ </form> a48474bc75 2008-05-29 drh: @ </blockquote> a48474bc75 2008-05-29 drh: @ a48474bc75 2008-05-29 drh: @ <p>Enter the UUID of a previous shunned artifact to cause it to be a48474bc75 2008-05-29 drh: @ accepted again in the repository. The artifact content is not a48474bc75 2008-05-29 drh: @ restored because the content is unknown. The only change is that a48474bc75 2008-05-29 drh: @ the formerly shunned artifact will be accepted on subsequent sync a48474bc75 2008-05-29 drh: @ operations.</p> a48474bc75 2008-05-29 drh: @ a48474bc75 2008-05-29 drh: @ <blockquote> a48474bc75 2008-05-29 drh: @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)"> 0be54823ba 2008-10-18 drh: login_insert_csrf_secret(); a48474bc75 2008-05-29 drh: @ <input type="text" name="uuid" size="50"> a48474bc75 2008-05-29 drh: @ <input type="submit" name="sub" value="Accept"> a48474bc75 2008-05-29 drh: @ </form> a48474bc75 2008-05-29 drh: @ </blockquote> 3f6edbc779 2008-11-10 drh: @ 766bec08ce 2009-01-25 drh: @ <hr> 3f6edbc779 2008-11-10 drh: @ <p>Press the button below to rebuild the respository. The rebuild 3f6edbc779 2008-11-10 drh: @ may take several seconds, so be patient after pressing the button.</p> 3f6edbc779 2008-11-10 drh: @ 3f6edbc779 2008-11-10 drh: @ <blockquote> 3f6edbc779 2008-11-10 drh: @ <form method="POST" action="%s(g.zBaseURL)/%s(g.zPath)"> 3f6edbc779 2008-11-10 drh: login_insert_csrf_secret(); 3f6edbc779 2008-11-10 drh: @ <input type="submit" name="rebuild" value="Rebuild"> 3f6edbc779 2008-11-10 drh: @ </form> 3f6edbc779 2008-11-10 drh: @ </blockquote> 3f6edbc779 2008-11-10 drh: @ a48474bc75 2008-05-29 drh: style_footer(); a48474bc75 2008-05-29 drh: } a48474bc75 2008-05-29 drh: a48474bc75 2008-05-29 drh: /* a48474bc75 2008-05-29 drh: ** Remove from the BLOB table all artifacts that are in the SHUN table. a48474bc75 2008-05-29 drh: */ a48474bc75 2008-05-29 drh: void shun_artifacts(void){ a48474bc75 2008-05-29 drh: Stmt q; a48474bc75 2008-05-29 drh: db_multi_exec( a48474bc75 2008-05-29 drh: "CREATE TEMP TABLE toshun(rid INTEGER PRIMARY KEY);" a48474bc75 2008-05-29 drh: "INSERT INTO toshun SELECT rid FROM blob, shun WHERE blob.uuid=shun.uuid;" a48474bc75 2008-05-29 drh: ); a48474bc75 2008-05-29 drh: db_prepare(&q, a48474bc75 2008-05-29 drh: "SELECT rid FROM delta WHERE srcid IN toshun" a48474bc75 2008-05-29 drh: ); a48474bc75 2008-05-29 drh: while( db_step(&q)==SQLITE_ROW ){ a48474bc75 2008-05-29 drh: int srcid = db_column_int(&q, 0); a48474bc75 2008-05-29 drh: content_undelta(srcid); a48474bc75 2008-05-29 drh: } a48474bc75 2008-05-29 drh: db_finalize(&q); a48474bc75 2008-05-29 drh: db_multi_exec( a48474bc75 2008-05-29 drh: "DELETE FROM delta WHERE rid IN toshun;" a48474bc75 2008-05-29 drh: "DELETE FROM blob WHERE rid IN toshun;" a48474bc75 2008-05-29 drh: "DROP TABLE toshun;" a48474bc75 2008-05-29 drh: ); 766bec08ce 2009-01-25 drh: } 766bec08ce 2009-01-25 drh: 766bec08ce 2009-01-25 drh: /* 766bec08ce 2009-01-25 drh: ** WEBPAGE: rcvfromlist 766bec08ce 2009-01-25 drh: ** 766bec08ce 2009-01-25 drh: ** Show a listing of RCVFROM table entries. 766bec08ce 2009-01-25 drh: */ 766bec08ce 2009-01-25 drh: void rcvfromlist_page(void){ 766bec08ce 2009-01-25 drh: int ofst = atoi(PD("ofst","0")); 766bec08ce 2009-01-25 drh: int cnt; 766bec08ce 2009-01-25 drh: Stmt q; 766bec08ce 2009-01-25 drh: 766bec08ce 2009-01-25 drh: login_check_credentials(); 766bec08ce 2009-01-25 drh: if( !g.okAdmin ){ 766bec08ce 2009-01-25 drh: login_needed(); 766bec08ce 2009-01-25 drh: } 766bec08ce 2009-01-25 drh: style_header("Content Sources"); 766bec08ce 2009-01-25 drh: if( ofst>0 ){ 766bec08ce 2009-01-25 drh: style_submenu_element("Later", "Later", "rcvfromlist?ofst=%d", 766bec08ce 2009-01-25 drh: ofst>30 ? ofst-30 : 0); 766bec08ce 2009-01-25 drh: } 766bec08ce 2009-01-25 drh: db_prepare(&q, 766bec08ce 2009-01-25 drh: "SELECT rcvid, login, datetime(rcvfrom.mtime), rcvfrom.ipaddr" 766bec08ce 2009-01-25 drh: " FROM rcvfrom LEFT JOIN user USING(uid)" 766bec08ce 2009-01-25 drh: " ORDER BY rcvid DESC LIMIT 31 OFFSET %d", 766bec08ce 2009-01-25 drh: ofst 766bec08ce 2009-01-25 drh: ); 9c89b0e0f1 2009-01-25 drh: @ <p>Whenever new artifacts are added to the repository, either by 9c89b0e0f1 2009-01-25 drh: @ push or using the web interface, an entry is made in the RCVFROM table 9c89b0e0f1 2009-01-25 drh: @ to record the source of that artifact. This log facilitates 9c89b0e0f1 2009-01-25 drh: @ finding and fixing attempts to inject illicit content into the 9c89b0e0f1 2009-01-25 drh: @ repository.</p> 9c89b0e0f1 2009-01-25 drh: @ 9c89b0e0f1 2009-01-25 drh: @ <p>Click on the "rcvid" to show a list of specific artifacts received 9c89b0e0f1 2009-01-25 drh: @ by a transaction. After identifying illicit artifacts, remove them 9c89b0e0f1 2009-01-25 drh: @ using the "Shun" feature.</p> 9c89b0e0f1 2009-01-25 drh: @ 766bec08ce 2009-01-25 drh: @ <table cellpadding=0 cellspacing=0 border=0> 766bec08ce 2009-01-25 drh: @ <tr><th>rcvid</th><th width=15> 766bec08ce 2009-01-25 drh: @ <th>Date</th><th width=15><th>User</th> 766bec08ce 2009-01-25 drh: @ <th width=15><th>IP Address</th></tr> 766bec08ce 2009-01-25 drh: cnt = 0; 766bec08ce 2009-01-25 drh: while( db_step(&q)==SQLITE_ROW ){ 766bec08ce 2009-01-25 drh: int rcvid = db_column_int(&q, 0); 766bec08ce 2009-01-25 drh: const char *zUser = db_column_text(&q, 1); 766bec08ce 2009-01-25 drh: const char *zDate = db_column_text(&q, 2); 766bec08ce 2009-01-25 drh: const char *zIpAddr = db_column_text(&q, 3); 766bec08ce 2009-01-25 drh: if( cnt==30 ){ 766bec08ce 2009-01-25 drh: style_submenu_element("Earlier", "Earlier", 766bec08ce 2009-01-25 drh: "rcvfromlist?ofst=%d", ofst+30); 766bec08ce 2009-01-25 drh: }else{ 766bec08ce 2009-01-25 drh: cnt++; 766bec08ce 2009-01-25 drh: @ <tr> 766bec08ce 2009-01-25 drh: @ <td><a href="rcvfrom?rcvid=%d(rcvid)">%d(rcvid)</a></td><td> 766bec08ce 2009-01-25 drh: @ <td>%s(zDate)</td><td> 766bec08ce 2009-01-25 drh: @ <td>%h(zUser)</td><td> 766bec08ce 2009-01-25 drh: @ <td> %s(zIpAddr) </td> 766bec08ce 2009-01-25 drh: @ </tr> 766bec08ce 2009-01-25 drh: } 766bec08ce 2009-01-25 drh: } 766bec08ce 2009-01-25 drh: db_finalize(&q); 766bec08ce 2009-01-25 drh: @ </table> 766bec08ce 2009-01-25 drh: style_footer(); 766bec08ce 2009-01-25 drh: } 766bec08ce 2009-01-25 drh: 766bec08ce 2009-01-25 drh: /* 766bec08ce 2009-01-25 drh: ** WEBPAGE: rcvfrom 766bec08ce 2009-01-25 drh: ** 766bec08ce 2009-01-25 drh: ** Show a single RCVFROM table entry. 766bec08ce 2009-01-25 drh: */ 766bec08ce 2009-01-25 drh: void rcvfrom_page(void){ 766bec08ce 2009-01-25 drh: int rcvid = atoi(PD("rcvid","0")); 766bec08ce 2009-01-25 drh: Stmt q; 766bec08ce 2009-01-25 drh: 766bec08ce 2009-01-25 drh: login_check_credentials(); 766bec08ce 2009-01-25 drh: if( !g.okAdmin ){ 766bec08ce 2009-01-25 drh: login_needed(); 766bec08ce 2009-01-25 drh: } 766bec08ce 2009-01-25 drh: style_header("Content Source %d", rcvid); 766bec08ce 2009-01-25 drh: db_prepare(&q, 766bec08ce 2009-01-25 drh: "SELECT login, datetime(rcvfrom.mtime), rcvfrom.ipaddr" 766bec08ce 2009-01-25 drh: " FROM rcvfrom LEFT JOIN user USING(uid)" 766bec08ce 2009-01-25 drh: " WHERE rcvid=%d", 766bec08ce 2009-01-25 drh: rcvid 766bec08ce 2009-01-25 drh: ); 766bec08ce 2009-01-25 drh: @ <table cellspacing=15 cellpadding=0 border=0> 9c89b0e0f1 2009-01-25 drh: @ <tr><td valign="top" align="right"><b>rcvid:</b></td> 766bec08ce 2009-01-25 drh: @ <td valign="top">%d(rcvid)</td></tr> 766bec08ce 2009-01-25 drh: if( db_step(&q)==SQLITE_ROW ){ 766bec08ce 2009-01-25 drh: const char *zUser = db_column_text(&q, 0); 766bec08ce 2009-01-25 drh: const char *zDate = db_column_text(&q, 1); 766bec08ce 2009-01-25 drh: const char *zIpAddr = db_column_text(&q, 2); 9c89b0e0f1 2009-01-25 drh: @ <tr><td valign="top" align="right"><b>User:</b></td> 766bec08ce 2009-01-25 drh: @ <td valign="top">%s(zUser)</td></tr> 9c89b0e0f1 2009-01-25 drh: @ <tr><td valign="top" align="right"><b>Date:</b></td> 766bec08ce 2009-01-25 drh: @ <td valign="top">%s(zDate)</td></tr> 9c89b0e0f1 2009-01-25 drh: @ <tr><td valign="top" align="right"><b>IP Address:</b></td> 766bec08ce 2009-01-25 drh: @ <td valign="top">%s(zIpAddr)</td></tr> 766bec08ce 2009-01-25 drh: } 766bec08ce 2009-01-25 drh: db_finalize(&q); 766bec08ce 2009-01-25 drh: db_prepare(&q, 766bec08ce 2009-01-25 drh: "SELECT rid, uuid, size FROM blob WHERE rcvid=%d", rcvid 766bec08ce 2009-01-25 drh: ); 9c89b0e0f1 2009-01-25 drh: @ <tr><td valign="top" align="right"><b>Artifacts:</b></td> 766bec08ce 2009-01-25 drh: @ <td valign="top"> 766bec08ce 2009-01-25 drh: while( db_step(&q)==SQLITE_ROW ){ 766bec08ce 2009-01-25 drh: int rid = db_column_int(&q, 0); 766bec08ce 2009-01-25 drh: const char *zUuid = db_column_text(&q, 1); 766bec08ce 2009-01-25 drh: int size = db_column_int(&q, 2); 766bec08ce 2009-01-25 drh: @ <a href="%s(g.zBaseURL)/info/%s(zUuid)">%s(zUuid)</a> 766bec08ce 2009-01-25 drh: @ (rid: %d(rid), size: %d(size))<br> 766bec08ce 2009-01-25 drh: } 766bec08ce 2009-01-25 drh: @ </td></tr> 766bec08ce 2009-01-25 drh: @ </table> a48474bc75 2008-05-29 drh: }