Index: /trunk/DNSDB.pm
===================================================================
--- /trunk/DNSDB.pm	(revision 17)
+++ /trunk/DNSDB.pm	(revision 18)
@@ -23,6 +23,6 @@
 @ISA		= qw(Exporter);
 @EXPORT_OK	= qw(
-	&initGlobals &connectDB &finish &addDomain &delDomain &domainName &grpName &getSOA &getRecLine
-	&getDomRecs &addRec &updateRec &delRec &domStatus
+	&initGlobals &connectDB &finish &addDomain &delDomain &domainName &addGroup &grpName &getSOA
+	&getRecLine &getDomRecs &addRec &updateRec &delRec &domStatus
 	%typemap %reverse_typemap
 	);
@@ -30,6 +30,6 @@
 @EXPORT		= (); # Export nothing by default.
 %EXPORT_TAGS	= ( ALL => [qw(
-		&initGlobals &connectDB &finish &addDomain &delDomain &domainName &grpName &getSOA &getRecLine
-		&getDomRecs &addRec &updateRec &delRec &domStatus
+		&initGlobals &connectDB &finish &addDomain &delDomain &domainName &addGroup &grpName &getSOA
+		&getRecLine &getDomRecs &addRec &updateRec &delRec &domStatus
 		%typemap %reverse_typemap
 		)]
@@ -256,4 +256,66 @@
 
 
+## DNSDB::addGroup()
+# Add a group
+# Takes a database handle, group name, parent group, and template-vs-cloneme flag
+# Returns a status code and message
+sub addGroup {
+  $errstr = '';
+  my $dbh = shift;
+  my $grpname = shift;
+  my $pargrp = shift;
+
+  # 0 indicates "template", hardcoded.
+  # Any other value clones that group's default records, if it exists.
+  my $torc = shift || 0;	
+
+  # Allow transactions, and raise an exception on errors so we can catch it later.
+  # Use local to make sure these get "reset" properly on exiting this block
+  local $dbh->{AutoCommit} = 0;
+  local $dbh->{RaiseError} = 1;
+
+  # Wrap all the SQL in a transaction
+  eval {
+    my $sth = $dbh->prepare("INSERT INTO groups (parent_group_id,group_name) VALUES (?,?)");
+    $sth->execute($pargrp,$grpname);
+
+    $sth = $dbh->prepare("SELECT group_id FROM groups WHERE group_name=?");
+    $sth->execute($grpname);
+    my ($grpid) = $sth->fetchrow_array();
+
+    $sth = $dbh->prepare("INSERT INTO default_records (group_id,host,type,val,distance,weight,port,ttl) ".
+	"VALUES ($grpid,?,?,?,?,?,?,?)");
+    if ($torc) {
+      my $sth2 = $dbh->prepare("SELECT host,type,val,distance,weight,port,ttl FROM default_records WHERE group_id=?");
+      while (my @clonedata = $sth2->fetchrow_array) {
+	$sth->execute(@clonedata);
+      }
+    } else {
+      # reasonable basic defaults for SOA, MX, NS, and minimal hosting
+      # could load from a config file, but somewhere along the line we need hardcoded bits.
+      $sth->execute('ns1.example.com:hostmaster.example.com', 6, '10800:3600:604800:10800', 0, 0, 0, 86400);
+      $sth->execute('DOMAIN', 1, '192.168.4.2', 0, 0, 0, 7200);
+      $sth->execute('DOMAIN', 15, 'mx.example.com', 10, 0, 0, 7200);
+      $sth->execute('DOMAIN', 2, 'ns1.example.com', 0, 0, 0, 7200);
+      $sth->execute('DOMAIN', 2, 'ns2.example.com', 0, 0, 0, 7200);
+      $sth->execute('www.DOMAIN', 5, 'DOMAIN', 0, 0, 0, 7200);
+    }
+
+die "epic FAIL..  hahahah, just testing!\n";
+    # once we get here, we should have suceeded.
+    $dbh->commit;
+  }; # end eval
+
+  if ($@) {
+    my $msg = $@;
+    eval { $dbh->rollback; };
+    return ('FAIL',$msg);
+  } else {
+    return ('OK','OK');
+  }
+
+} # end addGroup()
+
+
 ## DNSDB::grpName()
 # Return the group name based on a group ID
Index: /trunk/dns.cgi
===================================================================
--- /trunk/dns.cgi	(revision 17)
+++ /trunk/dns.cgi	(revision 18)
@@ -45,9 +45,12 @@
 # need to know the "upper" group the user can deal with;  may as well
 # stick this in the session rather than calling out to the DB every time.
-  $session->param('logingroupid',1);
-  $session->param('workinggroupid',1);	# yes, we *do* need to track this too.  er, probably.
-}
-
+  $session->param('logingroup',1);
+  $session->param('curgroup',1);	# yes, we *do* need to track this too.  er, probably.
+}
+
+my $logingroup = $session->param('logingroup');
+my $curgroup = ($session->param('curgroup') ? $session->param('curgroup') : $session->param('logingroup'));
 my $group = ($webvar{group} ? $webvar{group} : 1);
+
 # handle login redirect
 if ($webvar{action} && $webvar{action} eq 'login') {
@@ -102,4 +105,6 @@
   }
 
+  $page->param(curpage => $webvar{page});
+
   listdomains();
 
@@ -110,5 +115,5 @@
   $page->param(defrec => $webvar{defrec});
   $page->param(id => $webvar{id});
-  $page->param(curpage => 'reclist');
+  $page->param(curpage => $webvar{page});
 
 # select count(*) from (default_)?records where (group|domain)_id=?
@@ -134,18 +139,4 @@
 } elsif ($webvar{page} eq 'newdomain') {
 
-  # weesa gonna discard parent_group_id for now
-  my $sth = $dbh->prepare("select group_id,parent_group_id,name from groups order by group_id");
-  $sth->execute;
-  my @grplist;
-  while (my ($grpid,$pargrp,$grpname) = $sth->fetchrow_array()) {
-    my %row;
-    $row{grpname} = $grpname;
-    $row{grpval} = $grpid;
-##fixme: need magic
-#    $row{defgrp} = '';
-    push @grplist, \%row;
-  }
-
-  $page->param(grplist => \@grplist);
 
 } elsif ($webvar{page} eq 'deldom') {
@@ -384,7 +375,7 @@
 	"LEFT OUTER JOIN domains d ON d.group_id=g.group_id ".
 	"GROUP BY g.group_id, g.group_name, g2.group_name ".
-	"ORDER BY g.group_name".($offset eq 'all' ? '' : " LIMIT $perpage OFFSET ".$offset*$perpage));
-
+	"ORDER BY g.group_id".($offset eq 'all' ? '' : " LIMIT $perpage OFFSET ".$offset*$perpage));
   $sth->execute;
+
   my $rownum = 0;
   while (my @data = $sth->fetchrow_array) {
@@ -401,6 +392,16 @@
   $page->param(grptable => \@grplist);
 
+  $page->param(curpage => $webvar{page});
+
 } elsif ($webvar{page} eq 'newgrp') {
-
+  # do.. uhh.. stuff.. if we have no webvar{action}
+  if ($webvar{action} && $webvar{action} eq 'add') {
+	# not gonna provide the 4th param: template-or-clone flag, just yet
+    my ($code,$msg) = addGroup($dbh, $webvar{newgroup}, $webvar{pargroup});
+    changepage(page => "grpman") if $code eq 'OK';
+    $page->param(add_failed => 1);
+    $page->param(errmsg => $msg);
+    $page->param(newgroup => $webvar{newgroup});
+  }
 }
 
@@ -415,5 +416,5 @@
   $page->param(grp => $group);
   $page->param(grpname => grpName($dbh,$group));
-  $page->param(curpage => $webvar{page});
+  fill_grplist();
 }
 
@@ -433,4 +434,6 @@
 print $footer->output;
 
+# as per the docs, Just In Case
+$session->flush();
 
 exit 0;
@@ -628,2 +631,23 @@
   $page->param(domtable => \@domlist);
 } # end listdomains()
+
+
+sub fill_grplist {
+  # weesa gonna discard parent_group_id for now
+  my $sth = $dbh->prepare("SELECT group_id,parent_group_id,group_name FROM groups ORDER BY group_id");
+push @debugbits, "grp list sth err: ".$sth->errstr."<br>\n";
+  $sth->execute;
+  my @grplist;
+  while (my ($grpid,$pargrp,$grpname) = $sth->fetchrow_array()) {
+    my %row;
+    $row{grpname} = $grpname;
+    $row{grpval} = $grpid;
+##fixme: need magic
+#    $row{defgrp} = '';
+    $row{grpactive} = 1 if $grpid eq $curgroup;
+    push @grplist, \%row;
+  }
+
+  $page->param(grplist => \@grplist);
+
+}
Index: /trunk/templates/addgroup.tmpl
===================================================================
--- /trunk/templates/addgroup.tmpl	(revision 18)
+++ /trunk/templates/addgroup.tmpl	(revision 18)
@@ -0,0 +1,5 @@
+<TMPL_IF add_failed>
+<TMPL_INCLUDE NAME="newdomain.tmpl">
+<TMPL_ELSE>
+<TMPL_INCLUDE NAME="grpman.tmpl">
+</TMPL_IF>
Index: /trunk/templates/menu.tmpl
===================================================================
--- /trunk/templates/menu.tmpl	(revision 17)
+++ /trunk/templates/menu.tmpl	(revision 18)
@@ -1,4 +1,3 @@
 <td class="menu">
-Current group: <TMPL_VAR NAME=grpname><br />
 <a href="dns.cgi?sid=<TMPL_VAR NAME=sid>&page=domlist">Domains</a><br />
 <a href="dns.cgi?sid=<TMPL_VAR NAME=sid>&page=useradmin">Users</a><br />
@@ -7,9 +6,12 @@
 <a href="dns.cgi?sid=<TMPL_VAR NAME=sid>&page=axfr">AXFR Import</a><br />
 <hr>
-<a href="dns.cgi?sid=<TMPL_VAR NAME=sid>&page=grpman">Manage groups</a><br />
+Current group:
 <select name="group">
-	<TMPL_LOOP NAME=grouplist><option value="<TMPL_VAR NAME=grpval>"<TMPL_IF NAME=grplist> selected</TMPL_IF>><TMPL_VAR NAME=grpname></option>
+	<TMPL_LOOP NAME=grplist><option value="<TMPL_VAR NAME=grpval>"<TMPL_IF NAME=grpactive> selected</TMPL_IF>><TMPL_VAR NAME=grpname></option>
 	</TMPL_LOOP>
 </select>
+<hr>
+<a href="dns.cgi?sid=<TMPL_VAR NAME=sid>&page=grpman">Manage groups</a><br />
+ <TMPL_VAR NAME=grpname>
 <hr>
 <a href="dns.cgi?sid=<TMPL_VAR NAME=sid>&page=dnsq">DNS Query</a><br />
