remove 'deref_to_tree', not needed anymore
[webgit] / src / query.c
index c31cafd..dd54503 100644 (file)
@@ -2,21 +2,20 @@
     cehtehs git web frontend
 
   Copyright (C)
-    2007,               Christian Thaeter <ct@pipapo.org>
+    2007, 2008,         Christian Thaeter <ct@pipapo.org>
 
-  This program is free software; you can redistribute it and/or
-  modify it under the terms of the GNU General Public License as
-  published by the Free Software Foundation; either version 2 of the
-  License, or (at your option) any later version.
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU Affero General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
+  GNU Affero General Public License for more details.
 
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+  You should have received a copy of the GNU Affero General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 
 #include <time.h>
 
 void
-ctgit_query_init (struct ctgit_query* q)
+webgit_query_init (struct webgit_query* q)
 {
   q->request = NULL;
   q->now = time (NULL);
 
+  q->content_type = cwa_strndup ("application/xhtml+xml", SIZE_MAX);
+
+  q->login_cookie = NULL;
+  q->prefs_cookie = NULL;
+  q->cookie_expire = 365UL * 86400UL; /*1 year*/
+
+  q->count_def = 100;
+  q->rxpd = NULL;
+  q->skindir = cwa_strndup (WEBGIT_SKINDIR_DEFAULT, SIZE_MAX);
+  q->webskindir = cwa_strndup (WEBGIT_WEBSKINDIR_DEFAULT, SIZE_MAX);
+  q->secret = NULL;
+  q->accountdir = NULL;
+  q->maxage = 1000000000;
+
   q->repo = NULL;
-  q->action = cwa_strndup ("main", SIZE_MAX);
+  q->action = NULL;
   q->object = NULL;
   q->head = NULL;
+  q->commit = NULL;
+  q->path = NULL;
+  q->blob = NULL;
+  q->blob_size = 0;
+  q->user = NULL;
+  q->name = NULL;
+  q->email = NULL;
+  q->ssign = NULL;
+  q->recover = 0;
+  q->skin = cwa_strndup (WEBGIT_DEFAULT_SKIN, SIZE_MAX);
+  q->count = -1;
+
   llist_init (&q->repos);
 }
 
-struct ctgit_query*
-ctgit_query_destroy (struct ctgit_query* q)
+struct webgit_query*
+webgit_query_destroy (struct webgit_query* q)
 {
   cgi_free (q->request);
 
+  free (q->login_cookie);
+  free (q->prefs_cookie);
+
+  free (q->content_type);
+  free (q->rxpd);
+  free (q->skindir);
+  free (q->webskindir);
+  free (q->secret);
+  free (q->accountdir);
+
   free (q->repo);
   free (q->action);
   free (q->object);
   free (q->head);
+  free (q->commit);
+  free (q->path);
+  free (q->user);
+  free (q->name);
+  free (q->email);
+  free (q->ssign);
+  free (q->skin);
+  free (q->blob);
 
   LLIST_WHILE_HEAD (&q->repos, head)
-    ctgit_repoinfo_free ((struct ctgit_repo_info*) head);
+    webgit_repoinfo_free ((struct webgit_repo_info*) head);
 
   return q;
 }
 
 
 void
-ctgit_query_add_repo (struct ctgit_query* q, const char* path)
+webgit_query_add_repo (struct webgit_query* q, const char* path)
 {
-  struct ctgit_repo_info* ri = ctgit_repoinfo_new (q, path);
+  struct webgit_repo_info* ri = webgit_repoinfo_new (q, path);
   if (!ri)
     return;
 
   LList p = &q->repos;
   LLIST_FOREACH (&q->repos, node)
     {
-      struct ctgit_repo_info* n = (struct ctgit_repo_info*)node;
+      struct webgit_repo_info* n = (struct webgit_repo_info*)node;
       if (strcmp (n->name, ri->name) > 0)
         break;
       p = node;
@@ -76,67 +119,282 @@ ctgit_query_add_repo (struct ctgit_query* q, const char* path)
   llist_insert_next (p, &ri->node);
 }
 
+int
+webgit_validate_string (const char *s, size_t v_sz)
+{
+  for (const char* c = ";$&|<>!`#"; *c; ++c)
+    if (memchr (s, *c, v_sz))
+      return 0;
+
+  if (cwa_memmem (s, v_sz, "..", 2))
+    return 0;
+
+  return 1;
+}
 
 static void
-ctgit_repo_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
+webgit_repo_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
 {
   (void) self;
-  struct ctgit_query* q = (struct ctgit_query*) u_dat;
+  struct webgit_query* q = (struct webgit_query*) u_dat;
 
-  free (q->repo);
-  q->repo = cwa_strndup (v, v_sz);
+  /* TODO validate that v is a probably legal repo name (alnum()) */
+  if (webgit_validate_string (v, v_sz))
+    {
+      free (q->repo);
+      q->repo = cwa_strndup (v, v_sz);
+    }
 }
 
 
 static void
-ctgit_action_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
+webgit_action_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
 {
   (void) self;
-  struct ctgit_query* q = (struct ctgit_query*) u_dat;
+  struct webgit_query* q = (struct webgit_query*) u_dat;
 
-  free (q->action);
-  q->action = cwa_strndup (v, v_sz);
+  /* TODO validate that v is a probably legal action name alpha() */
+  if (webgit_validate_string (v, v_sz))
+    {
+      free (q->action);
+      q->action = cwa_strndup (v, v_sz);
+    }
 }
 
 
 static void
-ctgit_object_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
+webgit_object_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
 {
   (void) self;
-  struct ctgit_query* q = (struct ctgit_query*) u_dat;
+  struct webgit_query* q = (struct webgit_query*) u_dat;
 
   if (!q->action)
     q->action = cwa_strndup ("object", SIZE_MAX);
 
-  free (q->object);
-  q->object = cwa_strndup (v, v_sz);
+  /* TODO validate that v is a probably sha1 (<=40 chars, hex) */
+  if (webgit_validate_string (v, v_sz))
+    {
+      free (q->object);
+      q->object = cwa_strndup (v, v_sz);
+    }
 }
 
 
 static void
-ctgit_ref_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
+webgit_ref_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
 {
   (void) self;
-  struct ctgit_query* q = (struct ctgit_query*) u_dat;
+  struct webgit_query* q = (struct webgit_query*) u_dat;
 
-  free (q->head);
-  q->head = cwa_strndup (v, v_sz);
+  /* TODO validate that v is a probably legal reference (alnum() || one of '_/.') */
+  if (webgit_validate_string (v, v_sz))
+    {
+      free (q->head);
+      q->head = cwa_strndup (v, v_sz);
+    }
+}
+
+
+static void
+webgit_commit_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
+{
+  (void) self;
+  struct webgit_query* q = (struct webgit_query*) u_dat;
+
+  /* TODO validate that v is a probably legal reference (alnum() || one of '_/.') */
+  if (webgit_validate_string (v, v_sz))
+    {
+      free (q->commit);
+      q->commit = cwa_strndup (v, v_sz);
+    }
+}
+
+
+static void
+webgit_path_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
+{
+  (void) self;
+  struct webgit_query* q = (struct webgit_query*) u_dat;
+
+  /* TODO validate that v is a probably legal reference (alnum() || one of '_/.') */
+  if (webgit_validate_string (v, v_sz))
+    {
+      free (q->path);
+      q->path = cwa_strndup (v, v_sz);
+    }
+}
+
+
+static void
+webgit_blob_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
+{
+  (void) self;
+  struct webgit_query* q = (struct webgit_query*) u_dat;
+
+  free (q->blob);
+  q->blob = cwa_malloc (v_sz + 1);
+  q->blob_size = v_sz;
+  memcpy (q->blob, v, v_sz);
+  q->blob[v_sz] = '\0';
+}
+
+
+static void
+webgit_skin_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
+{
+  (void) self;
+  struct webgit_query* q = (struct webgit_query*) u_dat;
+
+  /* TODO validate that v is a probably legal reference (alnum() || one of '_/.') */
+  if (webgit_validate_string (v, v_sz))
+    {
+      free (q->skin);
+      q->skin = cwa_strndup (v, v_sz);
+    }
+}
+
+
+static void
+webgit_maxage_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
+{
+  (void) self;
+  struct webgit_query* q = (struct webgit_query*) u_dat;
+
+  if (v_sz)
+    {
+      unsigned long maxage = atol (v) * 86400UL;
+
+      LLIST_FOREACH (&q->repos, node)
+        ((struct webgit_repo_info*)node)->maxage = maxage;
+    }
+}
+
+
+static void
+webgit_expire_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
+{
+  (void) self;
+  struct webgit_query* q = (struct webgit_query*) u_dat;
+
+  if (v_sz)
+    {
+      q->cookie_expire = atol (v) * 86400UL;
+    }
+}
+
+
+static void
+webgit_user_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
+{
+  (void) self;
+  struct webgit_query* q = (struct webgit_query*) u_dat;
+
+  if (webgit_validate_string (v, v_sz))
+    {
+      free (q->user);
+      q->user = cwa_strndup (v, v_sz);
+    }
+}
+
+
+static void
+webgit_name_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
+{
+  (void) self;
+  struct webgit_query* q = (struct webgit_query*) u_dat;
+
+  if (webgit_validate_string (v, v_sz))
+    {
+      free (q->name);
+      q->name = cwa_strndup (v, v_sz);
+    }
+}
+
+
+static void
+webgit_email_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
+{
+  (void) self;
+  struct webgit_query* q = (struct webgit_query*) u_dat;
+
+  if (webgit_validate_string (v, v_sz))
+    {
+      free (q->email);
+      q->email = cwa_strndup (v, v_sz);
+    }
+}
+
+
+static void
+webgit_ssign_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
+{
+  (void) self;
+  struct webgit_query* q = (struct webgit_query*) u_dat;
+
+  if (webgit_validate_string (v, v_sz))
+    {
+      free (q->ssign);
+      q->ssign = cwa_strndup (v, v_sz);
+    }
+}
+
+
+static void
+webgit_recover_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
+{
+  (void) self;
+  struct webgit_query* q = (struct webgit_query*) u_dat;
+
+  q->recover = 1;
+}
+
+
+static void
+webgit_login_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
+{
+  if (v_sz)
+    {
+      char *name;
+      char *value;
+      char *data = cwa_urldecode (v);
+
+      while ((data = parse_namevalue (data, &name, &value)))
+        webgit_param_dispatch (self, name, value, value ? strlen (value) : 0, u_dat);
+    }
+}
+
+
+static void
+webgit_prefs_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
+{
+  webgit_login_param (self, v, v_sz, u_dat);
+}
+
+
+static void
+webgit_count_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
+{
+  (void) self;
+  struct webgit_query* q = (struct webgit_query*) u_dat;
+
+  if (v_sz)
+    q->count = atoi (v);
 }
 
 
 void
-ctgit_param_dispatch (const Cgi self,
+webgit_param_dispatch (const Cgi self,
                       const char* name,
                       const char* value,
                       size_t value_len,
                       void* user_data)
 {
-#define CTGIT_PARAM(name, _) {#name, ctgit_##name##_param},
+#define WEBGIT_PARAM(name, _) {#name, webgit_##name##_param},
   struct param_table{
     char* name;
     void (*cb)(const Cgi, const char* v, size_t v_sz, void* u_dat);
-  } cmds[] = {CTGIT_PARAMS {"", NULL}};
-#undef CTGIT_PARAMS
+  } cmds[] = {WEBGIT_PARAMS {"", NULL}};
+#undef WEBGIT_PARAMS
 
   for (struct param_table* j = cmds; j->cb; ++j)
     {
@@ -147,3 +405,11 @@ ctgit_param_dispatch (const Cgi self,
         }
     }
 }
+
+/*
+//      Local Variables:
+//      mode: C
+//      c-file-style: "gnu"
+//      indent-tabs-mode: nil
+//      End:
+*/