dnedit.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. /** --- BEGIN COPYRIGHT BLOCK ---
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. --- END COPYRIGHT BLOCK --- */
  38. /*
  39. * Generate a DN edit screen.
  40. */
  41. #include "dsgw.h"
  42. #include "dbtdsgw.h"
  43. #ifdef DSGW_DEBUG
  44. int main(int argc, char *argv[], char *env[] )
  45. #else /* DSGW_DEBUG */
  46. int main(int argc, char *argv[] )
  47. #endif /* DSGW_DEBUG */
  48. {
  49. char *tmplname, *attrname, *attrdesc, *qs, *dn, *edn;
  50. char *attrs[ 2 ], **attrvals, **xdn, *avedn, *js0, *js1;
  51. LDAP *ld;
  52. LDAPMessage *msgp;
  53. int i;
  54. /*
  55. * The URL used to invoke this CGI looks like:
  56. * http://host/dnedit?CONTEXT=context&TEMPLATE=tmplname&DN=dn&ATTR=attrname&DESC=description
  57. *
  58. * where:
  59. * "tmplname" is the name of the HTML template to render
  60. * "attrname" is the name of a dn-valued attribute to display
  61. * "description" is a textual description of the attribute
  62. *
  63. * Note: original form http://host/dnedit/dn?... is supported
  64. * for keeping backward compatibility.
  65. */
  66. tmplname = attrname = attrdesc = dn = edn = NULL;
  67. if (( qs = getenv( "QUERY_STRING" )) != NULL && *qs != '\0' ) {
  68. char *p, *q;
  69. q = qs + strlen( qs );
  70. while ((( p = strrchr( qs, '&' )) != NULL ) || ( q - qs > 1 )) {
  71. if ( p )
  72. *p++ = '\0';
  73. else
  74. p = qs;
  75. q = p;
  76. if ( p != NULL && strncasecmp( p, "dn=", 3 ) == 0 ) {
  77. edn = dsgw_ch_strdup( p + 3 );
  78. dn = dsgw_ch_strdup( p + 3 );
  79. dsgw_form_unescape( dn );
  80. } else if ( p != NULL && strncasecmp( p, "template=", 9 ) == 0 ) {
  81. tmplname = dsgw_ch_strdup( p + 9 );
  82. dsgw_form_unescape( tmplname );
  83. } else if ( p != NULL && strncasecmp( p, "attr=", 5 ) == 0 ) {
  84. attrname = dsgw_ch_strdup( p + 5 );
  85. dsgw_form_unescape( attrname );
  86. } else if ( p != NULL && strncasecmp( p, "desc=", 5 ) == 0 ) {
  87. attrdesc = dsgw_ch_strdup( p + 5 );
  88. /* Don't bother unescaping it;
  89. we're only going to put it back in another URL. */
  90. } else if ( p != NULL && strncasecmp( p, "context=", 8 ) == 0) {
  91. context = dsgw_ch_strdup( p + 8 );
  92. dsgw_form_unescape( context );
  93. }
  94. }
  95. if ( !tmplname )
  96. dsgw_error( DSGW_ERR_MISSINGINPUT, "template", DSGW_ERROPT_EXIT,
  97. 0, NULL );
  98. if ( !attrname )
  99. dsgw_error( DSGW_ERR_MISSINGINPUT, "attr", DSGW_ERROPT_EXIT,
  100. 0, NULL );
  101. if ( !attrdesc )
  102. dsgw_error( DSGW_ERR_MISSINGINPUT, "desc", DSGW_ERROPT_EXIT,
  103. 0, NULL );
  104. } else {
  105. dsgw_error( DSGW_ERR_MISSINGINPUT, NULL, DSGW_ERROPT_EXIT, 0, NULL );
  106. }
  107. if ( dn == NULL ) {
  108. dsgw_error( DSGW_ERR_MISSINGINPUT, "dn", DSGW_ERROPT_EXIT, 0, NULL );
  109. }
  110. (void)dsgw_init( argc, argv, DSGW_METHOD_GET );
  111. #ifdef DSGW_DEBUG
  112. dsgw_logstringarray( "env", env );
  113. #endif
  114. dsgw_send_header();
  115. /* Get the current attribute values */
  116. (void) dsgw_init_ldap( &ld, NULL, 0, 0);
  117. attrs[ 0 ] = attrname;
  118. attrs[ 1 ] = NULL;
  119. if (ldap_search_s( ld, dn, LDAP_SCOPE_BASE, "(objectclass=*)", attrs, 0,
  120. &msgp ) != LDAP_SUCCESS ) {
  121. dsgw_error( DSGW_ERR_ENTRY_NOT_FOUND, dn, DSGW_ERROPT_EXIT, 0, NULL );
  122. }
  123. attrvals = ldap_get_values( ld, msgp, attrname );
  124. /* Send the top-level document HTML */
  125. dsgw_emits( "<HTML>\n"
  126. "<SCRIPT LANGUAGE=\"JavaScript\">\n" );
  127. dsgw_emitf( "var emptyFrame = '';\n" );
  128. dsgw_emitf( "var attrname = '%s';\n", attrname );
  129. /*
  130. * fix for 333110: dn should be escaped to be used in saveChanges/domodify
  131. */
  132. dsgw_emitf( "var dn = '%s';\n", edn );
  133. dsgw_emitf( "var needToSaveChanges = false;\n" );
  134. dsgw_emitf( "var completion_url = '%s?dn=%s&context=%s';\n",
  135. dsgw_getvp( DSGW_CGINUM_EDIT ), edn, context);
  136. dsgw_emitf(
  137. /*
  138. * This needs to output \\\' so that when JavaScript writeln's
  139. * this string, it writes \' to the output document.
  140. *
  141. * I'm really, really sorry about this - ggood.
  142. *
  143. * Moral of the story - next time someone asks you to write C code which
  144. * writes JavaScript code which writes JavaScript code... just say "no".
  145. */
  146. "var comp_js = 'var cu=\\\\\\\'%s?context=%s&dn=%s\\\\\\\'; this.document.location.href=cu;'\n",
  147. dsgw_getvp( DSGW_CGINUM_EDIT ), context, edn );
  148. dsgw_emits("var dnlist = new Array;\n" );
  149. for ( i = 0; attrvals && attrvals[ i ] != NULL; i++ ) {
  150. xdn = ldap_explode_dn( attrvals[ i ], 1 );
  151. avedn = dsgw_strdup_escaped( attrvals[ i ]);
  152. dsgw_emitf( "dnlist[%d] = new Object\n", i );
  153. dsgw_emitf( "dnlist[%d].edn = '%s';\n", i, avedn );
  154. js0 = dsgw_escape_quotes( xdn[ 0 ] );
  155. if ( xdn[1] != NULL ) {
  156. js1 = dsgw_escape_quotes( xdn[ 1 ] );
  157. dsgw_emitf( "dnlist[%d].rdn = '%s, %s';\n", i, js0, js1 );
  158. free( js1 );
  159. } else {
  160. dsgw_emitf( "dnlist[%d].rdn = '%s';\n", i, js0 );
  161. }
  162. free( js0 );
  163. dsgw_emitf( "dnlist[%d].selected = false;\n", i );
  164. free( avedn );
  165. ldap_value_free( xdn );
  166. }
  167. dsgw_emitf( "dnlist.count = %d;\n", i );
  168. dsgw_emits(
  169. "var changesMade = 0;\n"
  170. "\n"
  171. /*
  172. * JavaScript function processSearch
  173. */
  174. "function processSearch(f)\n"
  175. "{\n"
  176. " var sel = f.type;\n"
  177. " var selvalue = sel.options[sel.selectedIndex].value;\n"
  178. " var lt = f.listtemplate;\n"
  179. " if ( f.searchstring.value.length == 0 ) {\n");
  180. dsgw_emit_alert( "controlFrame", NULL, XP_GetClientStr( DBT_noSearchStringWasProvidedPleaseT_ ));
  181. dsgw_emits(
  182. " return false;\n"
  183. " }\n"
  184. " lt.value = 'fa-' + selvalue;\n");
  185. dsgw_emitf(
  186. " f.action = ");
  187. dsgw_quote_emitf( QUOTATION_JAVASCRIPT, "%s?context=%s",
  188. dsgw_getvp( DSGW_CGINUM_DOSEARCH ), context);
  189. dsgw_emits( ";\n"
  190. " f.searchstring.select();\n"
  191. " f.searchstring.focus();\n"
  192. " return true;\n"
  193. "}\n"
  194. "\n"
  195. /*
  196. * JavaScript function removeItem
  197. */
  198. "function removeItem(itemno, refresh)\n"
  199. "{\n"
  200. " var extantDNs = dnlist;\n"
  201. " var extantDNsCount = dnlist.count;\n"
  202. " \n"
  203. " // Get rid of element in slot dup\n"
  204. " for (k = itemno; k < extantDNsCount - 1; k++) {\n"
  205. " extantDNs[k] = extantDNs[k+1];\n"
  206. " }\n"
  207. " dnlist.count--;\n"
  208. " if ( refresh ) genOutputFrame(outputFrame, dnlist);\n"
  209. " this.changesMade = 1;\n"
  210. "}\n"
  211. "\n"
  212. /*
  213. * JavaScript function dnarrcomp
  214. */
  215. "function dnarrcomp(a,b)\n"
  216. "{\n"
  217. " return(a.edn.toLowerCase() > b.edn.toLowerCase());\n"
  218. "}\n"
  219. " \n"
  220. #ifdef NAV30_SORT_NO_LONGER_COREDUMPS
  221. /*
  222. * JavaScript function sortEntries
  223. */
  224. "function sortEntries()\n"
  225. "{\n"
  226. " var extantDNs = dnlist;\n"
  227. " extantDNs.sort(dnarrcomp);\n"
  228. " genOutputFrame(outputFrame, dnlist);\n"
  229. "}\n"
  230. "\n"
  231. #endif /* NAV30_SORT_NO_LONGER_COREDUMPS */
  232. /*
  233. * JavaScript function genOutputFrame
  234. */
  235. "function genOutputFrame(oframe, dnl)\n"
  236. "{\n"
  237. " var d = oframe.document;\n"
  238. "\n"
  239. " d.open('text/html');\n"
  240. " d.writeln('<HTML>');\n" );
  241. dsgw_emitf(
  242. " d.writeln('<BODY %s>');\n", dsgw_html_body_colors );
  243. dsgw_emits(
  244. " d.writeln(");
  245. dsgw_quotation_begin (QUOTATION_JAVASCRIPT);
  246. dsgw_form_begin (NULL, NULL);
  247. dsgw_quotation_end();
  248. dsgw_emits( ");\n");
  249. dsgw_emits(
  250. " d.writeln('<CENTER>');\n"
  251. " if (dnl.count == 0) {\n" );
  252. dsgw_emits( " d.write(" );
  253. dsgw_quote_emits (QUOTATION_JAVASCRIPT, XP_GetClientStr (DBT_noNameInTheList_));
  254. dsgw_emits( ");\n" );
  255. dsgw_emits( " } else if (dnl.count == 1) {\n" );
  256. dsgw_emits( " d.write(" );
  257. dsgw_quote_emits (QUOTATION_JAVASCRIPT, XP_GetClientStr (DBT_oneNameInTheList_));
  258. dsgw_emits( ");\n" );
  259. dsgw_emits( " } else {\n" );
  260. dsgw_emits( " d.write('");
  261. dsgw_emitf( XP_GetClientStr( DBT_someNamesInTheList_ ), "' + dnl.count + '" );
  262. dsgw_emits( "');\n" );
  263. dsgw_emits(
  264. " }\n"
  265. #ifdef NAV30_SORT_NO_LONGER_COREDUMPS
  266. " d.writeln('</FONT>\\n')\n"
  267. " d.writeln('<INPUT TYPE=\"button\" VALUE=\"Sort\" onClick=\"parent.sortEntries();\"></CENTER>\\n');\n"
  268. #else
  269. " d.writeln('</FONT></CENTER>\\n');\n"
  270. #endif
  271. " if (dnl.count > 0) {\n"
  272. " d.write('<PRE><B>');\n" );
  273. dsgw_emitf(
  274. " d.write('%s</B><HR>');\n",
  275. XP_GetClientStr( DBT_RemoveFromList_ ));
  276. dsgw_emits(
  277. " for (i = 0; i < dnl.count; i++) {\n"
  278. " d.write('<INPUT TYPE=CHECKBOX onClick=\"parent."
  279. "removeItem(' + i + ', true);\">');\n"
  280. " d.write(' ');\n"
  281. " d.write(dnl[i].rdn + '\\n');\n"
  282. " }\n"
  283. " d.writeln('</PRE></FORM><HR>');\n"
  284. " }\n"
  285. " d.writeln('</BODY>');\n"
  286. " d.close();\n"
  287. "}\n"
  288. "\n"
  289. /*
  290. * JavaScript function mergeLists
  291. */
  292. "function mergeLists(mode, old, newl)\n"
  293. "{\n"
  294. " var dup = -1;\n"
  295. " var i, j, k;\n"
  296. " \n"
  297. " for (i = 0; i < newl.count; i++) {\n"
  298. " // Check for a duplicate\n"
  299. " for (j = 0; j < old.count; j++) {\n"
  300. " dup = -1;\n"
  301. " if (newl[i].edn.toLowerCase() == "
  302. "old[j].edn.toLowerCase()) {\n"
  303. " // Duplicate - skip\n"
  304. " dup = j;\n"
  305. " break;\n"
  306. " }\n"
  307. " }\n"
  308. " if ((dup == -1) && (mode == \"add\")) {\n"
  309. " // add new dn at end of array\n"
  310. " old[old.count] = new Array;\n"
  311. " old[old.count].edn = newl[i].edn;\n"
  312. " old[old.count].rdn = newl[i].rdn;\n"
  313. " old[old.count].sn = newl[i].sn;\n"
  314. " old[old.count].selected = false;\n"
  315. " old.count++;\n"
  316. " } else if (dup != -1 && mode == \"remove\") {\n"
  317. " removeItem(dup,false);\n"
  318. " }\n"
  319. " }\n"
  320. "}\n"
  321. "\n"
  322. /*
  323. * JavaScript function updateList
  324. */
  325. "function updateList(mode, old_list, new_list, outframe)\n"
  326. "{\n"
  327. " mergeLists(mode, old_list, new_list);\n"
  328. " genOutputFrame(outframe, old_list);\n"
  329. " this.changesMade = 1;\n"
  330. "}\n"
  331. "\n"
  332. /*
  333. * JavaScript function cancel
  334. */
  335. "function cancel ()\n"
  336. "{\n"
  337. " if (changesMade == 0) {\n"
  338. " document.location = completion_url;\n"
  339. " } else {\n");
  340. dsgw_emit_confirm ("controlFrame",
  341. "opener.document.location.href = opener.completion_url;",
  342. NULL /* no */,
  343. XP_GetClientStr(DBT_discardChangesWindow_), 1,
  344. XP_GetClientStr(DBT_discardChanges_));
  345. dsgw_emits (
  346. " }\n"
  347. "}\n"
  348. "\n"
  349. /*
  350. * JavaScript function saveChanges
  351. */
  352. "function saveChanges()\n"
  353. "{\n"
  354. " var i, j;\n"
  355. " needToSaveChanges = true;\n"
  356. " of = self.stagingFrame.document;\n"
  357. " of.open('text/html');\n" );
  358. dsgw_emitf(
  359. " of.write('<BODY onLoad=\"if ( parent.needToSaveChanges ) { parent.needToSaveChanges = false; document.stagingForm.submit() }\">');\n" );
  360. dsgw_emits(
  361. " of.write('");
  362. dsgw_form_begin ("stagingForm",
  363. "action=\"%s\" METHOD=\"POST\" TARGET=\"_parent\"",
  364. dsgw_getvp( DSGW_CGINUM_DOMODIFY ));
  365. dsgw_emits("\\n');\n");
  366. dsgw_emits(
  367. " if (self.dnlist.count < 1) {\n"
  368. " of.write('<INPUT TYPE=\"hidden\" NAME=\"replace_');\n"
  369. " of.write(self.attrname);\n"
  370. " of.write('\" VALUE=\"\">\\n');\n"
  371. " } else {\n"
  372. " for (j = 0; j < self.dnlist.count; j++) {\n"
  373. " of.write('<INPUT TYPE=\"hidden\" NAME=\"replace_');\n"
  374. " of.write(self.attrname);\n"
  375. " of.write('\" VALUE=\"');\n"
  376. " of.write(unescape(self.dnlist[j].edn));\n"
  377. " of.write('\">\\n');\n"
  378. " }\n"
  379. " }\n"
  380. " of.writeln('<INPUT TYPE=\"hidden\" NAME=\"changetype\" "
  381. "VALUE=\"modify\">\\n');\n"
  382. " of.writeln('<INPUT TYPE=\"hidden\" NAME=\"completion_javascript\" "
  383. "VALUE=\"' + comp_js + '\">');\n"
  384. " of.writeln('<INPUT TYPE=\"hidden\" NAME=\"dn\" VALUE=\"' "
  385. "+ self.dn + '\"\\n');\n"
  386. " of.writeln('<INPUT TYPE=\"hidden\" NAME=\"context\" "
  387. "VALUE=\"");
  388. dsgw_emits(context);
  389. dsgw_emits("\">\\n');\n"
  390. " of.writeln('</FORM>\\n');\n"
  391. " of.close();\n"
  392. "}\n"
  393. "</SCRIPT>\n"
  394. "\n"
  395. "<FRAMESET BORDER=1 FRAMEBORDER=1 ROWS=230,*,0,0 "
  396. "SCROLLING=\"NO\" NORESIZE onLoad=\"genOutputFrame"
  397. "(this.outputFrame, this.dnlist);\">\n" );
  398. dsgw_emitf( " <FRAME SRC=\"%s?%s&dn=%s&context=%s&DNATTR=%s&"
  399. "DNDESC=%s\" NAME=\"controlFrame\" SCROLLING=\"no\">\n",
  400. dsgw_getvp( DSGW_CGINUM_EDIT ), tmplname, edn, context, attrname,
  401. attrdesc );
  402. dsgw_emitf( " <FRAME SRC=\"javascript:parent.emptyFrame\" "
  403. "NAME=\"outputFrame\">\n"
  404. " <FRAME SRC=\"javascript:parent.emptyFrame\" "
  405. "NAME=\"stagingFrame\">\n"
  406. "</FRAMESET>\n"
  407. "</HTML>\n" );
  408. return 0;
  409. }