Index: src/setup.c
==================================================================
--- src/setup.c
+++ src/setup.c
@@ -109,10 +109,12 @@
     "A record of login attempts");
   setup_menu_entry("Stats", "stat",
     "Display repository statistics");
   setup_menu_entry("SQL", "admin_sql",
     "Enter raw SQL commands");
+  setup_menu_entry("TH1", "admin_th1",
+    "Enter raw TH1 commands");
   @ </table>
 
   style_footer();
 }
 
@@ -1759,8 +1761,52 @@
         @ </tr>
       }
       sqlite3_finalize(pStmt);
       @ </table>
     }
+  }
+  style_footer();
+}
+
+
+/*
+** WEBPAGE: admin_th1
+**
+** Run raw TH1 commands using the web interface.  If Tcl integration was
+** enabled at compile-time and the "tcl" setting is enabled, Tcl commands
+** may be run as well.
+*/
+void th1_page(void){
+  const char *zQ = P("q");
+  int go = P("go")!=0;
+  login_check_credentials();
+  if( !g.perm.Setup ){
+    login_needed();
+  }
+  db_begin_transaction();
+  style_header("Raw TH1 Commands");
+  @ <p><b>Caution:</b> There are no restrictions on the TH1 that can be
+  @ run by this page.  If Tcl integration was enabled at compile-time and
+  @ the "tcl" setting is enabled, Tcl commands may be run as well.</p>
+  @
+  @ <form method="post" action="%s(g.zTop)/admin_th1">
+  login_insert_csrf_secret();
+  @ TH1:<br />
+  @ <textarea name="q" rows="5" cols="80">%h(zQ)</textarea><br />
+  @ <input type="submit" name="go" value="Run TH1">
+  @ </form>
+  if( go ){
+    const char *zR;
+    int rc;
+    int n;
+    @ <hr />
+    login_verify_csrf_secret();
+    rc = Th_Eval(g.interp, 0, zQ, -1);
+    zR = Th_GetResult(g.interp, &n);
+    if( rc==TH_OK ){
+      @ <pre class="th1result">%h(zR)</pre>
+    }else{
+      @ <pre class="th1error">%h(zR)</pre>
+    }
   }
   style_footer();
 }

Index: src/style.c
==================================================================
--- src/style.c
+++ src/style.c
@@ -994,10 +994,21 @@
   },
   { "span.modpending",
     "Moderation Pending message on timeline",
     @   color: #b03800;
     @   font-style: italic;
+  },
+  { "pre.th1result",
+    "format for th1 script results",
+    @   white-space: pre-wrap;
+    @   word-wrap: break-word;
+  },
+  { "pre.th1error",
+    "format for th1 script errors",
+    @   white-space: pre-wrap;
+    @   word-wrap: break-word;
+    @   color: red;
   },
   { 0,
     0,
     0
   }