File Annotation
Not logged in
e487b77b1a 2008-02-04       drh: /*
e487b77b1a 2008-02-04       drh: ** Copyright (c) 2008 D. Richard Hipp
e487b77b1a 2008-02-04       drh: **
e487b77b1a 2008-02-04       drh: ** This program is free software; you can redistribute it and/or
e487b77b1a 2008-02-04       drh: ** modify it under the terms of the GNU General Public
e487b77b1a 2008-02-04       drh: ** License version 2 as published by the Free Software Foundation.
e487b77b1a 2008-02-04       drh: **
e487b77b1a 2008-02-04       drh: ** This program is distributed in the hope that it will be useful,
e487b77b1a 2008-02-04       drh: ** but WITHOUT ANY WARRANTY; without even the implied warranty of
e487b77b1a 2008-02-04       drh: ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
e487b77b1a 2008-02-04       drh: ** General Public License for more details.
e487b77b1a 2008-02-04       drh: **
e487b77b1a 2008-02-04       drh: ** You should have received a copy of the GNU General Public
e487b77b1a 2008-02-04       drh: ** License along with this library; if not, write to the
e487b77b1a 2008-02-04       drh: ** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
e487b77b1a 2008-02-04       drh: ** Boston, MA  02111-1307, USA.
e487b77b1a 2008-02-04       drh: **
e487b77b1a 2008-02-04       drh: ** Author contact information:
e487b77b1a 2008-02-04       drh: **   drh@hwaci.com
e487b77b1a 2008-02-04       drh: **   http://www.hwaci.com/drh/
e487b77b1a 2008-02-04       drh: **
e487b77b1a 2008-02-04       drh: *******************************************************************************
e487b77b1a 2008-02-04       drh: **
e487b77b1a 2008-02-04       drh: ** This file contains code to implement the file browser web interface.
e487b77b1a 2008-02-04       drh: */
e487b77b1a 2008-02-04       drh: #include "config.h"
e487b77b1a 2008-02-04       drh: #include "browse.h"
e487b77b1a 2008-02-04       drh: #include <assert.h>
e487b77b1a 2008-02-04       drh: 
e487b77b1a 2008-02-04       drh: /*
e487b77b1a 2008-02-04       drh: ** This is the implemention of the "pathelement(X,N)" SQL function.
e487b77b1a 2008-02-04       drh: **
e487b77b1a 2008-02-04       drh: ** If X is a unix-like pathname (with "/" separators) and N is an
e487b77b1a 2008-02-04       drh: ** integer, then skip the initial N characters of X and return the
e487b77b1a 2008-02-04       drh: ** name of the path component that begins on the N+1th character
e487b77b1a 2008-02-04       drh: ** (numbered from 0).  If the path component is a directory (if
e487b77b1a 2008-02-04       drh: ** it is followed by other path components) then prepend "/".
e487b77b1a 2008-02-04       drh: **
e487b77b1a 2008-02-04       drh: ** Examples:
e487b77b1a 2008-02-04       drh: **
e487b77b1a 2008-02-04       drh: **      pathelement('abc/pqr/xyz', 4)  ->  '/pqr'
e487b77b1a 2008-02-04       drh: **      pathelement('abc/pqr', 4)      ->  'pqr'
e487b77b1a 2008-02-04       drh: **      pathelement('abc/pqr/xyz', 0)  ->  '/abc'
e487b77b1a 2008-02-04       drh: */
e487b77b1a 2008-02-04       drh: static void pathelementFunc(
e487b77b1a 2008-02-04       drh:   sqlite3_context *context,
e487b77b1a 2008-02-04       drh:   int argc,
e487b77b1a 2008-02-04       drh:   sqlite3_value **argv
e487b77b1a 2008-02-04       drh: ){
e487b77b1a 2008-02-04       drh:   const unsigned char *z;
e487b77b1a 2008-02-04       drh:   int len, n, i;
e487b77b1a 2008-02-04       drh:   char *zOut;
e487b77b1a 2008-02-04       drh: 
e487b77b1a 2008-02-04       drh:   assert( argc==2 );
e487b77b1a 2008-02-04       drh:   z = sqlite3_value_text(argv[0]);
e487b77b1a 2008-02-04       drh:   if( z==0 ) return;
e487b77b1a 2008-02-04       drh:   len = sqlite3_value_bytes(argv[0]);
e487b77b1a 2008-02-04       drh:   n = sqlite3_value_int(argv[1]);
e487b77b1a 2008-02-04       drh:   if( len<=n ) return;
e487b77b1a 2008-02-04       drh:   if( n>0 && z[n-1]!='/' ) return;
e487b77b1a 2008-02-04       drh:   for(i=n; i<len && z[i]!='/'; i++){}
e487b77b1a 2008-02-04       drh:   if( i==len ){
e487b77b1a 2008-02-04       drh:     sqlite3_result_text(context, (char*)&z[n], len-n, SQLITE_TRANSIENT);
e487b77b1a 2008-02-04       drh:   }else{
e487b77b1a 2008-02-04       drh:     zOut = sqlite3_mprintf("/%.*s", i-n, &z[n]);
e487b77b1a 2008-02-04       drh:     sqlite3_result_text(context, zOut, i-n+1, sqlite3_free);
e487b77b1a 2008-02-04       drh:   }
e487b77b1a 2008-02-04       drh: }
e487b77b1a 2008-02-04       drh: 
e487b77b1a 2008-02-04       drh: 
e487b77b1a 2008-02-04       drh: /*
e487b77b1a 2008-02-04       drh: ** WEBPAGE: dir
e487b77b1a 2008-02-04       drh: **
e487b77b1a 2008-02-04       drh: ** Query parameters:
e487b77b1a 2008-02-04       drh: **
e487b77b1a 2008-02-04       drh: **    d=PATH        Directory to display.  Required.
e487b77b1a 2008-02-04       drh: */
e487b77b1a 2008-02-04       drh: void page_dir(void){
e487b77b1a 2008-02-04       drh:   const char *zD = P("d");
e487b77b1a 2008-02-04       drh:   int mxLen;
e487b77b1a 2008-02-04       drh:   int nCol, nRow;
e487b77b1a 2008-02-04       drh:   int cnt, i;
e487b77b1a 2008-02-04       drh:   char *zPrefix;
e487b77b1a 2008-02-04       drh:   Stmt q;
e487b77b1a 2008-02-04       drh: 
e487b77b1a 2008-02-04       drh:   login_check_credentials();
e487b77b1a 2008-02-04       drh:   if( !g.okHistory ){ login_needed(); return; }
e487b77b1a 2008-02-04       drh:   style_header("File List");
e487b77b1a 2008-02-04       drh:   sqlite3_create_function(g.db, "pathelement", 2, SQLITE_UTF8, 0,
e487b77b1a 2008-02-04       drh:                           pathelementFunc, 0, 0);
e487b77b1a 2008-02-04       drh: 
e487b77b1a 2008-02-04       drh:   /* If the d= parameter is an empty string, make it a NULL pointer */
e487b77b1a 2008-02-04       drh:   if( zD && strlen(zD)==0 ){ zD = 0; }
e487b77b1a 2008-02-04       drh: 
e487b77b1a 2008-02-04       drh:   /* Compute the title of the page */
e487b77b1a 2008-02-04       drh:   if( zD ){
e487b77b1a 2008-02-04       drh:     int i, j;
e487b77b1a 2008-02-04       drh:     char *zCopy;
e487b77b1a 2008-02-04       drh:     Blob title;
e487b77b1a 2008-02-04       drh: 
e487b77b1a 2008-02-04       drh:     blob_zero(&title);
e487b77b1a 2008-02-04       drh:     zCopy = sqlite3_mprintf("%s/", zD);
e487b77b1a 2008-02-04       drh:     blob_appendf(&title,
e487b77b1a 2008-02-04       drh:        "Files in directory <a href=\"%s/dir\"><i>root</i></a>",
e487b77b1a 2008-02-04       drh:        g.zBaseURL
e487b77b1a 2008-02-04       drh:     );
e487b77b1a 2008-02-04       drh:     for(i=0; zD[i]; i=j){
e487b77b1a 2008-02-04       drh:       for(j=i; zD[j] && zD[j]!='/'; j++){}
e487b77b1a 2008-02-04       drh:       if( zD[j] ){
e487b77b1a 2008-02-04       drh:         zCopy[j] = 0;
e487b77b1a 2008-02-04       drh:         blob_appendf(&title, "/<a href=\"%s/dir?d=%T\">%h</a>",
e487b77b1a 2008-02-04       drh:                      g.zBaseURL, zCopy, &zCopy[i]);
e487b77b1a 2008-02-04       drh:         zCopy[j] = '/';
e487b77b1a 2008-02-04       drh:       }else{
e487b77b1a 2008-02-04       drh:         blob_appendf(&title, "/%h", &zCopy[i]);
e487b77b1a 2008-02-04       drh:       }
e487b77b1a 2008-02-04       drh:       while( zD[j]=='/' ){ j++; }
e487b77b1a 2008-02-04       drh:     }
e487b77b1a 2008-02-04       drh:     @ <h2>%s(blob_str(&title))</h2>
e487b77b1a 2008-02-04       drh:     blob_reset(&title);
e487b77b1a 2008-02-04       drh:     zPrefix = zCopy;
e487b77b1a 2008-02-04       drh:   }else{
e487b77b1a 2008-02-04       drh:     @ <h2>Files in the top-level directory</h2>
e487b77b1a 2008-02-04       drh:     zPrefix = "";
e487b77b1a 2008-02-04       drh:   }
e487b77b1a 2008-02-04       drh: 
e487b77b1a 2008-02-04       drh:   /* Compute the temporary table "localfiles" containing the names
e487b77b1a 2008-02-04       drh:   ** of all files and subdirectories in the zD[] directory.
e487b77b1a 2008-02-04       drh:   **
e487b77b1a 2008-02-04       drh:   ** Subdirectory names begin with "/".  This causes them to sort
e487b77b1a 2008-02-04       drh:   ** first and it also gives us an easy way to distinguish files
e487b77b1a 2008-02-04       drh:   ** from directories in the loop that follows.
e487b77b1a 2008-02-04       drh:   */
e487b77b1a 2008-02-04       drh:   if( zD ){
e487b77b1a 2008-02-04       drh:     db_multi_exec(
e487b77b1a 2008-02-04       drh:        "CREATE TEMP TABLE localfiles(x UNIQUE NOT NULL);"
e487b77b1a 2008-02-04       drh:        "INSERT OR IGNORE INTO localfiles "
e487b77b1a 2008-02-04       drh:        "  SELECT pathelement(name,%d) FROM filename"
e487b77b1a 2008-02-04       drh:        "   WHERE +name GLOB '%q/*'",
e487b77b1a 2008-02-04       drh:        strlen(zD)+1, zD
e487b77b1a 2008-02-04       drh:     );
e487b77b1a 2008-02-04       drh:   }else{
e487b77b1a 2008-02-04       drh:     db_multi_exec(
e487b77b1a 2008-02-04       drh:        "CREATE TEMP TABLE localfiles(x UNIQUE NOT NULL);"
e487b77b1a 2008-02-04       drh:        "INSERT OR IGNORE INTO localfiles "
e487b77b1a 2008-02-04       drh:        "  SELECT pathelement(name,0) FROM filename"
e487b77b1a 2008-02-04       drh:     );
e487b77b1a 2008-02-04       drh:   }
e487b77b1a 2008-02-04       drh: 
e487b77b1a 2008-02-04       drh:   /* Generate a multi-column table listing the contents of zD[]
e487b77b1a 2008-02-04       drh:   ** directory.
e487b77b1a 2008-02-04       drh:   */
e487b77b1a 2008-02-04       drh:   mxLen = db_int(12, "SELECT max(length(x)) FROM localfiles");
e487b77b1a 2008-02-04       drh:   cnt = db_int(0, "SELECT count(*) FROM localfiles");
e487b77b1a 2008-02-04       drh:   nCol = 4;
e487b77b1a 2008-02-04       drh:   nRow = (cnt+nCol-1)/nCol;
e487b77b1a 2008-02-04       drh:   db_prepare(&q, "SELECT x FROM localfiles ORDER BY x");
e487b77b1a 2008-02-04       drh:   @ <table border="0" width="100%%"><tr><td valign="top" width="25%%">
e487b77b1a 2008-02-04       drh:   i = 0;
e487b77b1a 2008-02-04       drh:   while( db_step(&q)==SQLITE_ROW ){
e487b77b1a 2008-02-04       drh:     const char *zFName;
e487b77b1a 2008-02-04       drh:     if( i==nRow ){
e487b77b1a 2008-02-04       drh:       @ </td><td valign="top" width="25%%">
e487b77b1a 2008-02-04       drh:       i = 0;
e487b77b1a 2008-02-04       drh:     }
e487b77b1a 2008-02-04       drh:     i++;
e487b77b1a 2008-02-04       drh:     zFName = db_column_text(&q, 0);
e487b77b1a 2008-02-04       drh:     if( zFName[0]=='/' ){
e487b77b1a 2008-02-04       drh:       zFName++;
e487b77b1a 2008-02-04       drh:       @ <li><a href="%s(g.zBaseURL)/dir?d=%T(zPrefix)%T(zFName)">
e487b77b1a 2008-02-04       drh:       @     %h(zFName)/</a></li>
e487b77b1a 2008-02-04       drh:     }else{
e487b77b1a 2008-02-04       drh:       @ <li><a href="%s(g.zBaseURL)/finfo?name=%T(zPrefix)%T(zFName)">
e487b77b1a 2008-02-04       drh:       @     %h(zFName)</a></li>
e487b77b1a 2008-02-04       drh:     }
e487b77b1a 2008-02-04       drh:   }
e487b77b1a 2008-02-04       drh:   db_finalize(&q);
e487b77b1a 2008-02-04       drh:   @ </td></tr></table>
e487b77b1a 2008-02-04       drh:   style_footer();
e487b77b1a 2008-02-04       drh: }