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