00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "postgres_fe.h"
00016
00017 #include <ctype.h>
00018
00019 #include "dumputils.h"
00020
00021 #include "parser/keywords.h"
00022
00023
00024
00025 extern const ScanKeyword FEScanKeywords[];
00026 extern const int NumFEScanKeywords;
00027
00028 #define supports_grant_options(version) ((version) >= 70400)
00029
00030 static bool parseAclItem(const char *item, const char *type,
00031 const char *name, const char *subname, int remoteVersion,
00032 PQExpBuffer grantee, PQExpBuffer grantor,
00033 PQExpBuffer privs, PQExpBuffer privswgo);
00034 static char *copyAclUserName(PQExpBuffer output, char *input);
00035 static void AddAcl(PQExpBuffer aclbuf, const char *keyword,
00036 const char *subname);
00037 static PQExpBuffer defaultGetLocalPQExpBuffer(void);
00038
00039
00040 int quote_all_identifiers = 0;
00041 PQExpBuffer (*getLocalPQExpBuffer) (void) = defaultGetLocalPQExpBuffer;
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 static PQExpBuffer
00052 defaultGetLocalPQExpBuffer(void)
00053 {
00054 static PQExpBuffer id_return = NULL;
00055
00056 if (id_return)
00057 {
00058
00059 resetPQExpBuffer(id_return);
00060 }
00061 else
00062 {
00063
00064 id_return = createPQExpBuffer();
00065 }
00066
00067 return id_return;
00068 }
00069
00070
00071
00072
00073
00074
00075
00076 const char *
00077 fmtId(const char *rawid)
00078 {
00079 PQExpBuffer id_return = getLocalPQExpBuffer();
00080
00081 const char *cp;
00082 bool need_quotes = false;
00083
00084
00085
00086
00087
00088 if (quote_all_identifiers)
00089 need_quotes = true;
00090
00091 else if (!((rawid[0] >= 'a' && rawid[0] <= 'z') || rawid[0] == '_'))
00092 need_quotes = true;
00093 else
00094 {
00095
00096 for (cp = rawid; *cp; cp++)
00097 {
00098 if (!((*cp >= 'a' && *cp <= 'z')
00099 || (*cp >= '0' && *cp <= '9')
00100 || (*cp == '_')))
00101 {
00102 need_quotes = true;
00103 break;
00104 }
00105 }
00106 }
00107
00108 if (!need_quotes)
00109 {
00110
00111
00112
00113
00114
00115
00116
00117
00118 const ScanKeyword *keyword = ScanKeywordLookup(rawid,
00119 FEScanKeywords,
00120 NumFEScanKeywords);
00121
00122 if (keyword != NULL && keyword->category != UNRESERVED_KEYWORD)
00123 need_quotes = true;
00124 }
00125
00126 if (!need_quotes)
00127 {
00128
00129 appendPQExpBufferStr(id_return, rawid);
00130 }
00131 else
00132 {
00133 appendPQExpBufferChar(id_return, '\"');
00134 for (cp = rawid; *cp; cp++)
00135 {
00136
00137
00138
00139
00140
00141 if (*cp == '\"')
00142 appendPQExpBufferChar(id_return, '\"');
00143 appendPQExpBufferChar(id_return, *cp);
00144 }
00145 appendPQExpBufferChar(id_return, '\"');
00146 }
00147
00148 return id_return->data;
00149 }
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160 const char *
00161 fmtQualifiedId(int remoteVersion, const char *schema, const char *id)
00162 {
00163 PQExpBuffer id_return;
00164 PQExpBuffer lcl_pqexp = createPQExpBuffer();
00165
00166
00167 if (remoteVersion >= 70300 && schema && *schema)
00168 {
00169 appendPQExpBuffer(lcl_pqexp, "%s.", fmtId(schema));
00170 }
00171 appendPQExpBuffer(lcl_pqexp, "%s", fmtId(id));
00172
00173 id_return = getLocalPQExpBuffer();
00174
00175 appendPQExpBuffer(id_return, "%s", lcl_pqexp->data);
00176 destroyPQExpBuffer(lcl_pqexp);
00177
00178 return id_return->data;
00179 }
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191 void
00192 appendStringLiteral(PQExpBuffer buf, const char *str,
00193 int encoding, bool std_strings)
00194 {
00195 size_t length = strlen(str);
00196 const char *source = str;
00197 char *target;
00198
00199 if (!enlargePQExpBuffer(buf, 2 * length + 2))
00200 return;
00201
00202 target = buf->data + buf->len;
00203 *target++ = '\'';
00204
00205 while (*source != '\0')
00206 {
00207 char c = *source;
00208 int len;
00209 int i;
00210
00211
00212 if (!IS_HIGHBIT_SET(c))
00213 {
00214
00215 if (SQL_STR_DOUBLE(c, !std_strings))
00216 *target++ = c;
00217
00218 *target++ = c;
00219 source++;
00220 continue;
00221 }
00222
00223
00224 len = PQmblen(source, encoding);
00225
00226
00227 for (i = 0; i < len; i++)
00228 {
00229 if (*source == '\0')
00230 break;
00231 *target++ = *source++;
00232 }
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242 if (i < len)
00243 {
00244 char *stop = buf->data + buf->maxlen - 2;
00245
00246 for (; i < len; i++)
00247 {
00248 if (target >= stop)
00249 break;
00250 *target++ = ' ';
00251 }
00252 break;
00253 }
00254 }
00255
00256
00257 *target++ = '\'';
00258 *target = '\0';
00259
00260 buf->len = target - buf->data;
00261 }
00262
00263
00264
00265
00266
00267
00268
00269 void
00270 appendStringLiteralConn(PQExpBuffer buf, const char *str, PGconn *conn)
00271 {
00272 size_t length = strlen(str);
00273
00274
00275
00276
00277
00278 if (strchr(str, '\\') != NULL && PQserverVersion(conn) >= 80100)
00279 {
00280
00281 if (buf->len > 0 && buf->data[buf->len - 1] != ' ')
00282 appendPQExpBufferChar(buf, ' ');
00283 appendPQExpBufferChar(buf, ESCAPE_STRING_SYNTAX);
00284 appendStringLiteral(buf, str, PQclientEncoding(conn), false);
00285 return;
00286 }
00287
00288
00289 if (!enlargePQExpBuffer(buf, 2 * length + 2))
00290 return;
00291 appendPQExpBufferChar(buf, '\'');
00292 buf->len += PQescapeStringConn(conn, buf->data + buf->len,
00293 str, length, NULL);
00294 appendPQExpBufferChar(buf, '\'');
00295 }
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307 void
00308 appendStringLiteralDQ(PQExpBuffer buf, const char *str, const char *dqprefix)
00309 {
00310 static const char suffixes[] = "_XXXXXXX";
00311 int nextchar = 0;
00312 PQExpBuffer delimBuf = createPQExpBuffer();
00313
00314
00315 appendPQExpBufferChar(delimBuf, '$');
00316 if (dqprefix)
00317 appendPQExpBufferStr(delimBuf, dqprefix);
00318
00319
00320
00321
00322
00323
00324 while (strstr(str, delimBuf->data) != NULL)
00325 {
00326 appendPQExpBufferChar(delimBuf, suffixes[nextchar++]);
00327 nextchar %= sizeof(suffixes) - 1;
00328 }
00329
00330
00331 appendPQExpBufferChar(delimBuf, '$');
00332
00333
00334 appendPQExpBufferStr(buf, delimBuf->data);
00335 appendPQExpBufferStr(buf, str);
00336 appendPQExpBufferStr(buf, delimBuf->data);
00337
00338 destroyPQExpBuffer(delimBuf);
00339 }
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350 void
00351 appendByteaLiteral(PQExpBuffer buf, const unsigned char *str, size_t length,
00352 bool std_strings)
00353 {
00354 const unsigned char *source = str;
00355 char *target;
00356
00357 static const char hextbl[] = "0123456789abcdef";
00358
00359
00360
00361
00362
00363
00364
00365 if (!enlargePQExpBuffer(buf, 2 * length + 5))
00366 return;
00367
00368 target = buf->data + buf->len;
00369 *target++ = '\'';
00370 if (!std_strings)
00371 *target++ = '\\';
00372 *target++ = '\\';
00373 *target++ = 'x';
00374
00375 while (length-- > 0)
00376 {
00377 unsigned char c = *source++;
00378
00379 *target++ = hextbl[(c >> 4) & 0xF];
00380 *target++ = hextbl[c & 0xF];
00381 }
00382
00383
00384 *target++ = '\'';
00385 *target = '\0';
00386
00387 buf->len = target - buf->data;
00388 }
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401 bool
00402 parsePGArray(const char *atext, char ***itemarray, int *nitems)
00403 {
00404 int inputlen;
00405 char **items;
00406 char *strings;
00407 int curitem;
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419 *itemarray = NULL;
00420 *nitems = 0;
00421 inputlen = strlen(atext);
00422 if (inputlen < 2 || atext[0] != '{' || atext[inputlen - 1] != '}')
00423 return false;
00424 items = (char **) malloc(inputlen * (sizeof(char *) + sizeof(char)));
00425 if (items == NULL)
00426 return false;
00427 *itemarray = items;
00428 strings = (char *) (items + inputlen);
00429
00430 atext++;
00431 curitem = 0;
00432 while (*atext != '}')
00433 {
00434 if (*atext == '\0')
00435 return false;
00436 items[curitem] = strings;
00437 while (*atext != '}' && *atext != ',')
00438 {
00439 if (*atext == '\0')
00440 return false;
00441 if (*atext != '"')
00442 *strings++ = *atext++;
00443 else
00444 {
00445
00446 atext++;
00447 while (*atext != '"')
00448 {
00449 if (*atext == '\0')
00450 return false;
00451 if (*atext == '\\')
00452 {
00453 atext++;
00454 if (*atext == '\0')
00455 return false;
00456 }
00457 *strings++ = *atext++;
00458 }
00459 atext++;
00460 }
00461 }
00462 *strings++ = '\0';
00463 if (*atext == ',')
00464 atext++;
00465 curitem++;
00466 }
00467 if (atext[1] != '\0')
00468 return false;
00469 *nitems = curitem;
00470 return true;
00471 }
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497 bool
00498 buildACLCommands(const char *name, const char *subname,
00499 const char *type, const char *acls, const char *owner,
00500 const char *prefix, int remoteVersion,
00501 PQExpBuffer sql)
00502 {
00503 char **aclitems;
00504 int naclitems;
00505 int i;
00506 PQExpBuffer grantee,
00507 grantor,
00508 privs,
00509 privswgo;
00510 PQExpBuffer firstsql,
00511 secondsql;
00512 bool found_owner_privs = false;
00513
00514 if (strlen(acls) == 0)
00515 return true;
00516
00517
00518 if (owner && *owner == '\0')
00519 owner = NULL;
00520
00521 if (!parsePGArray(acls, &aclitems, &naclitems))
00522 {
00523 if (aclitems)
00524 free(aclitems);
00525 return false;
00526 }
00527
00528 grantee = createPQExpBuffer();
00529 grantor = createPQExpBuffer();
00530 privs = createPQExpBuffer();
00531 privswgo = createPQExpBuffer();
00532
00533
00534
00535
00536
00537
00538
00539
00540 firstsql = createPQExpBuffer();
00541 secondsql = createPQExpBuffer();
00542
00543
00544
00545
00546
00547
00548 appendPQExpBuffer(firstsql, "%sREVOKE ALL", prefix);
00549 if (subname)
00550 appendPQExpBuffer(firstsql, "(%s)", subname);
00551 appendPQExpBuffer(firstsql, " ON %s %s FROM PUBLIC;\n", type, name);
00552
00553
00554
00555
00556
00557
00558
00559
00560 if (remoteVersion < 80200 && strcmp(type, "DATABASE") == 0)
00561 {
00562
00563 appendPQExpBuffer(firstsql, "%sGRANT CONNECT ON %s %s TO PUBLIC;\n",
00564 prefix, type, name);
00565 }
00566
00567
00568 for (i = 0; i < naclitems; i++)
00569 {
00570 if (!parseAclItem(aclitems[i], type, name, subname, remoteVersion,
00571 grantee, grantor, privs, privswgo))
00572 {
00573 free(aclitems);
00574 return false;
00575 }
00576
00577 if (grantor->len == 0 && owner)
00578 printfPQExpBuffer(grantor, "%s", owner);
00579
00580 if (privs->len > 0 || privswgo->len > 0)
00581 {
00582 if (owner
00583 && strcmp(grantee->data, owner) == 0
00584 && strcmp(grantor->data, owner) == 0)
00585 {
00586 found_owner_privs = true;
00587
00588
00589
00590
00591
00592 if (supports_grant_options(remoteVersion)
00593 ? strcmp(privswgo->data, "ALL") != 0
00594 : strcmp(privs->data, "ALL") != 0)
00595 {
00596 appendPQExpBuffer(firstsql, "%sREVOKE ALL", prefix);
00597 if (subname)
00598 appendPQExpBuffer(firstsql, "(%s)", subname);
00599 appendPQExpBuffer(firstsql, " ON %s %s FROM %s;\n",
00600 type, name, fmtId(grantee->data));
00601 if (privs->len > 0)
00602 appendPQExpBuffer(firstsql,
00603 "%sGRANT %s ON %s %s TO %s;\n",
00604 prefix, privs->data, type, name,
00605 fmtId(grantee->data));
00606 if (privswgo->len > 0)
00607 appendPQExpBuffer(firstsql,
00608 "%sGRANT %s ON %s %s TO %s WITH GRANT OPTION;\n",
00609 prefix, privswgo->data, type, name,
00610 fmtId(grantee->data));
00611 }
00612 }
00613 else
00614 {
00615
00616
00617
00618 if (grantor->len > 0
00619 && (!owner || strcmp(owner, grantor->data) != 0))
00620 appendPQExpBuffer(secondsql, "SET SESSION AUTHORIZATION %s;\n",
00621 fmtId(grantor->data));
00622
00623 if (privs->len > 0)
00624 {
00625 appendPQExpBuffer(secondsql, "%sGRANT %s ON %s %s TO ",
00626 prefix, privs->data, type, name);
00627 if (grantee->len == 0)
00628 appendPQExpBuffer(secondsql, "PUBLIC;\n");
00629 else if (strncmp(grantee->data, "group ",
00630 strlen("group ")) == 0)
00631 appendPQExpBuffer(secondsql, "GROUP %s;\n",
00632 fmtId(grantee->data + strlen("group ")));
00633 else
00634 appendPQExpBuffer(secondsql, "%s;\n", fmtId(grantee->data));
00635 }
00636 if (privswgo->len > 0)
00637 {
00638 appendPQExpBuffer(secondsql, "%sGRANT %s ON %s %s TO ",
00639 prefix, privswgo->data, type, name);
00640 if (grantee->len == 0)
00641 appendPQExpBuffer(secondsql, "PUBLIC");
00642 else if (strncmp(grantee->data, "group ",
00643 strlen("group ")) == 0)
00644 appendPQExpBuffer(secondsql, "GROUP %s",
00645 fmtId(grantee->data + strlen("group ")));
00646 else
00647 appendPQExpBuffer(secondsql, "%s", fmtId(grantee->data));
00648 appendPQExpBuffer(secondsql, " WITH GRANT OPTION;\n");
00649 }
00650
00651 if (grantor->len > 0
00652 && (!owner || strcmp(owner, grantor->data) != 0))
00653 appendPQExpBuffer(secondsql, "RESET SESSION AUTHORIZATION;\n");
00654 }
00655 }
00656 }
00657
00658
00659
00660
00661 if (!found_owner_privs && owner)
00662 {
00663 appendPQExpBuffer(firstsql, "%sREVOKE ALL", prefix);
00664 if (subname)
00665 appendPQExpBuffer(firstsql, "(%s)", subname);
00666 appendPQExpBuffer(firstsql, " ON %s %s FROM %s;\n",
00667 type, name, fmtId(owner));
00668 }
00669
00670 destroyPQExpBuffer(grantee);
00671 destroyPQExpBuffer(grantor);
00672 destroyPQExpBuffer(privs);
00673 destroyPQExpBuffer(privswgo);
00674
00675 appendPQExpBuffer(sql, "%s%s", firstsql->data, secondsql->data);
00676 destroyPQExpBuffer(firstsql);
00677 destroyPQExpBuffer(secondsql);
00678
00679 free(aclitems);
00680
00681 return true;
00682 }
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696 bool
00697 buildDefaultACLCommands(const char *type, const char *nspname,
00698 const char *acls, const char *owner,
00699 int remoteVersion,
00700 PQExpBuffer sql)
00701 {
00702 bool result;
00703 PQExpBuffer prefix;
00704
00705 prefix = createPQExpBuffer();
00706
00707
00708
00709
00710
00711
00712
00713 appendPQExpBuffer(prefix, "ALTER DEFAULT PRIVILEGES FOR ROLE %s ",
00714 fmtId(owner));
00715 if (nspname)
00716 appendPQExpBuffer(prefix, "IN SCHEMA %s ", fmtId(nspname));
00717
00718 result = buildACLCommands("", NULL,
00719 type, acls, owner,
00720 prefix->data, remoteVersion,
00721 sql);
00722
00723 destroyPQExpBuffer(prefix);
00724
00725 return result;
00726 }
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744 static bool
00745 parseAclItem(const char *item, const char *type,
00746 const char *name, const char *subname, int remoteVersion,
00747 PQExpBuffer grantee, PQExpBuffer grantor,
00748 PQExpBuffer privs, PQExpBuffer privswgo)
00749 {
00750 char *buf;
00751 bool all_with_go = true;
00752 bool all_without_go = true;
00753 char *eqpos;
00754 char *slpos;
00755 char *pos;
00756
00757 buf = strdup(item);
00758 if (!buf)
00759 return false;
00760
00761
00762 eqpos = copyAclUserName(grantee, buf);
00763 if (*eqpos != '=')
00764 {
00765 free(buf);
00766 return false;
00767 }
00768
00769
00770 slpos = strchr(eqpos + 1, '/');
00771 if (slpos)
00772 {
00773 *slpos++ = '\0';
00774 slpos = copyAclUserName(grantor, slpos);
00775 if (*slpos != '\0')
00776 {
00777 free(buf);
00778 return false;
00779 }
00780 }
00781 else
00782 resetPQExpBuffer(grantor);
00783
00784
00785 #define CONVERT_PRIV(code, keywd) \
00786 do { \
00787 if ((pos = strchr(eqpos + 1, code))) \
00788 { \
00789 if (*(pos + 1) == '*') \
00790 { \
00791 AddAcl(privswgo, keywd, subname); \
00792 all_without_go = false; \
00793 } \
00794 else \
00795 { \
00796 AddAcl(privs, keywd, subname); \
00797 all_with_go = false; \
00798 } \
00799 } \
00800 else \
00801 all_with_go = all_without_go = false; \
00802 } while (0)
00803
00804 resetPQExpBuffer(privs);
00805 resetPQExpBuffer(privswgo);
00806
00807 if (strcmp(type, "TABLE") == 0 || strcmp(type, "SEQUENCE") == 0 ||
00808 strcmp(type, "TABLES") == 0 || strcmp(type, "SEQUENCES") == 0)
00809 {
00810 CONVERT_PRIV('r', "SELECT");
00811
00812 if (strcmp(type, "SEQUENCE") == 0 ||
00813 strcmp(type, "SEQUENCES") == 0)
00814
00815 CONVERT_PRIV('U', "USAGE");
00816 else
00817 {
00818
00819 CONVERT_PRIV('a', "INSERT");
00820 if (remoteVersion >= 70200)
00821 CONVERT_PRIV('x', "REFERENCES");
00822
00823 if (subname == NULL)
00824 {
00825 if (remoteVersion >= 70200)
00826 {
00827 CONVERT_PRIV('d', "DELETE");
00828 CONVERT_PRIV('t', "TRIGGER");
00829 }
00830 if (remoteVersion >= 80400)
00831 CONVERT_PRIV('D', "TRUNCATE");
00832 }
00833 }
00834
00835
00836 if (remoteVersion >= 70200 ||
00837 strcmp(type, "SEQUENCE") == 0 ||
00838 strcmp(type, "SEQUENCES") == 0)
00839 CONVERT_PRIV('w', "UPDATE");
00840 else
00841
00842 CONVERT_PRIV('w', "UPDATE,DELETE");
00843 }
00844 else if (strcmp(type, "FUNCTION") == 0 ||
00845 strcmp(type, "FUNCTIONS") == 0)
00846 CONVERT_PRIV('X', "EXECUTE");
00847 else if (strcmp(type, "LANGUAGE") == 0)
00848 CONVERT_PRIV('U', "USAGE");
00849 else if (strcmp(type, "SCHEMA") == 0)
00850 {
00851 CONVERT_PRIV('C', "CREATE");
00852 CONVERT_PRIV('U', "USAGE");
00853 }
00854 else if (strcmp(type, "DATABASE") == 0)
00855 {
00856 CONVERT_PRIV('C', "CREATE");
00857 CONVERT_PRIV('c', "CONNECT");
00858 CONVERT_PRIV('T', "TEMPORARY");
00859 }
00860 else if (strcmp(type, "TABLESPACE") == 0)
00861 CONVERT_PRIV('C', "CREATE");
00862 else if (strcmp(type, "TYPE") == 0 ||
00863 strcmp(type, "TYPES") == 0)
00864 CONVERT_PRIV('U', "USAGE");
00865 else if (strcmp(type, "FOREIGN DATA WRAPPER") == 0)
00866 CONVERT_PRIV('U', "USAGE");
00867 else if (strcmp(type, "FOREIGN SERVER") == 0)
00868 CONVERT_PRIV('U', "USAGE");
00869 else if (strcmp(type, "FOREIGN TABLE") == 0)
00870 CONVERT_PRIV('r', "SELECT");
00871 else if (strcmp(type, "LARGE OBJECT") == 0)
00872 {
00873 CONVERT_PRIV('r', "SELECT");
00874 CONVERT_PRIV('w', "UPDATE");
00875 }
00876 else
00877 abort();
00878
00879 #undef CONVERT_PRIV
00880
00881 if (all_with_go)
00882 {
00883 resetPQExpBuffer(privs);
00884 printfPQExpBuffer(privswgo, "ALL");
00885 if (subname)
00886 appendPQExpBuffer(privswgo, "(%s)", subname);
00887 }
00888 else if (all_without_go)
00889 {
00890 resetPQExpBuffer(privswgo);
00891 printfPQExpBuffer(privs, "ALL");
00892 if (subname)
00893 appendPQExpBuffer(privs, "(%s)", subname);
00894 }
00895
00896 free(buf);
00897
00898 return true;
00899 }
00900
00901
00902
00903
00904
00905
00906 static char *
00907 copyAclUserName(PQExpBuffer output, char *input)
00908 {
00909 resetPQExpBuffer(output);
00910
00911 while (*input && *input != '=')
00912 {
00913
00914
00915
00916 if (*input != '"')
00917 appendPQExpBufferChar(output, *input++);
00918 else
00919 {
00920
00921 input++;
00922
00923 while (!(*input == '"' && *(input + 1) != '"'))
00924 {
00925 if (*input == '\0')
00926 return input;
00927
00928
00929
00930
00931
00932 if (*input == '"' && *(input + 1) == '"')
00933 input++;
00934 appendPQExpBufferChar(output, *input++);
00935 }
00936 input++;
00937 }
00938 }
00939 return input;
00940 }
00941
00942
00943
00944
00945 static void
00946 AddAcl(PQExpBuffer aclbuf, const char *keyword, const char *subname)
00947 {
00948 if (aclbuf->len > 0)
00949 appendPQExpBufferChar(aclbuf, ',');
00950 appendPQExpBuffer(aclbuf, "%s", keyword);
00951 if (subname)
00952 appendPQExpBuffer(aclbuf, "(%s)", subname);
00953 }
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981 bool
00982 processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern,
00983 bool have_where, bool force_escape,
00984 const char *schemavar, const char *namevar,
00985 const char *altnamevar, const char *visibilityrule)
00986 {
00987 PQExpBufferData schemabuf;
00988 PQExpBufferData namebuf;
00989 int encoding = PQclientEncoding(conn);
00990 bool inquotes;
00991 const char *cp;
00992 int i;
00993 bool added_clause = false;
00994
00995 #define WHEREAND() \
00996 (appendPQExpBufferStr(buf, have_where ? " AND " : "WHERE "), \
00997 have_where = true, added_clause = true)
00998
00999 if (pattern == NULL)
01000 {
01001
01002 if (visibilityrule)
01003 {
01004 WHEREAND();
01005 appendPQExpBuffer(buf, "%s\n", visibilityrule);
01006 }
01007 return added_clause;
01008 }
01009
01010 initPQExpBuffer(&schemabuf);
01011 initPQExpBuffer(&namebuf);
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026 appendPQExpBufferStr(&namebuf, "^(");
01027
01028 inquotes = false;
01029 cp = pattern;
01030
01031 while (*cp)
01032 {
01033 char ch = *cp;
01034
01035 if (ch == '"')
01036 {
01037 if (inquotes && cp[1] == '"')
01038 {
01039
01040 appendPQExpBufferChar(&namebuf, '"');
01041 cp++;
01042 }
01043 else
01044 inquotes = !inquotes;
01045 cp++;
01046 }
01047 else if (!inquotes && isupper((unsigned char) ch))
01048 {
01049 appendPQExpBufferChar(&namebuf,
01050 pg_tolower((unsigned char) ch));
01051 cp++;
01052 }
01053 else if (!inquotes && ch == '*')
01054 {
01055 appendPQExpBufferStr(&namebuf, ".*");
01056 cp++;
01057 }
01058 else if (!inquotes && ch == '?')
01059 {
01060 appendPQExpBufferChar(&namebuf, '.');
01061 cp++;
01062 }
01063 else if (!inquotes && ch == '.')
01064 {
01065
01066 resetPQExpBuffer(&schemabuf);
01067 appendPQExpBufferStr(&schemabuf, namebuf.data);
01068 resetPQExpBuffer(&namebuf);
01069 appendPQExpBufferStr(&namebuf, "^(");
01070 cp++;
01071 }
01072 else if (ch == '$')
01073 {
01074
01075
01076
01077
01078
01079
01080
01081 appendPQExpBufferStr(&namebuf, "\\$");
01082 cp++;
01083 }
01084 else
01085 {
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095 if ((inquotes || force_escape) &&
01096 strchr("|*+?()[]{}.^$\\", ch))
01097 appendPQExpBufferChar(&namebuf, '\\');
01098 i = PQmblen(cp, encoding);
01099 while (i-- && *cp)
01100 {
01101 appendPQExpBufferChar(&namebuf, *cp);
01102 cp++;
01103 }
01104 }
01105 }
01106
01107
01108
01109
01110
01111 if (namebuf.len > 2)
01112 {
01113
01114
01115 appendPQExpBufferStr(&namebuf, ")$");
01116
01117 if (strcmp(namebuf.data, "^(.*)$") != 0)
01118 {
01119 WHEREAND();
01120 if (altnamevar)
01121 {
01122 appendPQExpBuffer(buf, "(%s ~ ", namevar);
01123 appendStringLiteralConn(buf, namebuf.data, conn);
01124 appendPQExpBuffer(buf, "\n OR %s ~ ", altnamevar);
01125 appendStringLiteralConn(buf, namebuf.data, conn);
01126 appendPQExpBufferStr(buf, ")\n");
01127 }
01128 else
01129 {
01130 appendPQExpBuffer(buf, "%s ~ ", namevar);
01131 appendStringLiteralConn(buf, namebuf.data, conn);
01132 appendPQExpBufferChar(buf, '\n');
01133 }
01134 }
01135 }
01136
01137 if (schemabuf.len > 2)
01138 {
01139
01140
01141 appendPQExpBufferStr(&schemabuf, ")$");
01142
01143 if (strcmp(schemabuf.data, "^(.*)$") != 0 && schemavar)
01144 {
01145 WHEREAND();
01146 appendPQExpBuffer(buf, "%s ~ ", schemavar);
01147 appendStringLiteralConn(buf, schemabuf.data, conn);
01148 appendPQExpBufferChar(buf, '\n');
01149 }
01150 }
01151 else
01152 {
01153
01154 if (visibilityrule)
01155 {
01156 WHEREAND();
01157 appendPQExpBuffer(buf, "%s\n", visibilityrule);
01158 }
01159 }
01160
01161 termPQExpBuffer(&schemabuf);
01162 termPQExpBuffer(&namebuf);
01163
01164 return added_clause;
01165 #undef WHEREAND
01166 }
01167
01168
01169
01170
01171
01172
01173 void
01174 buildShSecLabelQuery(PGconn *conn, const char *catalog_name, uint32 objectId,
01175 PQExpBuffer sql)
01176 {
01177 appendPQExpBuffer(sql,
01178 "SELECT provider, label FROM pg_catalog.pg_shseclabel "
01179 "WHERE classoid = '%s'::pg_catalog.regclass AND "
01180 "objoid = %u", catalog_name, objectId);
01181 }
01182
01183
01184
01185
01186
01187
01188
01189 void
01190 emitShSecLabels(PGconn *conn, PGresult *res, PQExpBuffer buffer,
01191 const char *target, const char *objname)
01192 {
01193 int i;
01194
01195 for (i = 0; i < PQntuples(res); i++)
01196 {
01197 char *provider = PQgetvalue(res, i, 0);
01198 char *label = PQgetvalue(res, i, 1);
01199
01200
01201 appendPQExpBuffer(buffer,
01202 "SECURITY LABEL FOR %s ON %s",
01203 fmtId(provider), target);
01204 appendPQExpBuffer(buffer,
01205 " %s IS ",
01206 fmtId(objname));
01207 appendStringLiteralConn(buffer, label, conn);
01208 appendPQExpBuffer(buffer, ";\n");
01209 }
01210 }
01211
01212
01213 void
01214 simple_string_list_append(SimpleStringList *list, const char *val)
01215 {
01216 SimpleStringListCell *cell;
01217
01218
01219 cell = (SimpleStringListCell *)
01220 pg_malloc(sizeof(SimpleStringListCell) + strlen(val));
01221
01222 cell->next = NULL;
01223 strcpy(cell->val, val);
01224
01225 if (list->tail)
01226 list->tail->next = cell;
01227 else
01228 list->head = cell;
01229 list->tail = cell;
01230 }
01231
01232 bool
01233 simple_string_list_member(SimpleStringList *list, const char *val)
01234 {
01235 SimpleStringListCell *cell;
01236
01237 for (cell = list->head; cell; cell = cell->next)
01238 {
01239 if (strcmp(cell->val, val) == 0)
01240 return true;
01241 }
01242 return false;
01243 }