dnedit.c 12 KB

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