newentry.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  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. * newentry.c -- CGI program to generate newentry form -- HTTP gateway
  40. */
  41. #include "dsgw.h"
  42. #include "dbtdsgw.h"
  43. static void emit_file(char* filename, dsgwnewtype* entType);
  44. #if 0 /* unused */
  45. static void
  46. unquote_emits(char* s)
  47. {
  48. dsgw_quotation_end();
  49. dsgw_emits (s);
  50. dsgw_quotation_begin (QUOTATION_JAVASCRIPT_MULTILINE);
  51. }
  52. static void
  53. quote_emit_file(char* filename)
  54. {
  55. dsgw_quotation_begin (QUOTATION_JAVASCRIPT_MULTILINE);
  56. emit_file (filename, NULL);
  57. dsgw_quotation_end();
  58. }
  59. #endif
  60. static void
  61. emit_file (char* filename, dsgwnewtype* entType)
  62. {
  63. auto FILE* html = dsgw_open_html_file( filename, DSGW_ERROPT_EXIT );
  64. auto char line[ BIG_LINE ];
  65. auto int argc;
  66. auto char **argv;
  67. char *deleteme = NULL;
  68. while ( dsgw_next_html_line( html, line )) {
  69. if ( dsgw_parse_line( line, &argc, &argv, 0, dsgw_simple_cond_is_true, NULL )) {
  70. if ( dsgw_directive_is( line, DRCT_HEAD )) {
  71. dsgw_head_begin();
  72. dsgw_emits ("\n");
  73. } else if ( dsgw_directive_is( line, "DS_NEWENTRY_SCRIPT" )) {
  74. dsgw_emits ("<SCRIPT LANGUAGE=\"JavaScript\">\n"
  75. "<!-- Hide from non-JavaScript-capable browsers\n"
  76. "var selectedType = -1;\n"
  77. "\n"
  78. "function typeChange(selectType)\n"
  79. "{\n"
  80. " var newType = selectType.selectedIndex;\n"
  81. " if ( newType != selectedType ) {\n"
  82. " selectedType = newType;\n"
  83. " newentryNameFrame.location.href = '"
  84. DSGW_URLPREFIX_CGI_HTTP
  85. "newentry?context=");
  86. dsgw_emits(context);
  87. dsgw_emits( "&file=name&etype=' +\n"
  88. " escape (selectType.options[newType].value);\n"
  89. " }\n"
  90. "}\n"
  91. "\n"
  92. "var previousLocation = '';\n"
  93. "var locationChangedRecently = false;\n"
  94. "\n"
  95. "function locationChange(nameForm)\n"
  96. "{\n"
  97. " var location = nameForm.selectLocation.options[nameForm.selectLocation.selectedIndex].value;\n"
  98. " if ( location != previousLocation ) {\n"
  99. " if ( nameForm.dnsuffix != null ) {\n"
  100. " if ( location != '' ) {\n"
  101. " nameForm.dnsuffix.blur();\n"
  102. " nameForm.dnsuffix.value = '';\n"
  103. " // In Navigator for Macintosh, the preceding code\n"
  104. " // causes a subsequent focus event in dnsuffix.\n"
  105. " // Prevent dnsuffixFocus from acting on it:\n"
  106. " locationChangedRecently = true;\n"
  107. " setTimeout ('locationChangedRecently = false', 100);\n"
  108. " } else {\n"
  109. " nameForm.dnsuffix.value = previousLocation;\n"
  110. " nameForm.dnsuffix.focus();\n"
  111. " nameForm.dnsuffix.select();\n"
  112. " }\n"
  113. " }\n"
  114. " previousLocation = location;\n"
  115. " }\n"
  116. "}\n"
  117. "\n"
  118. "function dnsuffixFocus(nameForm)\n"
  119. "{\n"
  120. " var location = nameForm.selectLocation.options[nameForm.selectLocation.selectedIndex].value;\n"
  121. " if ( location != '' && ( ! locationChangedRecently )) {\n"
  122. " if ( nameForm.dnsuffix.value == '' ) {\n"
  123. " nameForm.dnsuffix.value = location;\n"
  124. " setTimeout ('newentryNameFrame.document.nameForm.dnsuffix.select()', 75);\n"
  125. " // This is not done immediately, to avoid interference from mouse-up.\n"
  126. " }\n"
  127. " for ( i = 0; i < nameForm.selectLocation.length; i++ ) {\n"
  128. " if ( nameForm.selectLocation.options[i].value == '' ) {\n"
  129. " previousLocation = '';\n"
  130. " nameForm.selectLocation.selectedIndex = i;\n"
  131. " break;\n"
  132. " }\n"
  133. " }\n"
  134. " }\n"
  135. "}\n"
  136. "\n"
  137. "function submitNameForm(nameForm)\n"
  138. "{\n"
  139. " if ( nameForm.entryname.value == '' ) {\n");
  140. deleteme = XP_GetClientStr (DBT_enterNameForNewEntry_);
  141. dsgw_emit_alert ("newentryNameFrame", "width=400,height=130,resizable",
  142. XP_GetClientStr (DBT_enterNameForNewEntry_));
  143. dsgw_emits (" return false;\n"
  144. " } else if ( nameForm.selectLocation.options[nameForm.selectLocation.selectedIndex].value == '' &&\n"
  145. " ( nameForm.dnsuffix == null ||\n"
  146. " nameForm.dnsuffix.value == '' )) {\n");
  147. dsgw_emit_alert ("newentryNameFrame", "width=400,height=130,resizable",
  148. XP_GetClientStr (DBT_enterLocationForNewEntry_));
  149. dsgw_emits (" return false;\n"
  150. " } else {\n"
  151. " open('', 'NewEntryWindow');\n"
  152. " }\n"
  153. " return true;\n"
  154. "}\n"
  155. "\n"
  156. "function init()\n"
  157. "{\n"
  158. "}\n"
  159. "\n"
  160. "// end hiding -->\n"
  161. "</SCRIPT>\n");
  162. } else if ( dsgw_directive_is( line, "DS_NEWENTRY_TYPE_BODY" )) {
  163. dsgw_emitf ("<BODY %s>\n",
  164. dsgw_html_body_colors );
  165. } else if ( dsgw_directive_is( line, "DS_NEWENTRY_TYPE_FORM" )) {
  166. dsgw_form_begin ("typeForm", NULL);
  167. dsgw_emits ("\n");
  168. } else if ( dsgw_directive_is( line, "DS_NEWENTRY_TYPE_SELECT" )) {
  169. auto dsgwnewtype* ntp;
  170. dsgw_emits ("<SELECT NAME=\"selectType\" onChange=\"parent.typeChange(this)\">\n");
  171. for (ntp = gc->gc_newentrytypes; ntp; ntp = ntp->dsnt_next) {
  172. dsgw_emitf ("<OPTION VALUE=\"%s\">%s</OPTION>\n",
  173. ntp->dsnt_template ? ntp->dsnt_template : "",
  174. ntp->dsnt_fullname ? ntp->dsnt_fullname : "");
  175. }
  176. dsgw_emits ("</SELECT>\n" );
  177. } else if ( dsgw_directive_is( line, "DS_NEWENTRY_NAME_BODY" )) {
  178. dsgw_emits ("<BODY onLoad=\"");
  179. if (entType && entType->dsnt_loccount) {
  180. dsgw_emits ("parent.locationChange(document.nameForm);");
  181. }
  182. dsgw_emitf ("document.nameForm.entryname.focus()\" %s>\n",
  183. dsgw_html_body_colors );
  184. dsgw_emit_alertForm();
  185. } else if ( dsgw_directive_is( line, "DS_NEWENTRY_NAME_FORM" )) {
  186. dsgw_form_begin ("nameForm", "action=\"" DSGW_URLPREFIX_CGI_HTTP "newentry\""
  187. " target=NewEntryWindow"
  188. " onSubmit=\"return parent.submitNameForm(this)\"");
  189. dsgw_emits ("\n");
  190. if (entType) {
  191. if (entType->dsnt_rdnattr) {
  192. dsgw_emitf ("<INPUT TYPE=\"hidden\" NAME=\"rdntag\" VALUE=\"%s\">\n",
  193. entType->dsnt_rdnattr);
  194. }
  195. if (entType->dsnt_template) {
  196. dsgw_emitf ("<INPUT TYPE=\"hidden\" NAME=\"entrytype\" VALUE=\"%s\">\n",
  197. entType->dsnt_template);
  198. }
  199. }
  200. } else if ( dsgw_directive_is( line, "DS_NEWENTRY_LOCATION_BEGIN" )) {
  201. if ( ! (entType && entType->dsnt_loccount)) {
  202. while ( dsgw_next_html_line( html, line )) {
  203. if ( dsgw_parse_line( line, &argc, &argv, 1, dsgw_simple_cond_is_true, NULL )) {
  204. if ( dsgw_directive_is( line, "DS_NEWENTRY_LOCATION_END" )) {
  205. break;
  206. }
  207. }
  208. }
  209. }
  210. } else if ( dsgw_directive_is( line, "DS_NEWENTRY_LOCATION_SELECT" )) {
  211. dsgw_emits ("<SELECT NAME=\"selectLocation\""
  212. " onChange=\"parent.locationChange(this.form)\">\n");
  213. if (entType) {
  214. auto dsgwloc* locarray = gc->gc_newentrylocs;
  215. auto const int loccount = gc->gc_newentryloccount;
  216. auto int j;
  217. for ( j = 0; j < entType->dsnt_loccount; ++j ) {
  218. auto const int i = entType->dsnt_locations[j];
  219. if (i < loccount) {
  220. dsgw_emits ("<OPTION VALUE=");
  221. dsgw_emitf ("\"%s\"", locarray[i].dsloc_dnsuffix); /* XXX should escape '"' in dnsuffix */
  222. dsgw_emitf (">%s</OPTION>\n", locarray[i].dsloc_fullname);
  223. }
  224. }
  225. }
  226. } else if ( dsgw_directive_is( line, "DS_NEWENTRY_LOCATION_END" )) {
  227. } else if ( dsgw_directive_is( line, "EVALUATE" )) {
  228. if (entType) {
  229. auto int i;
  230. for (i = 0; i < argc; ++i) {
  231. if (!strcmp (argv[i], "entType.fullname")) {
  232. if (entType->dsnt_fullname) dsgw_emits (entType->dsnt_fullname);
  233. } else if (!strcmp (argv[i], "entType.rdnattr")) {
  234. if (entType->dsnt_rdnattr) dsgw_emits (entType->dsnt_rdnattr);
  235. } else if (!strcmp (argv[i], "entType.template")) {
  236. if (entType->dsnt_template) dsgw_emits (entType->dsnt_template);
  237. }
  238. }
  239. }
  240. } else if ( dsgw_directive_is( line, "DS_HELP_BUTTON" ) && argc > 0) {
  241. dsgw_emit_helpbutton (argv[0]);
  242. } else {
  243. dsgw_emits (line);
  244. }
  245. dsgw_argv_free( argv );
  246. }
  247. }
  248. fclose (html);
  249. }
  250. static char*
  251. compute_newurl()
  252. {
  253. auto char* entryType = dsgw_get_cgi_var( "entrytype", DSGW_CGIVAR_REQUIRED );
  254. auto char* entryName = dsgw_get_cgi_var( "entryname", DSGW_CGIVAR_REQUIRED );
  255. auto char* rdnTag = dsgw_get_cgi_var( "rdntag", DSGW_CGIVAR_REQUIRED );
  256. auto char* dnSuffix = dsgw_get_cgi_var( "selectLocation", DSGW_CGIVAR_OPTIONAL );
  257. auto size_t entryTypeLen = strlen (entryType);
  258. auto size_t entryNameLen = strlen (entryName);
  259. auto size_t rdnTagLen = strlen (rdnTag);
  260. auto size_t dnSuffixLen;
  261. auto char* dn;
  262. auto char* newurl = NULL;
  263. if (!dnSuffix || !*dnSuffix) {
  264. dnSuffix = dsgw_get_cgi_var( "dnsuffix", DSGW_CGIVAR_REQUIRED );
  265. }
  266. dnSuffixLen = strlen (dnSuffix);
  267. dn = dsgw_ch_malloc (rdnTagLen + 1 + entryNameLen + 2 + 1 + dnSuffixLen + 1);
  268. memcpy (dn, rdnTag, rdnTagLen + 1);
  269. strcat (dn, "=");
  270. if ( strchr (entryName, ',') || strchr (entryName, ';') ) {
  271. strcat (dn, "\"");
  272. strcat (dn, entryName);
  273. strcat (dn, "\"");
  274. } else {
  275. strcat (dn, entryName);
  276. }
  277. strcat (dn, ",");
  278. strcat (dn, dnSuffix);
  279. {
  280. auto char* edn = dsgw_strdup_escaped (dn);
  281. auto const char* const prefix = DSGW_URLPREFIX_CGI_HTTP "edit?";
  282. auto const char* const suffix = "&ADD";
  283. auto const size_t ednLen = strlen (edn);
  284. auto const size_t prefixLen = strlen (prefix);
  285. auto const size_t suffixLen = strlen (suffix);
  286. auto const size_t contextLen = strlen (context) + 9;
  287. newurl = dsgw_ch_malloc (prefixLen + entryTypeLen + contextLen + suffixLen + 4 + ednLen + 1);
  288. memcpy (newurl, prefix, prefixLen + 1);
  289. strcat (newurl, entryType);
  290. strcat (newurl, "&context=");
  291. strcat (newurl, context);
  292. strcat (newurl, suffix);
  293. strcat (newurl, "&dn=");
  294. strcat (newurl, edn);
  295. free (edn);
  296. }
  297. free (dn);
  298. return newurl;
  299. }
  300. static int
  301. client_is_authenticated()
  302. {
  303. auto char* cookie = dsgw_get_auth_cookie();
  304. auto char* rndstr = NULL;
  305. auto char* dn = NULL;
  306. auto int answer = 0;
  307. if (cookie == NULL) return 0;
  308. if (dsgw_parse_cookie (cookie, &rndstr, &dn) == 0) {
  309. if (dn) {
  310. answer = 1;
  311. free (dn);
  312. }
  313. if (rndstr) free (rndstr);
  314. }
  315. free (cookie);
  316. return answer;
  317. }
  318. static dsgwnewtype*
  319. find_entryType (char* query)
  320. {
  321. auto dsgwnewtype* ntp = gc->gc_newentrytypes;
  322. if (query && *query) {
  323. auto char* template = dsgw_ch_strdup (query);
  324. dsgw_form_unescape (template);
  325. for ( ; ntp; ntp = ntp->dsnt_next) {
  326. if (ntp->dsnt_template && !strcmp (ntp->dsnt_template, template)) {
  327. break;
  328. }
  329. }
  330. free (template);
  331. }
  332. return ntp;
  333. }
  334. static void
  335. get_request(char *docname, char *etype)
  336. {
  337. if ( docname == NULL || *docname == '\0' ) {
  338. emit_file ("newentry.html", NULL);
  339. } else if ( !strcmp( docname, "type" )) {
  340. emit_file ("newentryType.html", NULL);
  341. } else if ( !strcmp( docname, "name" )) {
  342. /*emit_file ("newentryName.html", find_entryType (getenv ("QUERY_STRING")));*/
  343. emit_file ("newentryName.html", find_entryType (etype));
  344. }
  345. }
  346. static void
  347. post_request()
  348. {
  349. auto char* newurl = compute_newurl();
  350. if (client_is_authenticated()) {
  351. /* Direct the client to GET newurl */
  352. dsgw_emits ("<HTML>" );
  353. dsgw_head_begin();
  354. dsgw_emitf ("\n<TITLE>%s</TITLE>\n", XP_GetClientStr (DBT_titleNewEntry_));
  355. dsgw_emits ("</HEAD>\n"
  356. "<FRAMESET ROWS=*,1>\n");
  357. dsgw_emitf (" <FRAME SRC=\"%s\" NORESIZE>\n", newurl);
  358. dsgw_emits ("</FRAMESET>\n"
  359. "</HTML>\n");
  360. /* It's tempting to use server redirection, like this:
  361. printf ("Location: %s\n\n", newurl);
  362. ... but it won't work, because we're handling a POST,
  363. and the client should GET newurl.
  364. */
  365. } else {
  366. #ifdef DSGW_DEBUG
  367. dsgw_log ("dsgw_emit_auth_dest (NULL, %s)\n",
  368. newurl ? newurl : "NULL");
  369. #endif
  370. dsgw_emit_auth_dest (NULL, newurl);
  371. }
  372. if (newurl) free (newurl);
  373. }
  374. int
  375. main( argc, argv, env )
  376. int argc;
  377. char *argv[];
  378. #ifdef DSGW_DEBUG
  379. char *env[];
  380. #endif
  381. {
  382. auto int reqmethod;
  383. char *qs = NULL;
  384. char *docname = NULL;
  385. char *etype = NULL;
  386. /* Parse out the file=blah.html */
  387. if (( qs = getenv( "QUERY_STRING" )) != NULL && *qs != '\0' ) {
  388. /* parse the query string: */
  389. auto char *p, *iter = NULL;
  390. qs = dsgw_ch_strdup( qs );
  391. for ( p = ldap_utf8strtok_r( qs, "&", &iter ); p != NULL;
  392. p = ldap_utf8strtok_r( NULL, "&", &iter )) {
  393. /*
  394. * Get the conf file name. It'll be translated
  395. * into /dsgw/context/CONTEXT.conf if
  396. * CONTEXT is all alphanumeric (no slahes,
  397. * or dots). CONTEXT is passed into the cgi.
  398. * if context=CONTEXT is not there, or PATH_INFO
  399. * was used, then use dsgw.conf
  400. */
  401. if ( !strncasecmp( p, "context=", 8 )) {
  402. context = dsgw_ch_strdup( p + 8 );
  403. dsgw_form_unescape( context );
  404. continue;
  405. }
  406. /*
  407. * file will be either "name", "type", or nothing.
  408. * It'll be mapped into an html file in get_request
  409. */
  410. if ( !strncasecmp( p, "file=", 5 )) {
  411. docname = dsgw_ch_strdup( p + 5 );
  412. dsgw_form_unescape( docname );
  413. continue;
  414. }
  415. /* etype will be ntgroup, or person, etc */
  416. if ( !strncasecmp( p, "etype=", 6 )) {
  417. etype = dsgw_ch_strdup( p + 6 );
  418. dsgw_form_unescape( etype );
  419. continue;
  420. }
  421. }
  422. free( qs ); qs = NULL;
  423. }
  424. if (docname != NULL && *docname == '/') {
  425. docname++;
  426. }
  427. reqmethod = dsgw_init( argc, argv, DSGW_METHOD_POST | DSGW_METHOD_GET);
  428. dsgw_send_header();
  429. #ifdef DSGW_DEBUG
  430. dsgw_logstringarray( "env", env );
  431. #endif
  432. if ( reqmethod == DSGW_METHOD_GET ) {
  433. get_request(docname, etype);
  434. } else {
  435. post_request();
  436. }
  437. exit( 0 );
  438. }