@@ -1133,15 +1133,25 @@ def property_detail(property_name, tab):
11331133 )
11341134 uploads = c .fetchall ()
11351135
1136- # Map local dataset filenames to SQL table names (for old/local files )
1136+ # Map local dataset filenames to SQL table names (only if the table exists )
11371137 table_map = {}
11381138 if tab == 'dataset' :
1139+ with sqlite3 .connect (DB_NAME ) as conn :
1140+ existing = {
1141+ r [0 ] for r in conn .execute (
1142+ "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'"
1143+ )
1144+ }
1145+
11391146 for row in uploads :
1140- storage_val = row ['storage' ] if 'storage' in row .keys () else 'local'
1147+ # sqlite3.Row is dict-like; 'storage' may be missing on older rows
1148+ storage_val = (row ['storage' ] if 'storage' in row .keys () and row ['storage' ] else 'local' )
11411149 if storage_val != 'drive' :
1142- fname = row ['filename' ]
1150+ fname = row ['filename' ] # always selected in the query
11431151 if fname and (fname .endswith ('.csv' ) or fname .endswith ('.npy' )):
1144- table_map [fname ] = file_to_table_name (fname )
1152+ tname = file_to_table_name (fname )
1153+ if tname in existing :
1154+ table_map [fname ] = tname
11451155
11461156 return render_template (
11471157 'property_detail.html' ,
@@ -1278,16 +1288,39 @@ def view_table(filename):
12781288
12791289@app .route ('/dataset/<table>' )
12801290def public_view (table ):
1281- # Anyone can view any table
1282- with sqlite3 .connect (DB_NAME ) as conn :
1283- df = pd .read_sql_query (f"SELECT * FROM { table } " , conn )
1284- return render_template ('view_table.html' ,
1285- tables = [df .to_html (classes = 'data' )],
1286- titles = df .columns .values ,
1287- filename = table ,
1288- imported_table = table ,
1289- admin = False )
1290-
1291+ # allow only simple identifiers
1292+ if not re .match (r'^[A-Za-z0-9_]+$' , table or '' ):
1293+ abort (404 )
1294+
1295+ try :
1296+ with sqlite3 .connect (DB_NAME ) as conn :
1297+ # verify table exists
1298+ cur = conn .cursor ()
1299+ cur .execute ("SELECT name FROM sqlite_master WHERE type='table' AND name=?" , (table ,))
1300+ if not cur .fetchone ():
1301+ abort (404 )
1302+
1303+ # quote identifier to avoid issues with reserved words/case
1304+ df = pd .read_sql_query (f'SELECT * FROM "{ table } "' , conn )
1305+
1306+ return render_template (
1307+ 'view_table.html' ,
1308+ tables = [df .to_html (classes = 'data' , index = False )],
1309+ titles = df .columns .values ,
1310+ filename = table ,
1311+ imported_table = table ,
1312+ admin = False
1313+ )
1314+ except Exception as e :
1315+ # don’t 500 the whole app; show a friendly message
1316+ return render_template (
1317+ 'view_table.html' ,
1318+ tables = [f"<p><b>Error loading table '{ table } ':</b> { e } </p>" ],
1319+ titles = [],
1320+ filename = table ,
1321+ imported_table = table ,
1322+ admin = False
1323+ ), 200
12911324#########################################################
12921325
12931326@app .route ('/download/<table>' )
0 commit comments