File Annotation
Not logged in
2e9d52f27f 2007-10-02       drh: /*
2e9d52f27f 2007-10-02       drh: ** Copyright (c) 2007 D. Richard Hipp
2e9d52f27f 2007-10-02       drh: **
2e9d52f27f 2007-10-02       drh: ** This program is free software; you can redistribute it and/or
2e9d52f27f 2007-10-02       drh: ** modify it under the terms of the GNU General Public
2e9d52f27f 2007-10-02       drh: ** License version 2 as published by the Free Software Foundation.
2e9d52f27f 2007-10-02       drh: **
2e9d52f27f 2007-10-02       drh: ** This program is distributed in the hope that it will be useful,
2e9d52f27f 2007-10-02       drh: ** but WITHOUT ANY WARRANTY; without even the implied warranty of
2e9d52f27f 2007-10-02       drh: ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
2e9d52f27f 2007-10-02       drh: ** General Public License for more details.
2e9d52f27f 2007-10-02       drh: **
2e9d52f27f 2007-10-02       drh: ** You should have received a copy of the GNU General Public
2e9d52f27f 2007-10-02       drh: ** License along with this library; if not, write to the
2e9d52f27f 2007-10-02       drh: ** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
2e9d52f27f 2007-10-02       drh: ** Boston, MA  02111-1307, USA.
2e9d52f27f 2007-10-02       drh: **
2e9d52f27f 2007-10-02       drh: ** Author contact information:
2e9d52f27f 2007-10-02       drh: **   drh@hwaci.com
2e9d52f27f 2007-10-02       drh: **   http://www.hwaci.com/drh/
2e9d52f27f 2007-10-02       drh: **
2e9d52f27f 2007-10-02       drh: *******************************************************************************
2e9d52f27f 2007-10-02       drh: **
2e9d52f27f 2007-10-02       drh: ** This file contains code used to parser ticket configuration
2e9d52f27f 2007-10-02       drh: ** artificates.
2e9d52f27f 2007-10-02       drh: */
2e9d52f27f 2007-10-02       drh: #include "config.h"
2e9d52f27f 2007-10-02       drh: #include "tktconf.h"
2e9d52f27f 2007-10-02       drh: #include <assert.h>
2e9d52f27f 2007-10-02       drh: 
2e9d52f27f 2007-10-02       drh: /*
2e9d52f27f 2007-10-02       drh: ** Return TRUE if the given token is a valid field name for
2e9d52f27f 2007-10-02       drh: ** the ticket table.  The name must be all letters, digits,
2e9d52f27f 2007-10-02       drh: ** and underscores.
2e9d52f27f 2007-10-02       drh: */
2e9d52f27f 2007-10-02       drh: static int is_valid_name(Blob *p){
2e9d52f27f 2007-10-02       drh:   const char *z = blob_buffer(p);
2e9d52f27f 2007-10-02       drh:   int n = blob_size(p);
2e9d52f27f 2007-10-02       drh:   int i;
2e9d52f27f 2007-10-02       drh: 
2e9d52f27f 2007-10-02       drh:   for(i=0; i<n; i++){
2e9d52f27f 2007-10-02       drh:     if( !isalnum(z[i]) && z[i]!='_' ){
2e9d52f27f 2007-10-02       drh:       return 0;
2e9d52f27f 2007-10-02       drh:     }
2e9d52f27f 2007-10-02       drh:   }
2e9d52f27f 2007-10-02       drh:   return 1;
2e9d52f27f 2007-10-02       drh: }
2e9d52f27f 2007-10-02       drh: 
2e9d52f27f 2007-10-02       drh: /*
2e9d52f27f 2007-10-02       drh: ** Return TRUE if the given token is a valid enumeration value.
2e9d52f27f 2007-10-02       drh: ** The token must consist of the following characters:
2e9d52f27f 2007-10-02       drh: **
2e9d52f27f 2007-10-02       drh: ** a-zA-Z0-9_%/.-
2e9d52f27f 2007-10-02       drh: */
2e9d52f27f 2007-10-02       drh: static int is_valid_enum(Blob *p){
2e9d52f27f 2007-10-02       drh:   const char *z = blob_buffer(p);
2e9d52f27f 2007-10-02       drh:   int n = blob_size(p);
2e9d52f27f 2007-10-02       drh:   int i;
2e9d52f27f 2007-10-02       drh: 
2e9d52f27f 2007-10-02       drh:   for(i=0; i<n; i++){
2e9d52f27f 2007-10-02       drh:     int c = z[i];
2e9d52f27f 2007-10-02       drh:     if( !isalnum(c) && c!='_' && c!='%' && c!='/' && c!='.' && c!='-' ){
2e9d52f27f 2007-10-02       drh:       return 0;
2e9d52f27f 2007-10-02       drh:     }
2e9d52f27f 2007-10-02       drh:   }
2e9d52f27f 2007-10-02       drh:   return 1;
2e9d52f27f 2007-10-02       drh: }
2e9d52f27f 2007-10-02       drh: 
2e9d52f27f 2007-10-02       drh: 
2e9d52f27f 2007-10-02       drh: /*
2e9d52f27f 2007-10-02       drh: ** A ticket configuration record is a single artifact that defines
2e9d52f27f 2007-10-02       drh: ** the ticket configuration for a server.  The file format is as
2e9d52f27f 2007-10-02       drh: ** follows:
2e9d52f27f 2007-10-02       drh: **
2e9d52f27f 2007-10-02       drh: **     ticket-configuration
2e9d52f27f 2007-10-02       drh: **     field <fieldname> <fieldtype> <width> <param> ...
2e9d52f27f 2007-10-02       drh: **     template <type> <delimiter>
2e9d52f27f 2007-10-02       drh: **     <text>
0edee97370 2007-10-03       drh: **     description <delimiter>
0edee97370 2007-10-03       drh: **     <text>
2e9d52f27f 2007-10-02       drh: **
2e9d52f27f 2007-10-02       drh: ** All lines are separated by \n.  Trailing whitespace is
2e9d52f27f 2007-10-02       drh: ** ignored.  The first line must be "ticket-configuration".
2e9d52f27f 2007-10-02       drh: ** Subsequent lines are either "field" or "template" lines.
2e9d52f27f 2007-10-02       drh: ** There must be exactly three template lines and one or more
2e9d52f27f 2007-10-02       drh: ** field lines (usually more).
2e9d52f27f 2007-10-02       drh: **
2e9d52f27f 2007-10-02       drh: ** Field lines define the fields of the "ticket" table in the
2e9d52f27f 2007-10-02       drh: ** database.  The fields appear in the table in the order in
2e9d52f27f 2007-10-02       drh: ** which they appear in the configuration artifact.  The <fieldname>
2e9d52f27f 2007-10-02       drh: ** must consist of alphanumerics and underscores.  <fieldtype>
0edee97370 2007-10-03       drh: ** is one of:  text, ctext, enum, date, uuid, baseline, private.  All
2e9d52f27f 2007-10-02       drh: ** types have at least a <width> parameter.  Text and Ctext types
2e9d52f27f 2007-10-02       drh: ** have a height parameter.  Enum has a list of allowed values.
2e9d52f27f 2007-10-02       drh: **
2e9d52f27f 2007-10-02       drh: ** The <type> of a template is one of: new, view, edit.  There must
2e9d52f27f 2007-10-02       drh: ** be one template of each type.  <delimiter> is an arbitrary string
2e9d52f27f 2007-10-02       drh: ** that terminates the template.  The body of the template is subsequent
2e9d52f27f 2007-10-02       drh: ** lines of text up to but not including the <delimiter>.  Trailing
2e9d52f27f 2007-10-02       drh: ** whitespace on the delimiter is ignored.
0edee97370 2007-10-03       drh: **
0edee97370 2007-10-03       drh: ** There should be one description entry.  The text that follows
0edee97370 2007-10-03       drh: ** is a human-readable plaintext description of this ticket
0edee97370 2007-10-03       drh: ** configuration.  The description is visible to the administrator
0edee97370 2007-10-03       drh: ** and is used to help identify this configuration among several
0edee97370 2007-10-03       drh: ** options.  The first line of the description is a one-line
0edee97370 2007-10-03       drh: ** summary.  Subsequent lines are details.
2e9d52f27f 2007-10-02       drh: **
2e9d52f27f 2007-10-02       drh: ** The pConfig parameter is the complete text of the configuration
2e9d52f27f 2007-10-02       drh: ** file to be parsed.  testFlag is 1 to cause the results to be printed
2e9d52f27f 2007-10-02       drh: ** on stdout or 0 to cause results to update the database.
2e9d52f27f 2007-10-02       drh: **
2e9d52f27f 2007-10-02       drh: ** Return the number of errors.  If there is an error and pErr!=NULL
2e9d52f27f 2007-10-02       drh: ** then leave an error message in pErr.  We assume that pErr has already
2e9d52f27f 2007-10-02       drh: ** been initialized.
2e9d52f27f 2007-10-02       drh: */
2e9d52f27f 2007-10-02       drh: int ticket_config_parse(Blob *pConfig, int testFlag, Blob *pErr){
2e9d52f27f 2007-10-02       drh:   int rc = 1;
2e9d52f27f 2007-10-02       drh:   Blob line;
2e9d52f27f 2007-10-02       drh:   Blob token;
2e9d52f27f 2007-10-02       drh:   Blob name;
2e9d52f27f 2007-10-02       drh:   Blob type;
2e9d52f27f 2007-10-02       drh:   Blob arg;
2e9d52f27f 2007-10-02       drh:   Blob sql;
2e9d52f27f 2007-10-02       drh:   Blob tbldef;
2e9d52f27f 2007-10-02       drh:   Blob err;
2e9d52f27f 2007-10-02       drh:   int seen_template = 0;
2e9d52f27f 2007-10-02       drh:   int lineno = 0;
2e9d52f27f 2007-10-02       drh: 
2e9d52f27f 2007-10-02       drh:   blob_zero(&sql);
2e9d52f27f 2007-10-02       drh:   blob_zero(&tbldef);
2e9d52f27f 2007-10-02       drh:   blob_zero(&token);
2e9d52f27f 2007-10-02       drh:   blob_zero(&name);
2e9d52f27f 2007-10-02       drh:   blob_zero(&type);
2e9d52f27f 2007-10-02       drh:   blob_zero(&arg);
2e9d52f27f 2007-10-02       drh:   blob_zero(&err);
2e9d52f27f 2007-10-02       drh: 
2e9d52f27f 2007-10-02       drh:   /* The configuration file must begin with a line that
2e9d52f27f 2007-10-02       drh:   ** says "ticket-configuration"
2e9d52f27f 2007-10-02       drh:   */
2e9d52f27f 2007-10-02       drh:   blob_line(pConfig, &line);
2e9d52f27f 2007-10-02       drh:   blob_token(&line, &token);
2e9d52f27f 2007-10-02       drh:   if( !blob_eq(&token, "ticket-configuration") ){
2e9d52f27f 2007-10-02       drh:     blob_appendf(&err, "missing initialization keyword");
2e9d52f27f 2007-10-02       drh:     goto bad_config_file;
2e9d52f27f 2007-10-02       drh:   }
2e9d52f27f 2007-10-02       drh:   lineno++;
2e9d52f27f 2007-10-02       drh: 
2e9d52f27f 2007-10-02       drh:   /* Begin accumulating SQL text that will implement the
2e9d52f27f 2007-10-02       drh:   ** ticket configuration.  tbldef will hold the ticket table
2e9d52f27f 2007-10-02       drh:   ** definition.  sql will hold text to initialize and define
2e9d52f27f 2007-10-02       drh:   ** the tktfield table and to insert template text into the
2e9d52f27f 2007-10-02       drh:   ** config table
2e9d52f27f 2007-10-02       drh:   */
2e9d52f27f 2007-10-02       drh:   blob_appendf(&tbldef,
2e9d52f27f 2007-10-02       drh:      "DROP TABLE IF EXISTS ticket;\n"
2e9d52f27f 2007-10-02       drh:      "CREATE TABLE ticket(\n"
2e9d52f27f 2007-10-02       drh:      "  tktid INTEGER PRIMARY KEY,\n"
2e9d52f27f 2007-10-02       drh:      "  tktuuid TEXT UNIQUE,\n"
2e9d52f27f 2007-10-02       drh:      "  starttime DATETIME,\n"
2e9d52f27f 2007-10-02       drh:      "  lastmod DATETIME"
2e9d52f27f 2007-10-02       drh:   );
2e9d52f27f 2007-10-02       drh:   blob_appendf(&sql,
2e9d52f27f 2007-10-02       drh:      "DROP TABLE IF EXISTS tktfield;\n"
2e9d52f27f 2007-10-02       drh:      "CREATE TABLE tktfield(\n"
2e9d52f27f 2007-10-02       drh:      "  fidx INTEGER PRIMARY KEY,\n"
2e9d52f27f 2007-10-02       drh:      "  name TEXT UNIQUE,\n"
2e9d52f27f 2007-10-02       drh:      "  type TEXT,\n"
2e9d52f27f 2007-10-02       drh:      "  width INTEGER,\n"
2e9d52f27f 2007-10-02       drh:      "  arg\n"
2e9d52f27f 2007-10-02       drh:      ");\n"
2e9d52f27f 2007-10-02       drh:   );
2e9d52f27f 2007-10-02       drh: 
2e9d52f27f 2007-10-02       drh:   /* Process the remainder of the configuration file (the part that
2e9d52f27f 2007-10-02       drh:   ** comes after the "ticket-configuration" header) line by line
2e9d52f27f 2007-10-02       drh:   */
2e9d52f27f 2007-10-02       drh:   while( blob_line(pConfig, &line) ){
2e9d52f27f 2007-10-02       drh:     char *z;
2e9d52f27f 2007-10-02       drh:     lineno++;
2e9d52f27f 2007-10-02       drh:     if( blob_token(&line, &token)==0 ){
2e9d52f27f 2007-10-02       drh:       /* Ignore blank lines */
2e9d52f27f 2007-10-02       drh:       continue;
2e9d52f27f 2007-10-02       drh:     }
2e9d52f27f 2007-10-02       drh:     z = blob_buffer(&token);
2e9d52f27f 2007-10-02       drh:     if( z[0]=='#' ){
2e9d52f27f 2007-10-02       drh:       /* Ignore comment lines */
2e9d52f27f 2007-10-02       drh:       continue;
2e9d52f27f 2007-10-02       drh:     }
2e9d52f27f 2007-10-02       drh: 
2e9d52f27f 2007-10-02       drh:     /*
2e9d52f27f 2007-10-02       drh:     **    field <name> <type> <width> <args...>
2e9d52f27f 2007-10-02       drh:     */
2e9d52f27f 2007-10-02       drh:     if( blob_eq(&token, "field")
2e9d52f27f 2007-10-02       drh:      && blob_token(&line,&name)
2e9d52f27f 2007-10-02       drh:      && blob_token(&line,&type)
2e9d52f27f 2007-10-02       drh:      && blob_token(&line,&arg)
2e9d52f27f 2007-10-02       drh:     ){
2e9d52f27f 2007-10-02       drh:       int width;
2e9d52f27f 2007-10-02       drh: 
2e9d52f27f 2007-10-02       drh:       if( !is_valid_name(&name) ){
2e9d52f27f 2007-10-02       drh:         blob_appendf(&err, "invalid field name: %b", &name);
2e9d52f27f 2007-10-02       drh:         goto bad_config_file;
2e9d52f27f 2007-10-02       drh:       }
2e9d52f27f 2007-10-02       drh:       if( !blob_is_int(&arg, &width) ){
2e9d52f27f 2007-10-02       drh:         blob_appendf(&err, "invalid field width: %b", &arg);
2e9d52f27f 2007-10-02       drh:         goto bad_config_file;
2e9d52f27f 2007-10-02       drh:       }
2e9d52f27f 2007-10-02       drh:       if( width<1 || width>200 ){
2e9d52f27f 2007-10-02       drh:         blob_appendf(&err, "width less than 1 or greater than 200");
2e9d52f27f 2007-10-02       drh:         goto bad_config_file;
2e9d52f27f 2007-10-02       drh:       }
2e9d52f27f 2007-10-02       drh:       blob_appendf(&tbldef, ",\n  tkt_%b", &name);
0edee97370 2007-10-03       drh:       if( blob_eq(&type,"text") || blob_eq(&type,"ctext")
0edee97370 2007-10-03       drh:             || blob_eq(&type,"private") ){
2e9d52f27f 2007-10-02       drh:         int height;
2e9d52f27f 2007-10-02       drh:         if( !blob_token(&line, &arg) || !blob_is_int(&arg, &height) ){
2e9d52f27f 2007-10-02       drh:           blob_appendf(&err, "invalid height: %b", &arg);
2e9d52f27f 2007-10-02       drh:           goto bad_config_file;
2e9d52f27f 2007-10-02       drh:         }
2e9d52f27f 2007-10-02       drh:         if( height<1 || height>1000 ){
2e9d52f27f 2007-10-02       drh:           blob_appendf(&err, "height less than 1 or greater than 1000");
2e9d52f27f 2007-10-02       drh:           goto bad_config_file;
2e9d52f27f 2007-10-02       drh:         }
2e9d52f27f 2007-10-02       drh:         blob_appendf(&sql,
2e9d52f27f 2007-10-02       drh:           "INSERT INTO tktfield(name,type,width,arg)"
2e9d52f27f 2007-10-02       drh:           "VALUES('%b','%b',%d,%d);\n",
2e9d52f27f 2007-10-02       drh:           &name, &type, width, height
2e9d52f27f 2007-10-02       drh:         );
2e9d52f27f 2007-10-02       drh:       }else if( blob_eq(&type,"enum") ){
2e9d52f27f 2007-10-02       drh:         int cnt = 0;
2e9d52f27f 2007-10-02       drh:         const char *zDelim = "'";
2e9d52f27f 2007-10-02       drh:         blob_appendf(&sql,
2e9d52f27f 2007-10-02       drh:           "INSERT INTO tktfield(name,type,width,arg)"
2e9d52f27f 2007-10-02       drh:           "VALUES('%b','%b',%d,",
2e9d52f27f 2007-10-02       drh:           &name, &type, width
2e9d52f27f 2007-10-02       drh:         );
2e9d52f27f 2007-10-02       drh:         while( blob_token(&line, &arg) ){
2e9d52f27f 2007-10-02       drh:           if( !is_valid_enum(&arg) ){
2e9d52f27f 2007-10-02       drh:             blob_appendf(&err, "invalid enumeration value: %b", &arg);
2e9d52f27f 2007-10-02       drh:             goto bad_config_file;
2e9d52f27f 2007-10-02       drh:           }
2e9d52f27f 2007-10-02       drh:           cnt++;
2e9d52f27f 2007-10-02       drh:           blob_appendf(&sql, "%s%b", zDelim, &arg);
2e9d52f27f 2007-10-02       drh:           zDelim = " ";
2e9d52f27f 2007-10-02       drh:         }
2e9d52f27f 2007-10-02       drh:         if( cnt<2 ){
2e9d52f27f 2007-10-02       drh:           blob_appendf(&err, "less than 2 enumeration values");
2e9d52f27f 2007-10-02       drh:           goto bad_config_file;
2e9d52f27f 2007-10-02       drh:         }
2e9d52f27f 2007-10-02       drh:         blob_appendf(&sql,"');\n");
2e9d52f27f 2007-10-02       drh:       }else if( blob_eq(&type,"uuid") || blob_eq(&type,"baseline") ||
2e9d52f27f 2007-10-02       drh:                 blob_eq(&type,"date") ){
2e9d52f27f 2007-10-02       drh:         blob_appendf(&sql,
2e9d52f27f 2007-10-02       drh:           "INSERT INTO tktfield(name,type,width)"
2e9d52f27f 2007-10-02       drh:           "VALUES('%b','%b',%d);\n",
2e9d52f27f 2007-10-02       drh:           &name, &type, width
2e9d52f27f 2007-10-02       drh:         );
2e9d52f27f 2007-10-02       drh:       }else{
2e9d52f27f 2007-10-02       drh:         blob_appendf(&err, "unknown field type: %b", &type);
2e9d52f27f 2007-10-02       drh:         goto bad_config_file;
2e9d52f27f 2007-10-02       drh:       }
0edee97370 2007-10-03       drh:     }else
2e9d52f27f 2007-10-02       drh: 
2e9d52f27f 2007-10-02       drh:     /*
2e9d52f27f 2007-10-02       drh:     **  template <type> <delimiter>
2e9d52f27f 2007-10-02       drh:     **  <text>
2e9d52f27f 2007-10-02       drh:     */
0edee97370 2007-10-03       drh:     if( blob_eq(&token, "template")
0edee97370 2007-10-03       drh:      && blob_token(&line, &type)
0edee97370 2007-10-03       drh:      && blob_token(&line, &arg)
2e9d52f27f 2007-10-02       drh:     ){
2e9d52f27f 2007-10-02       drh:       int idx;
2e9d52f27f 2007-10-02       drh:       Blob content;
2e9d52f27f 2007-10-02       drh:       int start;
2e9d52f27f 2007-10-02       drh:       int end;
2e9d52f27f 2007-10-02       drh: 
2e9d52f27f 2007-10-02       drh:       if( blob_eq(&type,"new") ){
2e9d52f27f 2007-10-02       drh:         idx = 0;
2e9d52f27f 2007-10-02       drh:       }else if( blob_eq(&type, "view") ){
2e9d52f27f 2007-10-02       drh:         idx = 1;
2e9d52f27f 2007-10-02       drh:       }else if( blob_eq(&type, "edit") ){
2e9d52f27f 2007-10-02       drh:         idx = 2;
2e9d52f27f 2007-10-02       drh:       }else{
2e9d52f27f 2007-10-02       drh:         blob_appendf(&err, "unknown template type: %b", &type);
2e9d52f27f 2007-10-02       drh:         goto bad_config_file;
2e9d52f27f 2007-10-02       drh:       }
2e9d52f27f 2007-10-02       drh:       if( (seen_template & (1<<idx))!=0 ){
2e9d52f27f 2007-10-02       drh:         blob_appendf(&err, "more than one %b template", &type);
2e9d52f27f 2007-10-02       drh:         goto bad_config_file;
2e9d52f27f 2007-10-02       drh:       }
2e9d52f27f 2007-10-02       drh:       seen_template |= 1<<idx;
2e9d52f27f 2007-10-02       drh:       start = end = blob_tell(pConfig);
2e9d52f27f 2007-10-02       drh:       while( blob_line(pConfig, &line) ){
2e9d52f27f 2007-10-02       drh:          blob_token(&line, &token);
2e9d52f27f 2007-10-02       drh:          if( blob_compare(&token, &arg)==0 ) break;
2e9d52f27f 2007-10-02       drh:          end = blob_tell(pConfig);
2e9d52f27f 2007-10-02       drh:       }
2e9d52f27f 2007-10-02       drh:       blob_init(&content, &blob_buffer(pConfig)[start], end - start);
2e9d52f27f 2007-10-02       drh:       blob_appendf(&sql,
2e9d52f27f 2007-10-02       drh:         "REPLACE INTO config(name, value) VALUES('tkt-%b-template',%B);\n",
2e9d52f27f 2007-10-02       drh:         &type, &content
2e9d52f27f 2007-10-02       drh:       );
2e9d52f27f 2007-10-02       drh:       blob_reset(&content);
0edee97370 2007-10-03       drh:     }else
0edee97370 2007-10-03       drh: 
0edee97370 2007-10-03       drh:     /*
0edee97370 2007-10-03       drh:     **  description <delimiter>
0edee97370 2007-10-03       drh:     **  <text>
0edee97370 2007-10-03       drh:     */
0edee97370 2007-10-03       drh:     if( blob_eq(&token, "description")
0edee97370 2007-10-03       drh:      && blob_token(&line, &arg)
0edee97370 2007-10-03       drh:     ){
0edee97370 2007-10-03       drh:       int idx;
0edee97370 2007-10-03       drh:       Blob content;
0edee97370 2007-10-03       drh:       int start;
0edee97370 2007-10-03       drh:       int end;
0edee97370 2007-10-03       drh: 
0edee97370 2007-10-03       drh:       start = end = blob_tell(pConfig);
0edee97370 2007-10-03       drh:       while( blob_line(pConfig, &line) ){
0edee97370 2007-10-03       drh:          blob_token(&line, &token);
0edee97370 2007-10-03       drh:          if( blob_compare(&token, &arg)==0 ) break;
0edee97370 2007-10-03       drh:          end = blob_tell(pConfig);
0edee97370 2007-10-03       drh:       }
0edee97370 2007-10-03       drh:       blob_init(&content, &blob_buffer(pConfig)[start], end - start);
0edee97370 2007-10-03       drh:       blob_appendf(&sql,
0edee97370 2007-10-03       drh:         "REPLACE INTO config(name, value) VALUES('tkt-desc',%B);\n",
0edee97370 2007-10-03       drh:          &content
0edee97370 2007-10-03       drh:       );
0edee97370 2007-10-03       drh:       blob_reset(&content);
0edee97370 2007-10-03       drh:     }else
0edee97370 2007-10-03       drh: 
0edee97370 2007-10-03       drh:     {
2e9d52f27f 2007-10-02       drh:       blob_appendf(&err, "unknown command: %b", &token);
2e9d52f27f 2007-10-02       drh:       goto bad_config_file;
2e9d52f27f 2007-10-02       drh:     }
2e9d52f27f 2007-10-02       drh:   }
2e9d52f27f 2007-10-02       drh:   if( seen_template != 0x7 ){
2e9d52f27f 2007-10-02       drh:     blob_appendf(&err, "missing templates");
2e9d52f27f 2007-10-02       drh:     goto bad_config_file;
2e9d52f27f 2007-10-02       drh:   }
2e9d52f27f 2007-10-02       drh: 
2e9d52f27f 2007-10-02       drh:   /* If we reach this point it means the parse was successful
2e9d52f27f 2007-10-02       drh:   */
2e9d52f27f 2007-10-02       drh:   rc = 0;
2e9d52f27f 2007-10-02       drh:   blob_appendf(&tbldef, "\n);\n");
2e9d52f27f 2007-10-02       drh:   if( testFlag ){
2e9d52f27f 2007-10-02       drh:     blob_write_to_file(&tbldef, "-");
2e9d52f27f 2007-10-02       drh:     blob_write_to_file(&sql, "-");
2e9d52f27f 2007-10-02       drh:   }else{
2e9d52f27f 2007-10-02       drh:     db_multi_exec("%b", &tbldef);
2e9d52f27f 2007-10-02       drh:     db_multi_exec("%b", &sql);
2e9d52f27f 2007-10-02       drh:   }
2e9d52f27f 2007-10-02       drh: 
2e9d52f27f 2007-10-02       drh: bad_config_file:
2e9d52f27f 2007-10-02       drh:   if( rc && pErr ){
2e9d52f27f 2007-10-02       drh:     blob_appendf(pErr, "line %d: %b", lineno, &err);
2e9d52f27f 2007-10-02       drh:   }
2e9d52f27f 2007-10-02       drh:   blob_reset(&token);
2e9d52f27f 2007-10-02       drh:   blob_reset(&line);
2e9d52f27f 2007-10-02       drh:   blob_reset(&name);
2e9d52f27f 2007-10-02       drh:   blob_reset(&type);
2e9d52f27f 2007-10-02       drh:   blob_reset(&arg);
2e9d52f27f 2007-10-02       drh:   blob_reset(&sql);
2e9d52f27f 2007-10-02       drh:   blob_reset(&tbldef);
2e9d52f27f 2007-10-02       drh:   blob_reset(&err);
2e9d52f27f 2007-10-02       drh:   return rc;
2e9d52f27f 2007-10-02       drh: }
2e9d52f27f 2007-10-02       drh: 
2e9d52f27f 2007-10-02       drh: /*
2e9d52f27f 2007-10-02       drh: ** COMMAND: test-tktconfig-parse
2e9d52f27f 2007-10-02       drh: */
2e9d52f27f 2007-10-02       drh: void test_tktconfig_cmd(void){
2e9d52f27f 2007-10-02       drh:   Blob config, err;
2e9d52f27f 2007-10-02       drh:   if( g.argc!=3 ){
2e9d52f27f 2007-10-02       drh:     usage("FILENAME");
2e9d52f27f 2007-10-02       drh:   }
2e9d52f27f 2007-10-02       drh:   blob_read_from_file(&config, g.argv[2]);
2e9d52f27f 2007-10-02       drh:   blob_zero(&err);
2e9d52f27f 2007-10-02       drh:   ticket_config_parse(&config, 1, &err);
2e9d52f27f 2007-10-02       drh:   if( blob_size(&err) ){
2e9d52f27f 2007-10-02       drh:     blob_write_to_file(&err, "-");
2e9d52f27f 2007-10-02       drh:   }
0edee97370 2007-10-03       drh: }
0edee97370 2007-10-03       drh: 
0edee97370 2007-10-03       drh: /*
0edee97370 2007-10-03       drh: ** Load the default ticket configuration.
0edee97370 2007-10-03       drh: */
0edee97370 2007-10-03       drh: void ticket_load_default_config(void){
0edee97370 2007-10-03       drh:   static const char zDefaultConfig[] =
0edee97370 2007-10-03       drh:     @ ticket-configuration
0edee97370 2007-10-03       drh:     @ description END-OF-DESCRIPTION
0edee97370 2007-10-03       drh:     @ Default Ticket Configuration
0edee97370 2007-10-03       drh:     @ The default ticket configuration for new projects
0edee97370 2007-10-03       drh:     @ END-OF-DESCRIPTION
0edee97370 2007-10-03       drh:     @ #####################################################################
0edee97370 2007-10-03       drh:     @ field title text 60 1
0edee97370 2007-10-03       drh:     @ field comment ctext 80 20
0edee97370 2007-10-03       drh:     @ field assignedto text 20 1
0edee97370 2007-10-03       drh:     @ field subsystem text 20 1
0edee97370 2007-10-03       drh:     @ field type enum 12 Code Build_Problem Documentation Feature_Request Incident
0edee97370 2007-10-03       drh:     @ field priority enum 10 High Medium Low
0edee97370 2007-10-03       drh:     @ field severity enum 10 Critical Severe Important Minor Cosmetic
0edee97370 2007-10-03       drh:     @ field sesolution enum 20 Open Fixed Rejected Unable_To_Reproduce Works_As_Designed External_Bug Not_A_Bug Duplicate Overcome_By_Events Drive_By_Patch
0edee97370 2007-10-03       drh:     @ field status enum 10 Open Verified In_Process Deferred Fixed Tested Closed
0edee97370 2007-10-03       drh:     @ field contact private 50 1
0edee97370 2007-10-03       drh:     @ field foundin text 30 1
0edee97370 2007-10-03       drh:     @ field assocvers baseline 50
0edee97370 2007-10-03       drh:     @ field presentin uuid 50
0edee97370 2007-10-03       drh:     @ field fixedin uuid 50
0edee97370 2007-10-03       drh:     @ field dueby date 20
0edee97370 2007-10-03       drh:     @ field deferuntil date 20
0edee97370 2007-10-03       drh:     @ ######################################################################
0edee97370 2007-10-03       drh:     @ template new END-OF-NEW-TEMPLATE
0edee97370 2007-10-03       drh:     @ <table cellpadding="5">
0edee97370 2007-10-03       drh:     @ <tr>
0edee97370 2007-10-03       drh:     @ <td cellpadding="2">
0edee97370 2007-10-03       drh:     @ Enter a one-line summary of the problem:<br>
0edee97370 2007-10-03       drh:     @ [entrywidget title]
0edee97370 2007-10-03       drh:     @ </td>
0edee97370 2007-10-03       drh:     @ </tr>
0edee97370 2007-10-03       drh:     @
0edee97370 2007-10-03       drh:     @ <tr>
0edee97370 2007-10-03       drh:     @ <td align="right">Type:
0edee97370 2007-10-03       drh:     @ [entrywidget type]
0edee97370 2007-10-03       drh:     @ </td>
0edee97370 2007-10-03       drh:     @ <td>What type of ticket is this?</td>
0edee97370 2007-10-03       drh:     @ </tr>
0edee97370 2007-10-03       drh:     @
0edee97370 2007-10-03       drh:     @ <tr>
0edee97370 2007-10-03       drh:     @ <td align="right">Version:
0edee97370 2007-10-03       drh:     @ [entrywidget foundin]
0edee97370 2007-10-03       drh:     @ </td>
0edee97370 2007-10-03       drh:     @ <td>In what version or build number do you observer the problem?</td>
0edee97370 2007-10-03       drh:     @ </tr>
0edee97370 2007-10-03       drh:     @
0edee97370 2007-10-03       drh:     @ <tr>
0edee97370 2007-10-03       drh:     @ <td align="right">Severity:
0edee97370 2007-10-03       drh:     @ [entrywidget severity]
0edee97370 2007-10-03       drh:     @ </td>
0edee97370 2007-10-03       drh:     @ <td>How debilitating is the problem?  How badly does the problem
0edee97370 2007-10-03       drh:     @ effect the operation of the product?</td>
0edee97370 2007-10-03       drh:     @ </tr>
0edee97370 2007-10-03       drh:     @
0edee97370 2007-10-03       drh:     @ <tr>
0edee97370 2007-10-03       drh:     @ <td colspan="2">
0edee97370 2007-10-03       drh:     @ Enter a detailed description of the problem.
0edee97370 2007-10-03       drh:     @ For code defects, be sure to provide details on exactly how
0edee97370 2007-10-03       drh:     @ the problem can be reproduced.  Provide as much detail as
0edee97370 2007-10-03       drh:     @ possible.
0edee97370 2007-10-03       drh:     @ <br>
0edee97370 2007-10-03       drh:     @ [entrywidget comment noappend]
0edee97370 2007-10-03       drh:     @ [ifpreview comment]
0edee97370 2007-10-03       drh:     @ <hr>
0edee97370 2007-10-03       drh:     @ [viewwidget comment]
0edee97370 2007-10-03       drh:     @ </hr>
0edee97370 2007-10-03       drh:     @ </tr>
0edee97370 2007-10-03       drh:     @
0edee97370 2007-10-03       drh:     @ <tr>
0edee97370 2007-10-03       drh:     @ <td align="right">
0edee97370 2007-10-03       drh:     @ [submitbutton]
0edee97370 2007-10-03       drh:     @ </td>
0edee97370 2007-10-03       drh:     @ <td>After filling in the information above, press this button to create
0edee97370 2007-10-03       drh:     @ the new ticket</td>
0edee97370 2007-10-03       drh:     @ </tr>
0edee97370 2007-10-03       drh:     @ </table>
0edee97370 2007-10-03       drh:     @ [defaultvalue status Open]
0edee97370 2007-10-03       drh:     @ [defaultvalue resolution Open]
0edee97370 2007-10-03       drh:     @ END-OF-NEW-TEMPLATE
0edee97370 2007-10-03       drh:     @ ######################################################################
0edee97370 2007-10-03       drh:     @ template edit END-OF-EDIT-TEMPLATE
0edee97370 2007-10-03       drh:     @ <table cellpadding="5">
0edee97370 2007-10-03       drh:     @ <tr><td align="right">Title:</td><td>
0edee97370 2007-10-03       drh:     @ [entrywidget title]
0edee97370 2007-10-03       drh:     @ </td></tr>
0edee97370 2007-10-03       drh:     @ <tr><td align="right">Status:</td><td>
0edee97370 2007-10-03       drh:     @ [entrywidget status]
0edee97370 2007-10-03       drh:     @ </td></tr>
0edee97370 2007-10-03       drh:     @ <tr><td align="right">Type:</td><td>
0edee97370 2007-10-03       drh:     @ [entrywidget type]
0edee97370 2007-10-03       drh:     @ </td></tr>
0edee97370 2007-10-03       drh:     @ <tr><td align="right">Severity:</td><td>
0edee97370 2007-10-03       drh:     @ [entrywidget severity]
0edee97370 2007-10-03       drh:     @ </td></tr>
0edee97370 2007-10-03       drh:     @ <tr><td align="right">Priority:</td><td>
0edee97370 2007-10-03       drh:     @ [entrywidget priority]
0edee97370 2007-10-03       drh:     @ </td></tr>
0edee97370 2007-10-03       drh:     @ <tr><td align="right">Resolution:</td><td>
0edee97370 2007-10-03       drh:     @ [entrywidget resolution]
0edee97370 2007-10-03       drh:     @ </td></tr>
0edee97370 2007-10-03       drh:     @ <tr><td align="right">Subsystem:</td><td>
0edee97370 2007-10-03       drh:     @ [entrywidget subsystem]
0edee97370 2007-10-03       drh:     @ </td></tr>
0edee97370 2007-10-03       drh:     @ <tr><td align="right">Assigned&nbsp;To:</td><td>
0edee97370 2007-10-03       drh:     @ [entrywidget assignedto]
0edee97370 2007-10-03       drh:     @ </td></tr>
0edee97370 2007-10-03       drh:     @ <tr><td align="right">Contact:</td><td>
0edee97370 2007-10-03       drh:     @ [entrywidget contact]
0edee97370 2007-10-03       drh:     @ </td></tr>
0edee97370 2007-10-03       drh:     @ <tr><td align="right">Version&nbsp;Found&nbsp;In:</td><td>
0edee97370 2007-10-03       drh:     @ [entrywidget foundin]
0edee97370 2007-10-03       drh:     @ </td></tr>
0edee97370 2007-10-03       drh:     @ <tr><td colspan="2">
0edee97370 2007-10-03       drh:     @ [ifappend comment]
0edee97370 2007-10-03       drh:     @   New Remarks:<br>
0edee97370 2007-10-03       drh:     @   [appendwidget comment]
0edee97370 2007-10-03       drh:     @ [else]
0edee97370 2007-10-03       drh:     @   Description And Comments:<br>
0edee97370 2007-10-03       drh:     @   [entrywidget comment]
0edee97370 2007-10-03       drh:     @ [endif]
0edee97370 2007-10-03       drh:     @ </td></tr>
0edee97370 2007-10-03       drh:     @ <tr><td align="right"></td><td>
0edee97370 2007-10-03       drh:     @ [submitbutton]
0edee97370 2007-10-03       drh:     @ </td></tr>
0edee97370 2007-10-03       drh:     @ </table>
0edee97370 2007-10-03       drh:     @ END-OF-EDIT-TEMPLATE
0edee97370 2007-10-03       drh:     @ ######################################################################
0edee97370 2007-10-03       drh:     @ template view END-OF-VIEW-TEMPLATE
0edee97370 2007-10-03       drh:     @ <table cellpadding="5">
0edee97370 2007-10-03       drh:     @ <tr><td align="right">Title:</td><td>
0edee97370 2007-10-03       drh:     @ [viewwidget title]
0edee97370 2007-10-03       drh:     @ </td></tr>
0edee97370 2007-10-03       drh:     @ <tr><td align="right">Status:</td><td>
0edee97370 2007-10-03       drh:     @ [viewwidget status]
0edee97370 2007-10-03       drh:     @ </td></tr>
0edee97370 2007-10-03       drh:     @ <tr><td align="right">Type:</td><td>
0edee97370 2007-10-03       drh:     @ [viewwidget type]
0edee97370 2007-10-03       drh:     @ </td></tr>
0edee97370 2007-10-03       drh:     @ <tr><td align="right">Severity:</td><td>
0edee97370 2007-10-03       drh:     @ [viewwidget severity]
0edee97370 2007-10-03       drh:     @ </td></tr>
0edee97370 2007-10-03       drh:     @ <tr><td align="right">Priority:</td><td>
0edee97370 2007-10-03       drh:     @ [viewwidget priority]
0edee97370 2007-10-03       drh:     @ </td></tr>
0edee97370 2007-10-03       drh:     @ <tr><td align="right">Resolution:</td><td>
0edee97370 2007-10-03       drh:     @ [viewwidget resolution]
0edee97370 2007-10-03       drh:     @ </td></tr>
0edee97370 2007-10-03       drh:     @ <tr><td align="right">Subsystem:</td><td>
0edee97370 2007-10-03       drh:     @ [viewwidget subsystem]
0edee97370 2007-10-03       drh:     @ </td></tr>
0edee97370 2007-10-03       drh:     @ <tr><td align="right">Assigned&nbsp;To:</td><td>
0edee97370 2007-10-03       drh:     @ [viewwidget assignedto]
0edee97370 2007-10-03       drh:     @ </td></tr>
0edee97370 2007-10-03       drh:     @ <tr><td align="right">Contact:</td><td>
0edee97370 2007-10-03       drh:     @ [viewwidget contact]
0edee97370 2007-10-03       drh:     @ </td></tr>
0edee97370 2007-10-03       drh:     @ <tr><td align="right">Version&nbsp;Found&nbsp;In:</td><td>
0edee97370 2007-10-03       drh:     @ [viewwidget foundin]
0edee97370 2007-10-03       drh:     @ </td></tr>
0edee97370 2007-10-03       drh:     @ <tr><td colspan="2">
0edee97370 2007-10-03       drh:     @ Description And Comments:<br>
0edee97370 2007-10-03       drh:     @ [viewwidget comment]
0edee97370 2007-10-03       drh:     @ </td></tr>
0edee97370 2007-10-03       drh:     @ </table>
0edee97370 2007-10-03       drh:     @ END-OF-VIEW-TEMPLATE
0edee97370 2007-10-03       drh:   ;
0edee97370 2007-10-03       drh:   Blob config, errmsg;
0edee97370 2007-10-03       drh:   blob_init(&config, zDefaultConfig, sizeof(zDefaultConfig)-1);
0edee97370 2007-10-03       drh:   db_begin_transaction();
0edee97370 2007-10-03       drh:   blob_zero(&errmsg);
0edee97370 2007-10-03       drh:   ticket_config_parse(&config, 0, &errmsg);
0edee97370 2007-10-03       drh:   if( blob_size(&errmsg) ){
0edee97370 2007-10-03       drh:     fossil_fatal("%b", &errmsg);
0edee97370 2007-10-03       drh:   }
0edee97370 2007-10-03       drh:   db_end_transaction(0);
2e9d52f27f 2007-10-02       drh: }