PageRenderTime 63ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/libsrc/Wi/sqlbif2.c

https://github.com/XixiLuo/virtuoso-opensource
C | 1801 lines | 1598 code | 138 blank | 65 comment | 424 complexity | 6bc5d005fae4296a4549051b7846197a MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, Apache-2.0, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * sqlbif2.c
  3. *
  4. * $Id$
  5. *
  6. * SQL Built In Functions. Part 2
  7. *
  8. * This file is part of the OpenLink Software Virtuoso Open-Source (VOS)
  9. * project.
  10. *
  11. * Copyright (C) 1998-2014 OpenLink Software
  12. *
  13. * This project is free software; you can redistribute it and/or modify it
  14. * under the terms of the GNU General Public License as published by the
  15. * Free Software Foundation; only version 2 of the License, dated June 1991.
  16. *
  17. * This program is distributed in the hope that it will be useful, but
  18. * WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  20. * General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU General Public License along
  23. * with this program; if not, write to the Free Software Foundation, Inc.,
  24. * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  25. *
  26. */
  27. #include "sqlnode.h"
  28. #include "sqlfn.h"
  29. #include "eqlcomp.h"
  30. #include "lisprdr.h"
  31. #include "sqlpar.h"
  32. #include "sqlcmps.h"
  33. #include "sqlintrp.h"
  34. #include "sqlbif.h"
  35. #include "arith.h"
  36. #include "security.h"
  37. #include "sqlpfn.h"
  38. #include "http.h"
  39. #include "libutil.h"
  40. #include "sqlo.h"
  41. #include "sqlver.h"
  42. #include "srvmultibyte.h"
  43. #include "xmlparser.h"
  44. #include "xmltree.h"
  45. #ifdef HAVE_PWD_H
  46. #include <pwd.h>
  47. #endif
  48. #ifdef HAVE_GRP_H
  49. #include <grp.h>
  50. #endif
  51. #ifndef KEYCOMP
  52. extern ptrlong itc_dive_transit_call_ctr;
  53. extern ptrlong itc_try_land_call_ctr;
  54. static caddr_t
  55. bif_itc_dive_transit_call_ctr (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args)
  56. {
  57. caddr_t res = box_num (itc_dive_transit_call_ctr);
  58. if ((0 < BOX_ELEMENTS (args)) && bif_long_arg (qst, args, 0, "itc_dive_transit_call_ctr"))
  59. itc_dive_transit_call_ctr = 0;
  60. return res;
  61. }
  62. static caddr_t
  63. bif_itc_try_land_call_ctr (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args)
  64. {
  65. caddr_t res = box_num (itc_try_land_call_ctr);
  66. if ((0 < BOX_ELEMENTS (args)) && bif_long_arg (qst, args, 0, "itc_try_land_call_ctr"))
  67. itc_try_land_call_ctr = 0;
  68. return res;
  69. }
  70. #endif
  71. static caddr_t
  72. bif_ddl_read_constraints (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args)
  73. {
  74. caddr_t spec_tb_name = bif_string_or_null_arg (qst, args, 0, "__ddl_read_constraints");
  75. ddl_read_constraints (spec_tb_name, qst);
  76. return NULL;
  77. }
  78. id_hash_t *name_to_pl_name;
  79. void
  80. pl_bif_name_define (const char *name)
  81. {
  82. char buff[2 * MAX_NAME_LEN];
  83. caddr_t data;
  84. if (!name_to_pl_name)
  85. {
  86. name_to_pl_name = id_casemode_hash_create (101);
  87. }
  88. name = sqlp_box_id_upcase (name);
  89. if (strchr (name, NAME_SEPARATOR))
  90. strcpy_ck (buff, name);
  91. else
  92. snprintf (buff, sizeof (buff), "DB.DBA.%s", name);
  93. data = sym_string (buff);
  94. id_hash_set (name_to_pl_name, (char *) &name, (char *) &data);
  95. }
  96. caddr_t
  97. find_pl_bif_name (caddr_t name)
  98. {
  99. caddr_t *full = (caddr_t *) id_hash_get (name_to_pl_name, (caddr_t) &name);
  100. if (full)
  101. return *full;
  102. else if (case_mode == CM_MSSQL)
  103. {
  104. caddr_t name2 = sqlp_box_id_upcase (name);
  105. full = (caddr_t *) id_hash_get (name_to_pl_name, (caddr_t) &name2);
  106. dk_free_box (name2);
  107. if (full)
  108. return *full;
  109. }
  110. return name;
  111. }
  112. int lockdown_mode = 0;
  113. typedef struct co_req_2_s {
  114. semaphore_t *sem;
  115. dk_set_t *set;
  116. } co_req_2_t;
  117. static void
  118. collect_listeners (co_req_2_t *req)
  119. {
  120. dk_set_t peers = PrpcListPeers ();
  121. DO_SET (dk_session_t *, peer, &peers)
  122. {
  123. if (SESSTAT_ISSET (peer->dks_session, SST_LISTENING) &&
  124. !PrpcIsListen (peer))
  125. {
  126. remove_from_served_sessions (peer);
  127. dk_set_push (req->set, peer);
  128. }
  129. }
  130. END_DO_SET ();
  131. if (req->sem)
  132. semaphore_leave (req->sem);
  133. }
  134. static void
  135. restore_listeners (co_req_2_t *req)
  136. {
  137. DO_SET (dk_session_t *, listener, req->set)
  138. {
  139. add_to_served_sessions (listener);
  140. }
  141. END_DO_SET ();
  142. dk_set_free (*req->set);
  143. *req->set = NULL;
  144. if (req->sem)
  145. semaphore_leave (req->sem);
  146. }
  147. int
  148. dks_is_localhost (dk_session_t *ses)
  149. {
  150. if (ses->dks_session->ses_class == SESCLASS_UNIX)
  151. return 1;
  152. else if (ses->dks_session->ses_class == SESCLASS_TCPIP)
  153. {
  154. char buf[150];
  155. if (!tcpses_getsockname (ses->dks_session, buf, sizeof (buf)))
  156. {
  157. if (!strncmp (buf, "127.0.0.1", 9))
  158. return 1;
  159. }
  160. }
  161. return 0;
  162. }
  163. static caddr_t
  164. bif_sys_lockdown (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args)
  165. {
  166. ptrlong lockdown = bif_long_arg (qst, args, 0, "sys_lockdown");
  167. query_instance_t *qi = (query_instance_t *) qst;
  168. dk_set_t clients;
  169. static dk_set_t listeners = NULL;
  170. co_req_2_t req;
  171. ptrlong disconnect_mode = 0;
  172. static ptrlong last_disconnect_mode = 0;
  173. long res = 0;
  174. sec_check_dba (qi, "sys_lockdown");
  175. req.sem = THREAD_CURRENT_THREAD->thr_sem;
  176. req.set = &listeners;
  177. if (BOX_ELEMENTS (args) > 1)
  178. disconnect_mode = bif_long_arg (qst, args, 1, "sys_lockdown");
  179. if (lockdown && !lockdown_mode)
  180. {
  181. dk_session_t *this_client_ses = IMMEDIATE_CLIENT;
  182. char buffer[50];
  183. if (!qi->qi_client->cli_ws)
  184. tcpses_print_client_ip (qi->qi_client->cli_session->dks_session, buffer, sizeof (buffer));
  185. else
  186. strncpy (buffer, qi->qi_client->cli_ws->ws_client_ip, sizeof (buffer));
  187. buffer[sizeof (buffer) - 1] = 0;
  188. if (!dks_is_localhost (this_client_ses))
  189. this_client_ses = NULL;
  190. logmsg (LOG_EMERG, NULL, 0, 1,
  191. "Security lockdown mode ON (listeners %s) via sys_lockdown() called by %s (IP:%s)",
  192. disconnect_mode ? "OFF" : "UNSERVED",
  193. qi->qi_client->cli_user ? qi->qi_client->cli_user->usr_name : "<internal>",
  194. buffer);
  195. lockdown_mode = 1;
  196. #ifndef NDEBUG
  197. if (listeners)
  198. GPF_T1 ("listeners already there on locking the system down");
  199. #endif
  200. PrpcSelfSignal ((self_signal_func) collect_listeners, (caddr_t) &req);
  201. semaphore_enter (req.sem);
  202. mutex_enter (thread_mtx);
  203. clients = srv_get_logons ();
  204. DO_SET (dk_session_t *, ses, &clients)
  205. {
  206. if (ses != this_client_ses)
  207. {
  208. client_connection_t *cli = DKS_DB_DATA (ses);
  209. if (cli)
  210. {
  211. cli->cli_terminate_requested = 1;
  212. ses->dks_to_close = 1;
  213. }
  214. }
  215. }
  216. END_DO_SET ();
  217. mutex_leave (thread_mtx);
  218. last_disconnect_mode = disconnect_mode;
  219. if (disconnect_mode)
  220. {
  221. DO_SET (dk_session_t *, ses, &listeners)
  222. {
  223. session_disconnect (ses->dks_session);
  224. }
  225. END_DO_SET ();
  226. }
  227. res = 1;
  228. }
  229. else if (!lockdown && lockdown_mode)
  230. {
  231. if (last_disconnect_mode)
  232. {
  233. DO_SET (dk_session_t *, ses, &listeners)
  234. {
  235. without_scheduling_tic ();
  236. session_listen (ses->dks_session);
  237. without_scheduling_tic ();
  238. }
  239. END_DO_SET ();
  240. }
  241. lockdown_mode = 0;
  242. PrpcSelfSignal ((self_signal_func) restore_listeners, (caddr_t) &req);
  243. semaphore_enter (req.sem);
  244. log_info ("Security lockdown mode ended via sys_lockdown()");
  245. res = 2;
  246. }
  247. return box_num (res);
  248. }
  249. int
  250. tcpses_check_disk_error (dk_session_t *ses, caddr_t *qst, int throw_error)
  251. {
  252. query_instance_t *qi = (query_instance_t *) qst;
  253. if (!ses || !ses->dks_session || !ses->dks_session->ses_class != SESCLASS_STRING
  254. || !ses->dks_session->ses_file->ses_max_blocks_init)
  255. return 0;
  256. if (SESSTAT_ISSET (ses->dks_session, SST_DISK_ERROR))
  257. {
  258. if (qst)
  259. {
  260. qi->qi_trx->lt_status = LT_BLOWN_OFF;
  261. qi->qi_trx->lt_error = LTE_NO_DISK;
  262. }
  263. if (throw_error)
  264. {
  265. sqlr_new_error ("42000", "SR452", "Error in accessing temp file");
  266. }
  267. return 1;
  268. }
  269. else
  270. return 0;
  271. }
  272. caddr_t
  273. bif_session_arg (caddr_t * qst, state_slot_t ** args, int nth, char *func)
  274. {
  275. caddr_t arg = bif_arg (qst, args, nth, func);
  276. dtp_t dtp = DV_TYPE_OF (arg);
  277. if (dtp != DV_STRING_SESSION && dtp != DV_CONNECTION)
  278. sqlr_new_error ("22023", "SR002",
  279. "Function %s needs a string output or a session as argument %d, not an arg of type %s (%d)",
  280. func, nth + 1, dv_type_title (dtp), dtp);
  281. return arg;
  282. }
  283. static caddr_t
  284. bif_blob_handle_from_session (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args)
  285. {
  286. caddr_t ses = bif_session_arg (qst, args, 0, "__blob_handle_from_session");
  287. blob_handle_t *bh;
  288. caddr_t dummy_null;
  289. if (!ssl_is_settable (args[0]))
  290. sqlr_new_error ("22023", "SR453", "__blob_handle_from_session argument 1 must be IN/OUT");
  291. bh = bh_alloc (DV_BLOB_HANDLE_DTP_FOR_BLOB_DTP (DV_BLOB_BIN));
  292. bh->bh_ask_from_client = 3;
  293. bh->bh_source_session = ses;
  294. dummy_null = NEW_DB_NULL;
  295. qst_swap (qst, args[0], &dummy_null);
  296. return (caddr_t) bh;
  297. }
  298. bif_type_t bt_blob_handle = {NULL, DV_BLOB_HANDLE, 0, 0};
  299. static caddr_t
  300. bif_os_chmod (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args)
  301. {
  302. caddr_t fname = bif_string_or_wide_or_uname_arg (qst, args, 0, "os_chmod");
  303. long mod = (long) bif_long_arg (qst, args, 1, "os_chmod");
  304. char *fname_cvt = NULL;
  305. caddr_t res;
  306. sec_check_dba ((query_instance_t *) qst, "os_chmod");
  307. #if defined (HAVE_CHMOD)
  308. fname_cvt = file_native_name (fname);
  309. file_path_assert (fname_cvt, NULL, 1);
  310. if (0 != chmod (fname_cvt, mod))
  311. {
  312. int eno = errno;
  313. res = box_dv_short_string (strerror (eno));
  314. }
  315. else
  316. res = NEW_DB_NULL;
  317. #else
  318. res = box_dv_short_string ("CHMOD feature not available in the host OS");
  319. #endif
  320. dk_free_box (fname_cvt);
  321. return res;
  322. }
  323. static dk_mutex_t *pwnam_mutex;
  324. caddr_t
  325. os_get_uname_by_uid (long uid)
  326. {
  327. caddr_t res = NULL;
  328. #if defined (HAVE_GETPWUID)
  329. struct passwd *pwd;
  330. mutex_enter (pwnam_mutex);
  331. pwd = getpwuid ((uid_t) uid);
  332. if (pwd)
  333. res = box_dv_short_string (pwd->pw_name);
  334. mutex_leave (pwnam_mutex);
  335. #endif
  336. if (!res)
  337. res = NEW_DB_NULL;
  338. return res;
  339. }
  340. caddr_t
  341. os_get_gname_by_gid (long gid)
  342. {
  343. caddr_t res = NULL;
  344. #if defined (HAVE_GETPWUID)
  345. struct group *grp;
  346. mutex_enter (pwnam_mutex);
  347. grp = getgrgid ((gid_t) gid);
  348. if (grp)
  349. res = box_dv_short_string (grp->gr_name);
  350. mutex_leave (pwnam_mutex);
  351. #endif
  352. if (!res)
  353. res = NEW_DB_NULL;
  354. return res;
  355. }
  356. #ifdef WIN32
  357. #include <Aclapi.h>
  358. caddr_t
  359. os_get_uname_by_fname (char *fname)
  360. {
  361. caddr_t ret = NULL;
  362. PSID owner = 0;
  363. if (ERROR_SUCCESS == GetNamedSecurityInfo (fname, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, &owner, NULL, NULL, NULL, NULL))
  364. {
  365. char name[1000], dname[1000];
  366. DWORD l_name = sizeof (name);
  367. DWORD l_dname = sizeof (dname);
  368. SID_NAME_USE use;
  369. if (LookupAccountSid (NULL, owner, name, &l_name, dname, &l_dname, &use))
  370. {
  371. ret = box_dv_short_string (name);
  372. }
  373. }
  374. return ret ? ret : NEW_DB_NULL;
  375. }
  376. caddr_t
  377. os_get_gname_by_fname (char *fname)
  378. {
  379. caddr_t ret = NULL;
  380. PSID owner = 0;
  381. if (ERROR_SUCCESS == GetNamedSecurityInfo (fname, SE_FILE_OBJECT, GROUP_SECURITY_INFORMATION, NULL, &owner, NULL, NULL, NULL))
  382. {
  383. char name[1000], dname[1000];
  384. DWORD l_name = sizeof (name);
  385. DWORD l_dname = sizeof (dname);
  386. SID_NAME_USE use;
  387. if (LookupAccountSid (NULL, owner, name, &l_name, dname, &l_dname, &use))
  388. {
  389. ret = box_dv_short_string (name);
  390. }
  391. }
  392. return ret ? ret : NEW_DB_NULL;
  393. }
  394. #endif
  395. static caddr_t
  396. bif_os_chown (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args)
  397. {
  398. caddr_t fname = bif_string_or_wide_or_uname_arg (qst, args, 0, "os_chown");
  399. caddr_t user = bif_string_arg (qst, args, 1, "os_chown");
  400. caddr_t group = bif_string_arg (qst, args, 2, "os_chown");
  401. char *fname_cvt = NULL;
  402. caddr_t res = NULL;
  403. sec_check_dba ((query_instance_t *) qst, "os_chown");
  404. fname_cvt = file_native_name (fname);
  405. file_path_assert (fname_cvt, NULL, 1);
  406. #if defined (HAVE_CHOWN) && defined (HAVE_GETPWNAM) && defined (HAVE_GETGRNAM)
  407. {
  408. char buffer[255];
  409. struct passwd *u_info = NULL;
  410. struct group *g_info = NULL;
  411. uid_t uid = -1;
  412. gid_t gid = -1;
  413. mutex_enter (pwnam_mutex);
  414. u_info = getpwnam (user);
  415. if (u_info)
  416. uid = u_info->pw_uid;
  417. g_info = getgrnam (group);
  418. if (g_info)
  419. gid = g_info->gr_gid;
  420. mutex_leave (pwnam_mutex);
  421. if (!res && !u_info)
  422. {
  423. snprintf (buffer, sizeof (buffer), "User %.200s does not exist", user);
  424. res = box_dv_short_string (buffer);
  425. }
  426. if (!res && !g_info)
  427. {
  428. snprintf (buffer, sizeof (buffer), "Group %.200s does not exist", group);
  429. res = box_dv_short_string (buffer);
  430. }
  431. if (!res)
  432. {
  433. if (0 != chown (fname_cvt, uid, gid))
  434. {
  435. int eno = errno;
  436. res = box_dv_short_string (strerror (eno));
  437. }
  438. else
  439. res = NEW_DB_NULL;
  440. }
  441. }
  442. #elif defined (WIN32)
  443. {
  444. SID_NAME_USE use_user = SidTypeUser, use_group = SidTypeGroup;
  445. char user_sid[SECURITY_MAX_SID_SIZE], group_sid[SECURITY_MAX_SID_SIZE], dom1[1000], dom2[1000];
  446. DWORD user_sid_sz = SECURITY_MAX_SID_SIZE, group_sid_sz = SECURITY_MAX_SID_SIZE, d1 = sizeof (dom1), d2 = sizeof (dom2);
  447. if (LookupAccountName (NULL, user, (PSID) user_sid, &user_sid_sz, dom1, &d1, &use_user) &&
  448. LookupAccountName (NULL, group, (PSID) group_sid, &group_sid_sz, dom2, &d2, &use_group))
  449. {
  450. if (ERROR_SUCCESS == SetNamedSecurityInfo (fname_cvt, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION,
  451. (PSID) user_sid, (PSID) group_sid, NULL, NULL))
  452. res = NEW_DB_NULL;
  453. }
  454. if (!res)
  455. {
  456. LPVOID lpMsgBuf;
  457. if (FormatMessage(
  458. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  459. FORMAT_MESSAGE_FROM_SYSTEM |
  460. FORMAT_MESSAGE_IGNORE_INSERTS,
  461. NULL,
  462. GetLastError(),
  463. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
  464. (LPTSTR) &lpMsgBuf,
  465. 0,
  466. NULL ))
  467. {
  468. res = box_dv_short_string (lpMsgBuf);
  469. LocalFree( lpMsgBuf );
  470. }
  471. else
  472. res = box_dv_short_string ("Unknown Win32 error");
  473. }
  474. }
  475. #else
  476. res = box_dv_short_string ("CHOWN feature not available in the host OS");
  477. #endif
  478. dk_free_box (fname_cvt);
  479. return res;
  480. }
  481. float compiler_unit_msecs = 0;
  482. #define SQLO_NITERS 1000
  483. #define COL_COUNT "select count (*) from SYS_COLS a table option (index primary key) where exists (select 1 from SYS_COLS b table option (loop) where a.\"TABLE\" = b.\"TABLE\" and a.\"COLUMN\" = b.\"COLUMN\")"
  484. extern int enable_vec_cost;
  485. void
  486. srv_calculate_sqlo_unit_msec (char* stmt)
  487. {
  488. caddr_t err = NULL;
  489. int deflt_stmt = 0;
  490. caddr_t score_box;
  491. float score;
  492. int save_qp = enable_qp;
  493. float start_time, end_time;
  494. local_cursor_t *lc_tim = NULL;
  495. query_t *qr = NULL;
  496. dbe_table_t *sys_cols_tb = sch_name_to_table (isp_schema (NULL), "DB.DBA.SYS_COLS");
  497. long old_tb_count;
  498. int inx;
  499. client_connection_t *cli = bootstrap_cli;
  500. old_tb_count = sys_cols_tb->tb_count;
  501. sys_cols_tb->tb_count = wi_inst.wi_schema->sc_id_to_col->ht_count;
  502. if (!stmt)
  503. {
  504. deflt_stmt = 1;
  505. stmt = COL_COUNT;
  506. }
  507. qr = sql_compile (stmt, cli, &err, SQLC_DEFAULT);
  508. start_time = (float) get_msec_real_time ();
  509. enable_qp = 1;
  510. for (inx = 0; inx < SQLO_NITERS; inx++)
  511. { /* repeat enough times as sys_cols is usually not very big */
  512. err = qr_quick_exec (qr, cli, NULL, &lc_tim, 0);
  513. lc_next (lc_tim);
  514. sys_cols_tb->tb_count = (long) unbox (lc_nth_col (lc_tim, 0));
  515. lc_next (lc_tim);
  516. lc_free (lc_tim);
  517. if (inx > 0 && inx % 10 == 0 && get_msec_real_time () - start_time > 1000)
  518. {
  519. inx += 1;
  520. break;
  521. }
  522. }
  523. end_time = (float) get_msec_real_time ();
  524. enable_qp = save_qp;
  525. qr_free (qr);
  526. score_box = (caddr_t) sql_compile (stmt, cli, &err, SQLC_SQLO_SCORE);
  527. score = unbox_float (score_box);
  528. /*printf ("cu score = %f\n", score);*/
  529. dk_free_tree (score_box);
  530. compiler_unit_msecs = (end_time - start_time) / (score * inx);
  531. if (deflt_stmt && enable_vec_cost)
  532. compiler_unit_msecs /= 4.339062;
  533. sys_cols_tb->tb_count = old_tb_count;
  534. local_commit (bootstrap_cli);
  535. log_info ("Compiler unit is timed at %f msec", (double) compiler_unit_msecs);
  536. }
  537. static caddr_t
  538. bif_user_has_role (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args)
  539. {
  540. caddr_t uname = bif_string_arg (qst, args, 0, "user_has_role");
  541. caddr_t rname = bif_string_arg (qst, args, 1, "user_has_role");
  542. user_t **place;
  543. user_t *usr;
  544. int inx;
  545. sec_check_dba ((query_instance_t *) qst, "user_has_role");
  546. place = (user_t **) id_hash_get (sec_users, (caddr_t) &uname);
  547. if (!place)
  548. sqlr_new_error ("22023", "SR390", "No such user %s in user_has_role", uname);
  549. usr = *place;
  550. DO_BOX (ptrlong, g_id, inx, usr->usr_g_ids)
  551. {
  552. user_t *gr = sec_id_to_user ((oid_t) g_id);
  553. if (!strcmp (gr->usr_name, rname))
  554. return box_num (1);
  555. }
  556. END_DO_BOX;
  557. return box_num (0);
  558. }
  559. static caddr_t
  560. bif_user_is_dba (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args)
  561. {
  562. caddr_t uname = bif_string_arg (qst, args, 0, "user_is_dba");
  563. user_t **place;
  564. user_t *usr;
  565. int rc;
  566. sec_check_dba ((query_instance_t *) qst, "user_is_dba");
  567. place = (user_t **) id_hash_get (sec_users, (caddr_t) &uname);
  568. if (!place)
  569. sqlr_new_error ("22023", "SR390", "No such user %s in user_is_dba", uname);
  570. usr = *place;
  571. rc = sec_user_has_group (G_ID_DBA, usr->usr_id);
  572. return box_num (rc);
  573. }
  574. static caddr_t
  575. bif_client_attr (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args)
  576. {
  577. query_instance_t * qi = (query_instance_t *) qst;
  578. caddr_t mode = bif_string_arg (qst, args, 0, "client_attr");
  579. session_t *ses;
  580. if (!stricmp ("client_protocol", mode))
  581. {
  582. if (qi->qi_client->cli_ws && qi->qi_client->cli_ws->ws_proto)
  583. return box_dv_short_string (qi->qi_client->cli_ws->ws_proto);
  584. else
  585. return box_dv_short_string ("SQL");
  586. }
  587. else if (!stricmp ("client_ip", mode))
  588. {
  589. return int_client_ip (qi, 0);
  590. }
  591. else if (!stricmp ("accepting_ip", mode))
  592. {
  593. char buf[100];
  594. if (!qi->qi_client->cli_ws && !qi->qi_client->cli_session)
  595. return box_dv_short_string ("127.0.0.1");
  596. ses = qi->qi_client->cli_ws && qi->qi_client->cli_ws->ws_session ?
  597. qi->qi_client->cli_ws->ws_session->dks_session : qi->qi_client->cli_session->dks_session;
  598. if (!tcpses_getsockname (ses, buf, sizeof (buf)))
  599. {
  600. #ifdef COM_UNIXSOCK
  601. {
  602. int port;
  603. if (!strncmp (buf, UNIXSOCK_ADD_ADDR, sizeof (UNIXSOCK_ADD_ADDR) - 1)
  604. && (port = atoi (buf + sizeof (UNIXSOCK_ADD_ADDR) - 1)))
  605. snprintf (buf, sizeof (buf), "127.0.0.1:%d", port);
  606. }
  607. #endif
  608. return box_dv_short_string (buf);
  609. }
  610. *err_ret = srv_make_new_error ("22005", "SR401", "Server address not known");
  611. }
  612. else if (!stricmp ("client_application", mode))
  613. {
  614. if (qi->qi_client->cli_user_info)
  615. return box_dv_short_string (qi->qi_client->cli_user_info);
  616. }
  617. else if (!stricmp ("client_ssl", mode))
  618. {
  619. #ifdef _SSL
  620. SSL *ssl = (SSL *) tcpses_get_ssl (qi->qi_client->cli_ws ?
  621. qi->qi_client->cli_ws->ws_session->dks_session :
  622. qi->qi_client->cli_session->dks_session);
  623. if (ssl)
  624. return box_num (1);
  625. #else
  626. sqlr_new_error ("22005", "SR403", "'client_ssl' value of client_attr option is not supported by this build of the Virtuoso server");
  627. return NULL;
  628. #endif
  629. }
  630. else if (!stricmp ("client_certificate", mode))
  631. {
  632. #ifdef _SSL
  633. caddr_t ret = NULL;
  634. char *ptr;
  635. SSL *ssl = (SSL *) tcpses_get_ssl (qi->qi_client->cli_ws ?
  636. qi->qi_client->cli_ws->ws_session->dks_session :
  637. qi->qi_client->cli_session->dks_session);
  638. X509 *cert = NULL;
  639. BIO *in = NULL;
  640. if (ssl)
  641. cert = SSL_get_peer_certificate (ssl);
  642. else
  643. return NULL;
  644. if (!cert)
  645. return NULL;
  646. in = BIO_new (BIO_s_mem());
  647. if (!in)
  648. {
  649. char err_buf[512];
  650. sqlr_new_error ("22005", "SR402", "Cannot allocate temp space. SSL error : %s",
  651. get_ssl_error_text (err_buf, sizeof (err_buf)));
  652. return NULL;
  653. }
  654. BIO_reset(in);
  655. PEM_write_bio_X509 (in, cert);
  656. ret = dk_alloc_box (BIO_get_mem_data (in, &ptr) + 1, DV_SHORT_STRING);
  657. memcpy (ret, ptr, box_length (ret) - 1);
  658. ret[box_length (ret) - 1] = 0;
  659. BIO_free (in);
  660. return ret;
  661. #else
  662. sqlr_new_error ("22005", "SR403", "'client_certificate' value of client_attr option is not supported by this build of the Virtuoso server");
  663. return NULL;
  664. #endif
  665. }
  666. else if (!stricmp ("transaction_log", mode))
  667. {
  668. int is_on = 1;
  669. if (srv_have_global_lock (THREAD_CURRENT_THREAD))
  670. is_on = 0;
  671. else if (qi->qi_trx->lt_replicate == REPL_NO_LOG)
  672. is_on = 0;
  673. return box_num (is_on);
  674. }
  675. else if (!stricmp ("connect_attrs", mode))
  676. {
  677. if (qi->qi_client->cli_info)
  678. return box_copy_tree (qi->qi_client->cli_info);
  679. else
  680. return NEW_DB_NULL;
  681. }
  682. else
  683. {
  684. *err_ret = srv_make_new_error ("22005", "SR403", " %s is not valid client_attr option", mode);
  685. }
  686. return NULL;
  687. }
  688. static caddr_t
  689. bif_query_instance_id (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args)
  690. {
  691. query_instance_t * qi = (query_instance_t *) qst;
  692. long depth = bif_long_range_arg (qst, args, 0, "query_instance_id", 0, 0xffff);
  693. while ((depth-- > 0) && (NULL != qi)) qi = qi->qi_caller;
  694. if (NULL == qi)
  695. return NEW_DB_NULL;
  696. return box_num ((ptrlong)qi);
  697. }
  698. static caddr_t
  699. bif_sql_warnings_resignal (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args)
  700. {
  701. caddr_t *warnings = (caddr_t *) bif_array_or_null_arg (qst, args, 0, "sql_warnings_resignal");
  702. if (warnings)
  703. {
  704. int inx;
  705. if (DV_ARRAY_OF_POINTER != DV_TYPE_OF (warnings))
  706. sqlr_new_error ("22023", "SR454", "Invalid warnings array");
  707. DO_BOX (caddr_t, warning, inx, warnings)
  708. {
  709. if (!IS_BOX_POINTER (warning) ||
  710. DV_ARRAY_OF_POINTER != DV_TYPE_OF (warning) ||
  711. BOX_ELEMENTS (warning) != 3 ||
  712. (((caddr_t*) warning)[0]) != (caddr_t) QA_WARNING ||
  713. (!DV_STRINGP (ERR_STATE (warning)) && DV_C_STRING != DV_TYPE_OF (ERR_STATE (warning))) ||
  714. (!DV_STRINGP (ERR_MESSAGE (warning)) && DV_C_STRING != DV_TYPE_OF (ERR_MESSAGE (warning))))
  715. sqlr_new_error ("22023", "SR455", "Invalid warning in the warnings array");
  716. sql_warning_add (box_copy_tree (warning), 0);
  717. }
  718. END_DO_BOX;
  719. }
  720. return NEW_DB_NULL;
  721. }
  722. static caddr_t
  723. bif_sql_warning (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args)
  724. {
  725. caddr_t sql_state = bif_string_arg (qst, args, 0, "sql_warning");
  726. caddr_t virt_code = bif_string_arg (qst, args, 1, "sql_warning");
  727. caddr_t msg = bif_string_arg (qst, args, 2, "sql_warning");
  728. sqlr_warning (sql_state, virt_code, "%s", msg);
  729. return NEW_DB_NULL;
  730. }
  731. static caddr_t
  732. bif_sec_uid_to_user (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args)
  733. {
  734. oid_t uid = (oid_t) bif_long_arg (qst, args, 0, "__sec_uid_to_user");
  735. user_t *user;
  736. user = sec_id_to_user (uid);
  737. if (user)
  738. return box_dv_short_string (user->usr_name);
  739. else
  740. return NEW_DB_NULL;
  741. }
  742. static caddr_t
  743. bif_current_proc_name (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args)
  744. {
  745. query_instance_t * qi = (query_instance_t *) qst;
  746. long frames = BOX_ELEMENTS (args) > 0 ? bif_long_arg (qst, args, 0, "current_proc_name") : 0;
  747. while (frames && IS_POINTER (qi))
  748. {
  749. frames --;
  750. qi = qi->qi_caller;
  751. }
  752. if (IS_POINTER (qi) && qi->qi_query && qi->qi_query->qr_proc_name)
  753. return box_string (qi->qi_query->qr_proc_name);
  754. return NEW_DB_NULL;
  755. }
  756. static caddr_t
  757. bif_host_id (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args)
  758. {
  759. if (build_host_id)
  760. return box_string (build_host_id);
  761. return NEW_DB_NULL;
  762. }
  763. boxint
  764. zorder_index (ptrlong x, ptrlong y)
  765. {
  766. x = ((x & 0x00000000FFFF0000LL) << 16) | (x & 0x000000000000FFFFLL);
  767. x = ((x & 0x0000FF00FF00FF00LL) << 8) | (x & 0x000000FF00FF00FFLL);
  768. x = ((x & 0x00F0F0F0F0F0F0F0LL) << 4) | (x & 0x000F0F0F0F0F0F0FLL);
  769. x = ((x & 0x0CCCCCCCCCCCCCCCLL) << 2) | (x & 0x0333333333333333LL);
  770. x = ((x & 0xAAAAAAAAAAAAAAAALL) << 1) | (x & 0x5555555555555555LL);
  771. y = ((y & 0x00000000FFFF0000LL) << 16) | (y & 0x000000000000FFFFLL);
  772. y = ((y & 0x0000FF00FF00FF00LL) << 8) | (y & 0x000000FF00FF00FFLL);
  773. y = ((y & 0x00F0F0F0F0F0F0F0LL) << 4) | (y & 0x000F0F0F0F0F0F0FLL);
  774. y = ((y & 0x0CCCCCCCCCCCCCCCLL) << 2) | (y & 0x0333333333333333LL);
  775. y = ((y & 0xAAAAAAAAAAAAAAAALL) << 1) | (y & 0x5555555555555555LL);
  776. return (y << 1) | x;
  777. }
  778. static caddr_t
  779. bif_zorder_index (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args)
  780. {
  781. ptrlong x = bif_long_range_arg (qst, args, 0, "zorder_index", -2020000000, 202000000);
  782. ptrlong y = bif_long_range_arg (qst, args, 1, "zorder_index", -2020000000, 202000000);
  783. boxint res = zorder_index (x, y);
  784. return box_num (res);
  785. }
  786. /*! URI parser according RFC 1808 recommendations
  787. Fills in array of twelve begin and past-the end indexes of elements */
  788. void
  789. rfc1808_parse_uri (const char *iri, rdf1808_split_t *split_ret)
  790. {
  791. const char *delim;
  792. split_ret->schema_begin = split_ret->schema_end = split_ret->netloc_begin = 0;
  793. split_ret->fragment_end = strlen (iri);
  794. /* Here we know Ss nn pp pp qq fF t */
  795. delim = strchr (iri, '#');
  796. if (NULL != delim)
  797. {
  798. split_ret->query_end = delim-iri;
  799. split_ret->fragment_begin = delim+1-iri;
  800. }
  801. else
  802. split_ret->query_end = split_ret->fragment_begin = split_ret->fragment_end;
  803. /* Here we know Ss nn pp pp qQ FF t */
  804. delim = strchr (iri, ':');
  805. if ((NULL != delim) && (delim < iri+split_ret->query_end))
  806. {
  807. const char *scan = iri;
  808. while (scan < delim)
  809. {
  810. if (!isalnum ((unsigned char) (scan[0])) && (NULL == strchr ("+-.", scan[0])))
  811. goto schema_done;
  812. scan++;
  813. }
  814. split_ret->schema_end = delim-iri;
  815. split_ret->netloc_begin = delim + 1 - iri;
  816. }
  817. schema_done:
  818. /* Here we know SS Nn pp pp qQ FF t */
  819. if (('/' == iri[split_ret->netloc_begin]) && ('/' == iri[split_ret->netloc_begin+1]))
  820. {
  821. split_ret->netloc_begin += 2;
  822. split_ret->two_slashes = split_ret->netloc_begin;
  823. delim = strchr (iri + split_ret->netloc_begin, '/');
  824. if ((NULL != delim) && (delim < iri+split_ret->query_end))
  825. {
  826. split_ret->netloc_end = split_ret->path_begin = delim - iri;
  827. }
  828. else
  829. {
  830. split_ret->netloc_end = split_ret->path_begin = split_ret->path_end = split_ret->params_begin = split_ret->params_end = split_ret->query_begin = split_ret->query_end;
  831. return;
  832. }
  833. }
  834. else
  835. {
  836. split_ret->two_slashes = 0;
  837. split_ret->netloc_end = split_ret->path_begin = split_ret->netloc_begin;
  838. }
  839. /* Here we know SS NN Pp pp qQ FF T */
  840. delim = strchr (iri + split_ret->path_begin, '?');
  841. if ((NULL != delim) && (delim < iri+split_ret->query_end))
  842. {
  843. split_ret->query_begin = delim + 1 - iri;
  844. split_ret->params_end = delim - iri;
  845. }
  846. else
  847. {
  848. split_ret->params_end = split_ret->query_begin = split_ret->query_end;
  849. }
  850. /* Here we know SS NN Pp pP QQ FF T */
  851. delim = strchr (iri + split_ret->path_begin, ';');
  852. if ((NULL != delim) && (delim < iri+split_ret->params_end))
  853. {
  854. split_ret->params_begin = delim + 1 - iri;
  855. split_ret->path_end = delim - iri;
  856. }
  857. else
  858. {
  859. split_ret->path_end = split_ret->params_begin = split_ret->params_end;
  860. }
  861. /* Here we know SS NN PP PP QQ FF T */
  862. CHECK_RDF1808_SPLIT((split_ret[0]), strlen (iri))
  863. }
  864. void
  865. rfc1808_parse_wide_uri (const wchar_t *iri, rdf1808_split_t *split_ret)
  866. {
  867. const wchar_t *delim;
  868. split_ret->schema_begin = split_ret->schema_end = split_ret->netloc_begin = 0;
  869. split_ret->fragment_end = virt_wcslen (iri);
  870. /* Here we know Ss nn pp pp qq fF t */
  871. delim = virt_wcschr (iri, '#');
  872. if (NULL != delim)
  873. {
  874. split_ret->query_end = delim-iri;
  875. split_ret->fragment_begin = delim+1-iri;
  876. }
  877. else
  878. split_ret->query_end = split_ret->fragment_begin = split_ret->fragment_end;
  879. /* Here we know Ss nn pp pp qQ FF t */
  880. delim = virt_wcschr (iri, ':');
  881. if ((NULL != delim) && (delim < iri+split_ret->query_end))
  882. {
  883. const wchar_t *scan = iri;
  884. while (scan < delim)
  885. {
  886. if (scan[0] & ~0x7f)
  887. goto schema_done;
  888. if (!isalnum ((unsigned char) (scan[0])) && (NULL == strchr ("+-.", ((char *)scan)[0])))
  889. goto schema_done;
  890. scan++;
  891. }
  892. split_ret->schema_end = delim-iri;
  893. split_ret->netloc_begin = delim + 1 - iri;
  894. }
  895. schema_done:
  896. /* Here we know SS Nn pp pp qQ FF t */
  897. if (('/' == iri[split_ret->netloc_begin]) && ('/' == iri[split_ret->netloc_begin+1]))
  898. {
  899. split_ret->netloc_begin += 2;
  900. split_ret->two_slashes = split_ret->netloc_begin;
  901. delim = virt_wcschr (iri + split_ret->netloc_begin, '/');
  902. if ((NULL != delim) && (delim < iri+split_ret->query_end))
  903. {
  904. split_ret->netloc_end = split_ret->path_begin = delim - iri;
  905. }
  906. else
  907. {
  908. split_ret->netloc_end = split_ret->path_begin = split_ret->path_end = split_ret->params_begin = split_ret->params_end = split_ret->query_begin = split_ret->query_end;
  909. return;
  910. }
  911. }
  912. else
  913. {
  914. split_ret->two_slashes = 0;
  915. split_ret->netloc_end = split_ret->path_begin = split_ret->netloc_begin;
  916. }
  917. /* Here we know SS NN Pp pp qQ FF T */
  918. delim = virt_wcschr (iri + split_ret->path_begin, '?');
  919. if ((NULL != delim) && (delim < iri+split_ret->query_end))
  920. {
  921. split_ret->query_begin = delim + 1 - iri;
  922. split_ret->params_end = delim - iri;
  923. }
  924. else
  925. {
  926. split_ret->params_end = split_ret->query_begin = split_ret->query_end;
  927. }
  928. /* Here we know SS NN Pp pP QQ FF T */
  929. delim = virt_wcschr (iri + split_ret->path_begin, ';');
  930. if ((NULL != delim) && (delim < iri+split_ret->params_end))
  931. {
  932. split_ret->params_begin = delim + 1 - iri;
  933. split_ret->path_end = delim - iri;
  934. }
  935. else
  936. {
  937. split_ret->path_end = split_ret->params_begin = split_ret->params_end;
  938. }
  939. /* Here we know SS NN PP PP QQ FF T */
  940. CHECK_RDF1808_SPLIT((split_ret[0]), virt_wcslen (iri))
  941. }
  942. /*! URI parser according RFC 1808 recommendations
  943. returns array of six past-the end indexes of elements */
  944. static caddr_t
  945. bif_rfc1808_parse_uri (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args)
  946. {
  947. ccaddr_t uri = bif_string_or_wide_or_uname_arg (qst, args, 0, "rfc1808_parse_uri");
  948. dtp_t uri_dtp = DV_TYPE_OF (uri);
  949. size_t uri_len;
  950. rdf1808_split_t split;
  951. caddr_t res;
  952. uri_len = box_length (uri);
  953. if (SMALLEST_POSSIBLE_POINTER <= uri_len)
  954. {
  955. if (DV_WIDE == uri_dtp)
  956. sqlr_new_error ("22023", "SR571", "Function rfc1808_parse_uri() got abnormally long URI as argument (%ld chars)",
  957. (long)(uri_len - 1) );
  958. else
  959. sqlr_new_error ("22023", "SR570", "Function rfc1808_parse_uri() got abnormally long URI as argument (%ld chars, '%.50s ... %50s')",
  960. (long)(uri_len - 1), uri, uri + uri_len - 51 );
  961. }
  962. if (DV_WIDE == uri_dtp)
  963. rfc1808_parse_wide_uri ((const wchar_t *)uri, &split);
  964. else
  965. rfc1808_parse_uri (uri, &split);
  966. if ((1 < BOX_ELEMENTS(args)) && bif_long_arg (qst, args, 1, "rfc1808_parse_uri"))
  967. {
  968. res = dk_alloc_box (DV_ARRAY_OF_POINTER, sizeof (rdf1808_split_t));
  969. memcpy (res, &split, 13 * sizeof (rdf1808_split_t));
  970. return res;
  971. }
  972. if (DV_WIDE == uri_dtp)
  973. {
  974. wchar_t *wideuri = (wchar_t *)uri;
  975. return list (6,
  976. box_wide_char_string ((caddr_t)(wideuri + split.schema_begin) , (split.schema_end - split.schema_begin) * sizeof (wchar_t) , DV_WIDE),
  977. box_wide_char_string ((caddr_t)(wideuri + split.netloc_begin) , (split.netloc_end - split.netloc_begin) * sizeof (wchar_t) , DV_WIDE),
  978. (((split.path_end == split.path_begin) && (0 < split.two_slashes)) ?
  979. box_wide_char_string ((caddr_t)(L"/"), sizeof (wchar_t), DV_WIDE) :
  980. box_wide_char_string ((caddr_t)(wideuri + split.path_begin) , (split.path_end - split.path_begin) * sizeof (wchar_t) , DV_WIDE) ),
  981. box_wide_char_string ((caddr_t)(wideuri + split.params_begin) , (split.params_end - split.params_begin) * sizeof (wchar_t) , DV_WIDE),
  982. box_wide_char_string ((caddr_t)(wideuri + split.query_begin) , (split.query_end - split.query_begin) * sizeof (wchar_t) , DV_WIDE),
  983. box_wide_char_string ((caddr_t)(wideuri + split.fragment_begin) , (split.fragment_end - split.fragment_begin) * sizeof (wchar_t), DV_WIDE) );
  984. }
  985. else
  986. {
  987. box_t (*box_x_nchars)(const char *buf, size_t len) =
  988. ((DV_UNAME == uri_dtp) ?
  989. box_dv_uname_nchars : box_dv_short_nchars );
  990. return list (6,
  991. box_x_nchars (uri + split.schema_begin , split.schema_end - split.schema_begin),
  992. box_x_nchars (uri + split.netloc_begin , split.netloc_end - split.netloc_begin),
  993. (((split.path_end == split.path_begin) && (0 < split.two_slashes)) ?
  994. box_x_nchars ("/", 1) :
  995. box_x_nchars (uri + split.path_begin , split.path_end - split.path_begin) ),
  996. box_x_nchars (uri + split.params_begin , split.params_end - split.params_begin),
  997. box_x_nchars (uri + split.query_begin , split.query_end - split.query_begin),
  998. box_x_nchars (uri + split.fragment_begin, split.fragment_end - split.fragment_begin) );
  999. }
  1000. }
  1001. /*! URI expander according RFC 1808 recommendations */
  1002. caddr_t
  1003. rfc1808_expand_uri (/*query_instance_t *qi,*/ ccaddr_t base_uri, ccaddr_t rel_uri,
  1004. ccaddr_t output_cs_name, int do_resolve_like_http_get,
  1005. ccaddr_t base_string_cs_name, /* Encoding used for base_uri IFF it is a narrow string, neither DV_UNAME nor WIDE */
  1006. ccaddr_t rel_string_cs_name, /* Encoding used for rel_uri IFF it is a narrow string, neither DV_UNAME nor WIDE */
  1007. caddr_t * err_ret )
  1008. {
  1009. caddr_t output_cs_upcase = output_cs_name ? sqlp_box_upcase (output_cs_name) : NULL;
  1010. const char *buffer_cs_upcase = (((NULL == output_cs_name) || strcmp (output_cs_name, "_WIDE_")) ? output_cs_name : "UTF-8");
  1011. const char *base_cs, *rel_cs;
  1012. int buf_len;
  1013. char *buf_tail = NULL, *buf_prev_tail = NULL;
  1014. dtp_t base_uri_dtp = DV_TYPE_OF (base_uri);
  1015. dtp_t rel_uri_dtp = DV_TYPE_OF (rel_uri);
  1016. caddr_t buffer = NULL, res = NULL;
  1017. int base_uri_is_temp = 0;
  1018. int rel_uri_is_temp = 0;
  1019. int buffer_is_temp = 0;
  1020. int res_is_new = 0;
  1021. rdf1808_split_t base_split, rel_split;
  1022. err_ret[0] = NULL;
  1023. switch (base_uri_dtp)
  1024. {
  1025. case DV_WIDE: base_cs = "_WIDE_"; break;
  1026. case DV_UNAME: base_cs = "UTF-8"; break;
  1027. case DV_STRING: base_cs = base_string_cs_name; break;
  1028. default: base_cs = buffer_cs_upcase; break;
  1029. }
  1030. switch (rel_uri_dtp)
  1031. {
  1032. case DV_WIDE: rel_cs = "_WIDE_"; break;
  1033. case DV_UNAME: rel_cs = "UTF-8"; break;
  1034. case DV_STRING: rel_cs = rel_string_cs_name; break;
  1035. default: rel_cs = buffer_cs_upcase; break;
  1036. }
  1037. if ((base_cs != buffer_cs_upcase) && !((NULL != base_cs) && (NULL != buffer_cs_upcase) && !strcmp (base_cs, buffer_cs_upcase)))
  1038. {
  1039. base_uri = charset_recode_from_named_to_named ((caddr_t)base_uri, base_cs, buffer_cs_upcase, &base_uri_is_temp, err_ret);
  1040. if (err_ret[0]) goto res_complete; /* see below */
  1041. }
  1042. if ((rel_cs != buffer_cs_upcase) && !((NULL != rel_cs) && (NULL != buffer_cs_upcase) && !strcmp (rel_cs, buffer_cs_upcase)))
  1043. {
  1044. rel_uri = charset_recode_from_named_to_named ((caddr_t)rel_uri, rel_cs, buffer_cs_upcase, &rel_uri_is_temp, err_ret);
  1045. if (err_ret[0]) goto res_complete; /* see below */
  1046. }
  1047. if ((NULL == base_uri) || ('\0' == base_uri[0]))
  1048. {
  1049. buffer = (caddr_t) rel_uri;
  1050. buffer_is_temp = rel_uri_is_temp;
  1051. rel_uri_is_temp = 0;
  1052. goto buffer_ready; /* see below */
  1053. }
  1054. if ((NULL == rel_uri) ||
  1055. (('\0' == rel_uri[0]) && (NULL == strchr (base_uri, '#')) && (NULL == strchr (base_uri, '?'))) )
  1056. {
  1057. buffer = (caddr_t) base_uri;
  1058. buffer_is_temp = base_uri_is_temp;
  1059. base_uri_is_temp = 0;
  1060. goto buffer_ready; /* see below */
  1061. }
  1062. rfc1808_parse_uri (rel_uri, &rel_split);
  1063. if (0 != rel_split.schema_end)
  1064. {
  1065. buffer = (caddr_t) rel_uri;
  1066. buffer_is_temp = rel_uri_is_temp;
  1067. rel_uri_is_temp = 0;
  1068. goto buffer_ready; /* see below */
  1069. }
  1070. rfc1808_parse_uri (base_uri, &base_split);
  1071. if ((0 == base_split.schema_end) && (0 != base_split.path_end) && do_resolve_like_http_get)
  1072. {
  1073. caddr_t fixed_base;
  1074. int prefix_len = ((0 != base_split.two_slashes) ? 5 : 7);
  1075. buf_len = base_split.fragment_end + prefix_len;
  1076. fixed_base = dk_alloc_box (base_split.fragment_end + prefix_len + 1, DV_STRING);
  1077. strcpy_box_ck (fixed_base, ((0 != base_split.two_slashes) ? "http:" : "http://"));
  1078. strcat_box_ck (fixed_base, base_uri);
  1079. buffer = rfc1808_expand_uri (/*qi,*/ fixed_base, rel_uri, buffer_cs_upcase, 0, buffer_cs_upcase, buffer_cs_upcase, err_ret);
  1080. if (NULL != err_ret[0])
  1081. {
  1082. dk_free_box (fixed_base);
  1083. goto res_complete;
  1084. }
  1085. if (buffer == fixed_base)
  1086. buffer_is_temp = 1;
  1087. else
  1088. {
  1089. dk_free_box (fixed_base);
  1090. if (buffer == rel_uri)
  1091. {
  1092. buffer_is_temp = rel_uri_is_temp;
  1093. rel_uri_is_temp = 0;
  1094. }
  1095. else
  1096. buffer_is_temp = 1;
  1097. }
  1098. goto buffer_ready;
  1099. }
  1100. buf_len = base_split.fragment_end + rel_split.fragment_end + 20;
  1101. buf_prev_tail = buf_tail = buffer = dk_alloc_box (buf_len, DV_STRING);
  1102. buffer_is_temp = 1;
  1103. if ((base_split.fragment_begin == base_split.fragment_end) && (base_split.query_end == base_split.fragment_begin-1))
  1104. {
  1105. if ((0 == rel_split.path_begin) && (rel_split.path_end == rel_split.fragment_end) && (NULL == strchr (rel_uri, '/')))
  1106. {
  1107. rel_split.path_end =
  1108. rel_split.params_begin = rel_split.params_end =
  1109. rel_split.query_begin = rel_split.query_end =
  1110. rel_split.fragment_begin = 0;
  1111. }
  1112. }
  1113. #define TAIL_APPEND_CUT(pref,fld,prefix,prefix_len,suffix,suffix_len) \
  1114. { \
  1115. int cut_len = pref##_split.fld##_end - pref##_split.fld##_begin; \
  1116. if (prefix_len) \
  1117. { \
  1118. memcpy (buf_tail, prefix, prefix_len); \
  1119. buf_tail += prefix_len; \
  1120. } \
  1121. memcpy (buf_tail, pref##_uri + pref##_split.fld##_begin, cut_len); \
  1122. buf_tail += cut_len; \
  1123. if (suffix_len) \
  1124. { \
  1125. memcpy (buf_tail, suffix, suffix_len); \
  1126. buf_tail += suffix_len; \
  1127. } \
  1128. buf_prev_tail = buf_tail; \
  1129. }
  1130. #ifndef NDEBUG
  1131. #define IF_NONEMPTY_THEN_TAIL_APPEND_CUT(pref,fld,prefix,prefix_len,suffix,suffix_len) \
  1132. if (pref##_split.fld##_end != pref##_split.fld##_begin) \
  1133. { \
  1134. if (pref##_split.fld##_end < pref##_split.fld##_begin) \
  1135. GPF_T1("Ill boundaries"); \
  1136. if ((buf_tail < buffer) || (buf_tail > buffer + box_length (buffer) - 5)) \
  1137. GPF_T1("Ill buf_tail"); \
  1138. if (buf_tail > buffer + buf_len) \
  1139. GPF_T1("Dangerously big buf_tail"); \
  1140. if (buf_tail + prefix_len + suffix_len + pref##_split.fld##_end - pref##_split.fld##_begin > buffer + buf_len) \
  1141. GPF_T1("Dangerously big buf_tail forecast"); \
  1142. TAIL_APPEND_CUT(pref,fld,prefix,prefix_len,suffix,suffix_len) \
  1143. }
  1144. #else
  1145. #define IF_NONEMPTY_THEN_TAIL_APPEND_CUT(pref,fld,prefix,prefix_len,suffix,suffix_len) \
  1146. if (pref##_split.fld##_end != pref##_split.fld##_begin) \
  1147. TAIL_APPEND_CUT(pref,fld,prefix,prefix_len,suffix,suffix_len)
  1148. #endif
  1149. IF_NONEMPTY_THEN_TAIL_APPEND_CUT(base,schema,"",0,":",1);
  1150. IF_NONEMPTY_THEN_TAIL_APPEND_CUT(rel,netloc,"//",2,"",0)
  1151. else
  1152. IF_NONEMPTY_THEN_TAIL_APPEND_CUT(base,netloc,"//",2,"",0)
  1153. if (0 == rel_split.path_end)
  1154. {
  1155. IF_NONEMPTY_THEN_TAIL_APPEND_CUT(base,path,"",0,"",0);
  1156. }
  1157. else if ((rel_split.path_begin != rel_split.path_end) && ('/' == rel_uri[rel_split.path_begin]))
  1158. {
  1159. IF_NONEMPTY_THEN_TAIL_APPEND_CUT(rel,path,"",0,"",0);
  1160. }
  1161. else if ((rel_split.path_begin == rel_split.path_end) && (0 != rel_split.path_end))
  1162. {
  1163. (buf_tail++)[0] = '/';
  1164. buf_prev_tail = buf_tail;
  1165. }
  1166. else
  1167. {
  1168. char *base_lastslash = (char *) (base_uri + base_split.path_end);
  1169. int base_beg_len, rel_len;
  1170. char *hit;
  1171. while (base_lastslash > base_uri + base_split.path_begin)
  1172. {
  1173. base_lastslash--;
  1174. if ('/' == base_lastslash[0])
  1175. break;
  1176. }
  1177. base_beg_len = base_lastslash - (base_uri + base_split.path_begin);
  1178. if (base_beg_len > 0)
  1179. {
  1180. memcpy (buf_tail, base_uri + base_split.path_begin, base_beg_len);
  1181. buf_tail += base_beg_len;
  1182. }
  1183. (buf_tail++)[0] = '/';
  1184. rel_len = rel_split.path_end - rel_split.path_begin;
  1185. memcpy (buf_tail, rel_uri + rel_split.path_begin, rel_len);
  1186. buf_tail += rel_len;
  1187. if (('.' == buf_tail[-1]) && (('/' == buf_tail[-2]) || (('.' == buf_tail[-2]) && ('/' == buf_tail[-3]))))
  1188. (buf_tail++)[0] = '/';
  1189. buf_tail[0] = '\0';
  1190. hit = strstr (buf_prev_tail, "/./");
  1191. while (NULL != hit)
  1192. {
  1193. char *shft = hit;
  1194. while ('\0' != (shft[0] = shft[2])) shft++;
  1195. buf_tail -= 2;
  1196. hit = strstr (hit, "/./");
  1197. }
  1198. hit = strstr (buf_prev_tail, "/../");
  1199. while (NULL != hit)
  1200. {
  1201. char *crop_end = hit+3;
  1202. char *crop_begin;
  1203. if (hit == buf_prev_tail)
  1204. crop_begin = buf_prev_tail;
  1205. else
  1206. {
  1207. crop_begin = hit-1;
  1208. while ('/' != crop_begin[0] && crop_begin > buf_prev_tail) crop_begin--;
  1209. }
  1210. hit = crop_begin;
  1211. while ('\0' != (crop_begin[0] = crop_end[0])) { crop_begin++; crop_end++; }
  1212. buf_tail -= (crop_end - crop_begin);
  1213. hit = strstr (hit, "/../");
  1214. }
  1215. }
  1216. IF_NONEMPTY_THEN_TAIL_APPEND_CUT(rel,params,";",1,"",0)
  1217. else if ((rel_split.schema_begin == rel_split.schema_end) &&
  1218. (rel_split.netloc_begin == rel_split.netloc_end) &&
  1219. (rel_split.path_begin == rel_split.path_end) )
  1220. {
  1221. IF_NONEMPTY_THEN_TAIL_APPEND_CUT(base,params,";",1,"",0);
  1222. }
  1223. IF_NONEMPTY_THEN_TAIL_APPEND_CUT(rel,query,"?",1,"",0)
  1224. else if ((rel_split.schema_begin == rel_split.schema_end) &&
  1225. (rel_split.netloc_begin == rel_split.netloc_end) &&
  1226. (rel_split.path_begin == rel_split.path_end) &&
  1227. (rel_split.params_begin == rel_split.params_end) )
  1228. {
  1229. IF_NONEMPTY_THEN_TAIL_APPEND_CUT(base,query,"?",1,"",0);
  1230. }
  1231. if (rel_split.fragment_end != rel_split.query_end)
  1232. { /* This is an exception because empty "#" is also meaningful */
  1233. TAIL_APPEND_CUT(rel,fragment,"#",1,"",0);
  1234. }
  1235. buf_tail[0] = '\0';
  1236. buffer_ready:
  1237. if (NULL == buf_tail)
  1238. {
  1239. for (buf_tail = buffer; '\0' != buf_tail[0]; buf_tail++);
  1240. }
  1241. if ((buffer_cs_upcase != output_cs_upcase) &&
  1242. ((NULL == buffer_cs_upcase) || (NULL == output_cs_upcase) || strcmp(buffer_cs_upcase, output_cs_upcase)) )
  1243. {
  1244. caddr_t boxed_buffer = box_dv_short_nchars (buffer, buf_tail - buffer);
  1245. res = charset_recode_from_named_to_named (boxed_buffer, buffer_cs_upcase, output_cs_upcase, &res_is_new, err_ret);
  1246. if (res_is_new)
  1247. dk_free_box (boxed_buffer);
  1248. else
  1249. res_is_new = 1;
  1250. if (err_ret[0])
  1251. goto res_complete; /* see below */
  1252. }
  1253. else
  1254. {
  1255. if (NULL != buf_prev_tail)
  1256. {
  1257. res = box_dv_short_nchars (buffer, buf_tail - buffer);
  1258. res_is_new = 1;
  1259. }
  1260. else
  1261. {
  1262. res = buffer;
  1263. res_is_new = buffer_is_temp;
  1264. buffer_is_temp = 0;
  1265. }
  1266. }
  1267. res_complete:
  1268. if (!res_is_new)
  1269. res = box_copy (res);
  1270. dk_free_box (output_cs_upcase);
  1271. if (base_uri_is_temp)
  1272. dk_free_box ((caddr_t) base_uri);
  1273. if (rel_uri_is_temp)
  1274. dk_free_box ((caddr_t) rel_uri);
  1275. if (buffer_is_temp)
  1276. dk_free_box (buffer);
  1277. return res;
  1278. }
  1279. /*! URI expander according RFC 1808 recommendations */
  1280. static caddr_t
  1281. bif_rfc1808_expand_uri (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args)
  1282. {
  1283. caddr_t base_uri = bif_string_or_uname_or_wide_or_null_arg (qst, args, 0, "rfc1808_expand_uri");
  1284. caddr_t rel_uri = bif_string_or_uname_or_wide_or_null_arg (qst, args, 1, "rfc1808_expand_uri");
  1285. ccaddr_t output_cs_name = ((2 < BOX_ELEMENTS(args)) ? bif_string_or_null_arg (qst, args, 2, "rfc1808_expand_uri") : NULL);
  1286. int resolve_like_http_get = ((3 < BOX_ELEMENTS(args)) ? bif_long_arg (qst, args, 3, "rfc1808_expand_uri") : 0);
  1287. ccaddr_t base_cs_name = ((4 < BOX_ELEMENTS(args)) ? bif_string_or_null_arg (qst, args, 4, "rfc1808_expand_uri") : NULL);
  1288. ccaddr_t rel_cs_name = ((5 < BOX_ELEMENTS(args)) ? bif_string_or_null_arg (qst, args, 5, "rfc1808_expand_uri") : NULL);
  1289. caddr_t err = NULL;
  1290. caddr_t res = rfc1808_expand_uri (/*(query_instance_t *)qst,*/ base_uri, rel_uri, output_cs_name, resolve_like_http_get, base_cs_name, rel_cs_name, &err);
  1291. int res_is_new = ((res != base_uri) && (res != rel_uri));
  1292. if (NULL != err)
  1293. {
  1294. if (res_is_new)
  1295. dk_free_box (res);
  1296. sqlr_resignal (err);
  1297. }
  1298. if (res_is_new)
  1299. return res;
  1300. return box_copy (res);
  1301. }
  1302. static caddr_t
  1303. bif_patch_restricted_xml_chars (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args)
  1304. {
  1305. #define o 0
  1306. static char restricted_xml_chars[0x80] = {
  1307. /*0 1 2 3 4 5 6 7 8 9 A B C D E F */
  1308. 3,3,3,3,3,3,3,3,3,5,5,3,3,5,3,3,
  1309. /*0 1 2 3 4 5 6 7 8 9 A B C D E F */
  1310. 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
  1311. /* ! " # $ % & ' ( ) * + , - . / */
  1312. o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,
  1313. /*0 1 2 3 4 5 6 7 8 9 : ; < = > ? */
  1314. o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,
  1315. /*@ A B C D E F G H I J K L M N O */
  1316. o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,
  1317. /*P Q R S T U V W X Y Z [ \ ] ^ _ */
  1318. o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,
  1319. /*` a b c d e f g h i j k l m n o */
  1320. o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,
  1321. /*p q r s t u v w x y z { | } ~ */
  1322. o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o };
  1323. #undef o
  1324. caddr_t src = bif_string_or_uname_or_wide_or_null_arg (qst, args, 0, "patch_restricted_xml_chars");
  1325. int add_percents = bif_long_arg (qst, args, 1, "patch_restricted_xml_chars");
  1326. dtp_t src_dtp;
  1327. int src_box_length;
  1328. int weird_char_ctr = 0;
  1329. caddr_t dest_to_swap;
  1330. if (NULL == src)
  1331. return NULL;
  1332. src_dtp = DV_TYPE_OF (src);
  1333. src_box_length = box_length (src);
  1334. if (!SSL_IS_REFERENCEABLE (args[0]))
  1335. sqlr_new_error ("22023", "SR642", "The first argument of patch_restricted_xml_chars() should be a variable, not a constant or an expression");
  1336. if (DV_WIDE == src_dtp)
  1337. {
  1338. wchar_t *tail = (wchar_t *)src;
  1339. wchar_t *end = ((wchar_t *)(src + src_box_length)) - 1;
  1340. wchar_t *dest, *dest_tail;
  1341. if (add_percents)
  1342. {
  1343. for (;tail < end; tail++)
  1344. {
  1345. if (tail[0] & ~0x7F)
  1346. continue;
  1347. if (restricted_xml_chars[tail[0]])
  1348. weird_char_ctr++;
  1349. }
  1350. if (0 == weird_char_ctr)
  1351. return NULL;
  1352. dest = dest_tail = dk_alloc_box ((sizeof (wchar_t) * 2 * weird_char_ctr) + src_box_length, src_dtp);
  1353. dest_to_swap = (caddr_t) dest;
  1354. for (tail = (wchar_t *)src; tail < end; tail++)
  1355. {
  1356. if ((tail[0] & ~0x7F) || (0 == restricted_xml_chars[(unsigned)(tail[0])]))
  1357. (dest_tail++)[0] = tail[0];
  1358. else
  1359. {
  1360. (dest_tail++)[0] = '%';
  1361. (dest_tail++)[0] = "0123456789ABCDEF"[(tail[0] >> 4) & 0xf];
  1362. (dest_tail++)[0] = "0123456789ABCDEF"[tail[0] & 0xf];
  1363. }
  1364. }
  1365. dest_tail[0] = 0;
  1366. }
  1367. else
  1368. {
  1369. for (;tail < end; tail++)
  1370. {
  1371. if (tail[0] & ~0x7F)
  1372. continue;
  1373. if (restricted_xml_chars[tail[0]] & 2)
  1374. tail[0] = ' ';
  1375. }
  1376. return NULL;
  1377. }
  1378. }
  1379. else
  1380. {
  1381. char *tail = src;
  1382. char *end = src + src_box_length - 1;
  1383. char *dest, *dest_tail;
  1384. int dest_box_len;
  1385. if (add_percents)
  1386. {
  1387. for (;tail < end; tail++)
  1388. {
  1389. if (tail[0] & ~0x7F)
  1390. continue;
  1391. if (restricted_xml_chars[(unsigned)(tail[0])])
  1392. weird_char_ctr++;
  1393. }
  1394. if (0 == weird_char_ctr)
  1395. return NULL;
  1396. dest_box_len = (2 * weird_char_ctr) + src_box_length;
  1397. dest_to_swap = dest = dest_tail = dk_alloc_box (dest_box_len, (DV_UNAME == src_dtp) ? DV_STRING : src_dtp);
  1398. for (tail = src; tail < end; tail++)
  1399. {
  1400. if ((tail[0] & ~0x7F) || (0 == restricted_xml_chars[(unsigned)(tail[0])]))
  1401. (dest_tail++)[0] = tail[0];
  1402. else
  1403. {
  1404. (dest_tail++)[0] = '%';
  1405. (dest_tail++)[0] = "0123456789ABCDEF"[(tail[0] >> 4) & 0xf];
  1406. (dest_tail++)[0] = "0123456789ABCDEF"[tail[0] & 0xf];
  1407. }
  1408. }
  1409. dest_tail[0] = 0;
  1410. if (DV_UNAME == src_dtp)
  1411. {
  1412. dest_to_swap = box_dv_uname_nchars (dest, dest_box_len - 1);
  1413. dk_free_tree (dest);
  1414. }
  1415. }
  1416. else
  1417. {
  1418. if (DV_UNAME == src_dtp)
  1419. {
  1420. for (;tail < end; tail++)
  1421. {
  1422. if (tail[0] & ~0x7F)
  1423. continue;
  1424. if (restricted_xml_chars[(unsigned)(tail[0])])
  1425. weird_char_ctr++;
  1426. }
  1427. if (0 == weird_char_ctr)
  1428. return NULL;
  1429. tail = src = box_dv_short_nchars (src, src_box_length - 1);
  1430. end = src + src_box_length - 1;
  1431. }
  1432. for (;tail < end; tail++)
  1433. {
  1434. if (tail[0] & ~0x7F)
  1435. continue;
  1436. if (restricted_xml_chars[(unsigned)(tail[0])] & 2)
  1437. tail[0] = ' ';
  1438. }
  1439. if (DV_UNAME == src_dtp)
  1440. {
  1441. dest_to_swap = box_dv_uname_nchars (src, src_box_length - 1);
  1442. dk_free_tree (src);
  1443. }
  1444. else
  1445. return NULL;
  1446. }
  1447. }
  1448. qst_swap (qst, args[0], &dest_to_swap);
  1449. dk_free_tree (dest_to_swap);
  1450. return NULL;
  1451. }
  1452. static const char *cl_sequence_set_text =
  1453. " create procedure cl_sequence_set (in _name varchar, in _count int, in _mode int)\n"
  1454. "{\n"
  1455. "if (sys_stat (\'cl_master_host\') = sys_stat (\'cl_this_host\'))\n"
  1456. "{\n"
  1457. "__sequence_set (\'__…

Large files files are truncated, but you can click here to view the full file