use IsisDB module instead of OpenIsis -- this will fix various problems in
[webpac] / openisis / tcl / tspr.c
1 /*
2         openisis - an open implementation of the CDS/ISIS database
3         Version 0.8.x (patchlevel see file Version)
4         Copyright (C) 2001-2003 by Erik Grziwotz, erik@openisis.org
5
6         This library is free software; you can redistribute it and/or
7         modify it under the terms of the GNU Lesser General Public
8         License as published by the Free Software Foundation; either
9         version 2.1 of the License, or (at your option) any later version.
10
11         This library is distributed in the hope that it will be useful,
12         but WITHOUT ANY WARRANTY; without even the implied warranty of
13         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14         Lesser General Public License for more details.
15
16         You should have received a copy of the GNU Lesser General Public
17         License along with this library; if not, write to the Free Software
18         Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
20         see README for more information
21 EOH */
22
23 /*
24         $Id: tspr.c,v 1.7 2003/06/06 10:35:38 mawag Exp $
25         OpenIsis TSP runner
26         must be binary in order to use with #! lines
27 */
28
29
30 #include <stdlib.h> /* getenv */
31 #include <unistd.h> /* read/write */
32
33 #include "openisis.h"
34 #include "openisistcl.h"
35
36 #define CL_MAX 512*1024
37
38 static int opc;
39 static const char **opv;
40
41
42 static int urldec ( OpenIsisRec **preq, const char *q, int l )
43 {
44         OpenIsisRec *req = *preq;
45         const char *e = q + (0 <= l ? l : (l = strlen(q)));
46
47         while ( q < e && *q ) {
48                 char *v, *p;
49                 int tag, len;
50                 /* assume numeric tags */
51                 len = openIsisA2il( q, e-q, &tag );
52                 if ( !len && opc ) {
53                         int i = opc;
54                         while ( i-- ) {
55                                 int cmplen = strlen(opv[i]);
56                                 if ( cmplen > e-q-1 )
57                                         cmplen = e-q-1;
58                                 if ( !memcmp( opv[i], q, cmplen ) && '=' == q[cmplen] ) {
59                                         tag = i+1;
60                                         len = cmplen;
61                                         break;
62                                 }
63                         }
64                 }
65                 q += len;
66                 if ( '=' != *q || 0 >= tag ) {
67                         openIsisSMsg( OPENISIS_LOG_ERROR, "bad param %d '%.32s'", tag, q );
68                         return 1;
69                 }
70                 q++;
71                 OPENISIS_RADD( req, tag, 0, e-q, !0 );
72                 if ( ! req )
73                         return 3;
74                 p = v = (char*)req->field[req->len-1].val;
75                 for (;;p++,q++) {
76                         switch (*q) {
77                         case '+': *p = ' '; continue;
78                         default: *p = *q; continue;
79                         case '%': /* dehex 2 */
80                                 *p = 0;
81                                 q++;
82                                 if ( '0' <= *q && *q <= '9' )
83                                         *p += *q - '0';
84                                 else if ( 'A' <= *q && *q <= 'F' )
85                                         *p += *q - 'A' + 10;
86                                 else if ( 'a' <= *q && *q <= 'f' )
87                                         *p += *q - 'a' + 10;
88                                 else
89                                         return 2; /* carp bad hex */
90                                 *p <<= 4;
91                                 q++;
92                                 if ( '0' <= *q && *q <= '9' )
93                                         *p += *q - '0';
94                                 else if ( 'A' <= *q && *q <= 'F' )
95                                         *p += *q - 'A' + 10;
96                                 else if ( 'a' <= *q && *q <= 'f' )
97                                         *p += *q - 'a' + 10;
98                                 else
99                                         return 2;
100                                 continue;
101                         case '&':
102                                 q++;
103                         case 0:
104                                 break;
105                         }
106                         /* hit proper end */
107                         req->used += req->field[req->len-1].len = p - v;
108                         break;
109                 }
110         } /* while q */
111         *preq = req;
112         return 0;
113 }
114
115
116
117 #ifdef ORATCL
118 extern int Oratcl_Init ( Tcl_Interp *ip );
119 #endif
120 #ifdef PGTCL
121 extern int Pgtcl_Init ( Tcl_Interp *ip );
122 #endif
123
124
125 static int appinit ( Tcl_Interp *interp )
126 {
127         if ( TCL_OK != Tcl_Init( interp )
128                 /* done in new session
129                 || TCL_OK != OpenisisTcl_Init( interp )
130                 */
131 #ifdef ORATCL
132                 || TCL_OK != Oratcl_Init( interp )
133 #endif
134 #ifdef PGTCL
135                 || TCL_OK != Pgtcl_Init( interp )
136 #endif
137         )
138                 return TCL_ERROR;
139         return TCL_OK;
140 }
141
142 static char prelude[] = "Content-Type: text/html\r\n\r\n";
143 static char code[] = "package require openIsis 0.8\nopenIsis::Tspr $tsp";
144
145 int main ( int argc, const char **argv )
146 {
147         OpenIsisRec *req = 0;
148         int sid, rid, ret;
149         const char *q;
150         Tcl_Interp *interp;
151
152         if ( 2 > argc )
153                 return 42;
154         opc = argc-2;
155         opv = argv+1;
156         openIsisCOpen(0);
157
158         /* Tcl_Main( argc, argv, appinit ); */
159         Tcl_FindExecutable(argv[0]); /* adds ../lib to auto_path */
160         interp = Tcl_CreateInterp();
161         appinit( interp );
162         if ( (q = getenv("SCRIPT_NAME")) )
163                 OPENISIS_RADDS( req, -10, q, !0 );
164         if ( (q = getenv("PATH_INFO")) )
165                 OPENISIS_RADDS( req, -11, q, !0 );
166         if ( (q = getenv("REMOTE_USER")) )
167                 OPENISIS_RADDS( req, -12, q, !0 );
168         /* URL-decode env(QUERY_STRING) into request record */
169         if ( (q = getenv("QUERY_STRING")) && (ret = urldec( &req, q, -1 )) ) 
170                 return ret;
171         if ( (q = getenv("CONTENT_LENGTH")) && *q ) {
172                 char buf[CL_MAX+1];
173                 int l = openIsisA2i( q, -1 );
174                 if ( l > CL_MAX )
175                         return 4;
176                 if ( !(q = getenv("CONTENT_TYPE"))
177                         || strcmp("application/x-www-form-urlencoded", q)
178                 )
179                         return 5;
180                 if ( l != read( 0, buf, l ) )
181                         return 6;
182                 buf[l] = 0;
183                 if ( (ret = urldec( &req, buf, l )) )
184                         return ret;
185         }
186         sid = openIsisTclNewSession( interp );
187         rid = openIsisTclCreateRecCmd( sid, "request", 0, 0 );
188
189         Tcl_SetVar( interp, "tsp", (char*)argv[argc-1], 0 );
190         write( 1, prelude, sizeof(prelude)-1 );
191         if ( openIsisTclEval( sid, 1, &rid, &req, code ) ) {
192                 const char *errorInfo
193                         = Tcl_GetVar( interp, "errorInfo", TCL_GLOBAL_ONLY );
194                 openIsisSMsg( OPENISIS_LOG_ERROR, "error in tsp\n%s",
195                         errorInfo ? errorInfo : "-" );
196                 return 3;
197         }
198         return 0;
199 }