]> andersk Git - moira.git/blob - server/qvalidate.pc
Change SNET_STATUS_PRIVATE to SNET_STATUS_PRIVATE_10MBPS and
[moira.git] / server / qvalidate.pc
1 /* $Id$
2  *
3  * Argument validation routines
4  *
5  * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology
6  * For copying and distribution information, please see the file
7  * <mit-copyright.h>.
8  */
9
10 #include <mit-copyright.h>
11 #include "mr_server.h"
12 #include "query.h"
13 #include "qrtn.h"
14
15 #include <ctype.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <unistd.h>
19
20 EXEC SQL INCLUDE sqlca;
21 EXEC SQL INCLUDE sqlda;
22
23 RCSID("$Header$");
24
25 extern char *whoami, *table_name[], *sqlbuffer[QMAXARGS];
26 extern int dbms_errno, mr_errcode;
27
28 EXEC SQL BEGIN DECLARE SECTION;
29 extern char stmt_buf[];
30 EXEC SQL END DECLARE SECTION;
31
32 int validate_chars(char *argv[], struct valobj *vo);
33 int validate_id(struct query *, char *argv[], struct valobj *vo);
34 int validate_name(char *argv[], struct valobj *vo);
35 int validate_rename(char *argv[], struct valobj *vo);
36 int validate_type(char *argv[], struct valobj *vo);
37 int validate_typedata(struct query *, char *argv[], struct valobj *vo);
38 int validate_len(char *argv[], struct valobj *vo);
39 int validate_num(char *argv[], struct valobj *vo);
40
41 extern SQLDA *sqlald(int, int, int);
42 SQLDA *mr_alloc_sqlda(void);
43
44 EXEC SQL WHENEVER SQLERROR DO dbmserr();
45
46 /* Validation Routines */
47
48 int validate_row(struct query *q, char *argv[], struct validate *v)
49 {
50   EXEC SQL BEGIN DECLARE SECTION;
51   int rowcount;
52   EXEC SQL END DECLARE SECTION;
53   char *qual;
54
55   /* build where clause */
56   qual = build_qual(v->qual, v->argc, argv);
57
58   /* look for the record */
59   sprintf(stmt_buf, "SELECT COUNT (*) FROM %s WHERE %s",
60           table_name[q->rtable], qual);
61   dosql(sqlbuffer);
62   free(qual);
63   if (dbms_errno)
64     return mr_errcode;
65
66   rowcount = atoi(sqlbuffer[0]);
67   if (rowcount == 0)
68     return MR_NO_MATCH;
69   if (rowcount > 1)
70     return MR_NOT_UNIQUE;
71   return MR_EXISTS;
72 }
73
74 int validate_fields(struct query *q, char *argv[], struct valobj *vo, int n)
75 {
76   int status;
77
78   while (--n >= 0)
79     {
80       switch (vo->type)
81         {
82         case V_NAME:
83           status = validate_name(argv, vo);
84           break;
85
86         case V_ID:
87           status = validate_id(q, argv, vo);
88           break;
89
90         case V_TYPE:
91           status = validate_type(argv, vo);
92           break;
93
94         case V_TYPEDATA:
95           status = validate_typedata(q, argv, vo);
96           break;
97
98         case V_RENAME:
99           status = validate_rename(argv, vo);
100           break;
101
102         case V_CHAR:
103           status = validate_chars(argv, vo);
104           break;
105
106         case V_LEN:
107           status = validate_len(argv, vo);
108           break;
109
110         case V_NUM:
111           status = validate_num(argv, vo);
112           break;
113         }
114
115       if (status != MR_EXISTS)
116         return status;
117       vo++;
118     }
119
120   if (dbms_errno)
121     return mr_errcode;
122   return MR_SUCCESS;
123 }
124
125
126 /* validate_chars: verify that there are no illegal characters in
127  * the string.  Legal characters are printing chars other than
128  * ", *, ?, \, [ and ].
129  */
130 static int illegalchars[] = {
131   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
132   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
133   0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
134   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0 - ? */
135   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* : - O */
136   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, /* P - _ */
137   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
138   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
139   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
140   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
141   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
142   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
143   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
144   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
145   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
146   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
147 };
148
149 int validate_chars(char *argv[], struct valobj *vo)
150 {
151   char *s = argv[vo->index];
152   EXEC SQL BEGIN DECLARE SECTION;
153   int len;
154   char *tname, *cname;
155   EXEC SQL END DECLARE SECTION;
156
157   /* check for bad characters */
158   while (*s)
159     {
160       if (illegalchars[(int)*s++])
161         return MR_BAD_CHAR;
162     }
163
164   /* check for length */
165   tname = table_name[vo->table];
166   cname = vo->namefield;
167   EXEC SQL SELECT data_length INTO :len FROM user_tab_columns
168     WHERE table_name = UPPER(:tname) AND column_name = UPPER(:cname);
169
170   if ((strlen(argv[vo->index]) > len) &&
171       strcmp(argv[vo->index], UNIQUE_LOGIN)) /* kludge... sigh */
172     return MR_ARG_TOO_LONG;
173
174   return MR_EXISTS;
175 }
176
177
178 int validate_id(struct query *q, char *argv[], struct valobj *vo)
179 {
180   EXEC SQL BEGIN DECLARE SECTION;
181   char *name, *namefield, *idfield;
182   int id, rowcount, tbl;
183   EXEC SQL END DECLARE SECTION;
184   int status;
185   char *c;
186
187   name = argv[vo->index];
188   tbl = vo->table;
189   namefield = vo->namefield;
190   idfield = vo->idfield;
191
192   if (tbl == MACHINE_TABLE || tbl == SUBNET_TABLE)
193     {
194       for (c = name; *c; c++)
195         {
196           if (islower(*c))
197             *c = toupper(*c);
198         }
199     }
200   status = name_to_id(name, tbl, &id);
201   if (status == 0)
202     {
203       *(int *)argv[vo->index] = id;
204       return MR_EXISTS;
205     }
206   else if (status == MR_NO_MATCH && tbl == STRINGS_TABLE &&
207            (q->type == APPEND || q->type == UPDATE))
208     {
209       if (strlen(name) >= STRINGS_STRING_SIZE)
210         return MR_ARG_TOO_LONG;
211       id = add_string(name);
212       *(int *)argv[vo->index] = id;
213       return MR_EXISTS;
214     }
215   else if (status == MR_NO_MATCH || status == MR_NOT_UNIQUE)
216     return vo->error;
217   else
218     return status;
219 }
220
221 int validate_name(char *argv[], struct valobj *vo)
222 {
223   char *name, *namefield;
224   char *c;
225
226   name = argv[vo->index];
227   namefield = vo->namefield;
228   if (vo->table == SERVERS_TABLE && !strcmp(namefield, "name"))
229     {
230       for (c = name; *c; c++)
231         {
232           if (islower(*c))
233             *c = toupper(*c);
234         }
235     }
236   sprintf(stmt_buf, "SELECT DISTINCT COUNT(*) FROM %s WHERE %s.%s = '%s'",
237           table_name[vo->table], table_name[vo->table], namefield, name);
238   dosql(sqlbuffer);
239
240   if (dbms_errno)
241     return mr_errcode;
242   return (atoi(sqlbuffer[0]) == 1) ? MR_EXISTS : vo->error;
243 }
244
245 int validate_rename(char *argv[], struct valobj *vo)
246 {
247   EXEC SQL BEGIN DECLARE SECTION;
248   char *name, *namefield, *idfield;
249   int id;
250   EXEC SQL END DECLARE SECTION;
251   int status;
252   char *c;
253
254   status = validate_chars(argv, vo);
255   if (status != MR_EXISTS)
256     return status;
257   name = argv[vo->index];
258   /* minor kludge to upcasify machine names */
259   if (vo->table == MACHINE_TABLE)
260     {
261       for (c = name; *c; c++)
262         {
263           if (islower(*c))
264             *c = toupper(*c);
265         }
266     }
267   namefield = vo->namefield;
268   idfield = vo->idfield;
269   id = -1;
270   if (idfield == 0)
271     {
272       if (!strcmp(argv[vo->index], argv[vo->index - 1]))
273         return MR_EXISTS;
274       sprintf(stmt_buf, "SELECT %s FROM %s WHERE %s = '%s'",
275               namefield, table_name[vo->table], namefield, name);
276       dosql(sqlbuffer);
277
278       if (dbms_errno)
279         return mr_errcode;
280       if (sqlca.sqlcode == SQL_NO_MATCH)
281         return MR_EXISTS; /* how's _that_ for intuitive? */
282       else
283         return vo->error;
284     }
285   status = name_to_id(name, vo->table, &id);
286   if (status == MR_NO_MATCH || id == *(int *)argv[vo->index - 1])
287     return MR_EXISTS;
288   else
289     return vo->error;
290 }
291
292
293 int validate_type(char *argv[], struct valobj *vo)
294 {
295   EXEC SQL BEGIN DECLARE SECTION;
296   char *typename;
297   char *val;
298   int cnt;
299   EXEC SQL END DECLARE SECTION;
300   char *c;
301
302   typename = vo->namefield;
303   c = val = argv[vo->index];
304   while (*c)
305     {
306       if (illegalchars[(int)*c++])
307         return MR_BAD_CHAR;
308     }
309
310   /* uppercase type fields */
311   for (c = val; *c; c++)
312     {
313       if (islower(*c))
314         *c = toupper(*c);
315     }
316
317   EXEC SQL SELECT COUNT(trans) INTO :cnt FROM alias
318     WHERE name = :typename AND type = 'TYPE' AND trans = :val;
319   if (dbms_errno)
320     return mr_errcode;
321   return cnt ? MR_EXISTS : vo->error;
322 }
323
324 /* validate member or type-specific data field */
325
326 int validate_typedata(struct query *q, char *argv[], struct valobj *vo)
327 {
328   EXEC SQL BEGIN DECLARE SECTION;
329   char *name;
330   char *field_type;
331   char data_type[129];
332   int id;
333   EXEC SQL END DECLARE SECTION;
334   int status;
335   char *c;
336
337   /* get named object */
338   name = argv[vo->index];
339
340   /* get field type string (known to be at index-1) */
341   field_type = argv[vo->index - 1];
342
343   /* get corresponding data type associated with field type name */
344   EXEC SQL SELECT trans INTO :data_type FROM alias
345     WHERE name = :field_type AND type = 'TYPEDATA';
346   if (dbms_errno)
347     return mr_errcode;
348   if (sqlca.sqlerrd[2] != 1)
349     return MR_TYPE;
350
351   /* now retrieve the record id corresponding to the named object */
352   if (strchr(data_type, ' '))
353     *strchr(data_type, ' ') = '\0';
354   if (!strcmp(data_type, "user"))
355     {
356       /* USER */
357       if (strchr(name, '@'))
358         return MR_USER;
359       status = name_to_id(name, USERS_TABLE, &id);
360       if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE))
361         return MR_USER;
362       if (status)
363         return status;
364     }
365   else if (!strcmp(data_type, "list"))
366     {
367       /* LIST */
368       status = name_to_id(name, LIST_TABLE, &id);
369       if (status && status == MR_NOT_UNIQUE)
370         return MR_LIST;
371       if (status == MR_NO_MATCH)
372         {
373           /* if idfield is non-zero, then if argv[0] matches the string
374            * that we're trying to resolve, we should get the value of
375            * numvalues.[idfield] for the id.
376            */
377           if (vo->idfield && (*(int *)argv[0] == *(int *)argv[vo->index]))
378             {
379               set_next_object_id(q->validate->object_id, q->rtable, 0);
380               name = vo->idfield;
381               EXEC SQL SELECT value INTO :id FROM numvalues
382                 WHERE name = :name;
383               if (sqlca.sqlerrd[2] != 1)
384                 return MR_LIST;
385             }
386           else
387             return MR_LIST;
388         }
389       else if (status)
390         return status;
391     }
392   else if (!strcmp(data_type, "machine"))
393     {
394       /* MACHINE */
395       for (c = name; *c; c++)
396         {
397           if (islower(*c))
398             *c = toupper(*c);
399         }
400       status = name_to_id(name, MACHINE_TABLE, &id);
401       if (status && (status == MR_NO_MATCH || status == MR_NOT_UNIQUE))
402         return MR_MACHINE;
403       if (status)
404         return status;
405     }
406   else if (!strcmp(data_type, "string"))
407     {
408       /* STRING */
409       status = name_to_id(name, STRINGS_TABLE, &id);
410       if (status && status == MR_NOT_UNIQUE)
411         return MR_STRING;
412       if (status == MR_NO_MATCH)
413         {
414           if (q->type != APPEND && q->type != UPDATE)
415             return MR_STRING;
416           if (strlen(name) >= STRINGS_STRING_SIZE)
417             return MR_ARG_TOO_LONG;
418           id = add_string(name);
419         }
420       else if (status)
421         return status;
422     }
423   else if (!strcmp(data_type, "none") || !strcmp(data_type, "all"))
424     id = 0;
425   else
426     return MR_TYPE;
427
428   /* now set value in argv */
429   *(int *)argv[vo->index] = id;
430
431   return MR_EXISTS;
432 }
433
434
435 /* Make sure the data fits in the field */
436 int validate_len(char *argv[], struct valobj *vo)
437 {
438   EXEC SQL BEGIN DECLARE SECTION;
439   int len;
440   char *tname, *cname;
441   EXEC SQL END DECLARE SECTION;
442
443   tname = table_name[vo->table];
444   cname = vo->namefield;
445   EXEC SQL SELECT data_length INTO :len FROM user_tab_columns
446     WHERE table_name = UPPER(:tname) AND column_name = UPPER(:cname);
447
448   if ((strlen(argv[vo->index]) > len) &&
449       strcmp(argv[vo->index], UNIQUE_LOGIN)) /* kludge... sigh */
450     return MR_ARG_TOO_LONG;
451
452   return MR_EXISTS;
453 }
454
455 /* Make sure the data is numeric */
456 int validate_num(char *argv[], struct valobj *vo)
457 {
458   char *p = argv[vo->index];
459
460   if (!strcmp(p, UNIQUE_GID) || !strcmp(p, UNIQUE_UID))
461     {
462       strcpy(p, "-1");
463       return MR_EXISTS;
464     }
465
466   if (*p == '-')
467     p++;
468   if (!*p)
469     return MR_INTEGER;
470
471   for (; *p; p++)
472     {
473       if (*p < '0' || *p > '9')
474         return MR_INTEGER;
475     }
476
477   return MR_EXISTS;
478 }
479
480 /* Check the database at startup time. */
481
482 void sanity_check_database(void)
483 {
484   EXEC SQL BEGIN DECLARE SECTION;
485   int oid, id;
486   EXEC SQL END DECLARE SECTION;
487
488   /* Sometimes a crash can leave strings_id in numvalues in an
489      incorrect state. Check for that and fix it. */
490
491   EXEC SQL SELECT value INTO :oid FROM numvalues WHERE name = 'strings_id';
492
493   for (id = oid + 1; sqlca.sqlcode == 0; id++)
494     {
495       EXEC SQL SELECT string_id INTO :id FROM strings
496         WHERE string_id = :id;
497     }
498
499   if (id != oid + 1)
500     EXEC SQL UPDATE numvalues SET value = :id - 1 WHERE name = 'strings_id';
501 }
502
503
504 char *sqlbuffer[QMAXARGS];
505
506 /* Dynamic SQL support routines */
507 SQLDA *mr_alloc_sqlda(void)
508 {
509   SQLDA *it;
510   int j;
511
512   it = sqlald(QMAXARGS, ARGLEN, 0);
513   if (!it)
514     {
515       com_err(whoami, MR_NO_MEM, "setting up SQLDA");
516       exit(1);
517     }
518
519   for (j = 0; j < QMAXARGS; j++)
520     {
521       it->V[j] = sqlbuffer[j] = xmalloc(ARGLEN);
522       it->T[j] = 97; /* 97 = CHARZ = null-terminated string */
523       it->L[j] = ARGLEN;
524     }
525
526   return it;
527 }
528
529 /*  Adds a string to the string table.  Returns the id number.
530  *
531  */
532 int add_string(char *nm)
533 {
534   EXEC SQL BEGIN DECLARE SECTION;
535   char *name = nm;
536   int id;
537   EXEC SQL END DECLARE SECTION;
538
539   EXEC SQL SELECT value INTO :id FROM numvalues WHERE name = 'strings_id';
540   id++;
541   EXEC SQL UPDATE numvalues SET value = :id WHERE name = 'strings_id';
542
543   EXEC SQL INSERT INTO strings (string_id, string) VALUES (:id, :name);
544
545   return id;
546 }
This page took 0.419762 seconds and 5 git commands to generate.