entrydisplay.c 93 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240
  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. * entrydisplay.c -- output entries one at a time or in a list -- HTTP gateway
  40. */
  41. #include "dsgw.h"
  42. #include "dbtdsgw.h"
  43. #include <ldap.h> /* ldap_utf8* */
  44. #include <unicode/udat.h>
  45. #include <unicode/utypes.h>
  46. #include <unicode/unum.h>
  47. #include <unicode/ucal.h>
  48. /*
  49. * Note: the value of the following DSGW_ATTRHTML_XXX #defines must match
  50. * their position in the attrhtmltypes[] and attrhtmlvals[] arrays.
  51. */
  52. #define DSGW_ATTRHTML_HIDDEN 0
  53. #define DSGW_ATTRHTML_TEXT 1
  54. #define DSGW_ATTRHTML_TEXTAREA 2
  55. #define DSGW_ATTRHTML_RADIO 3
  56. #define DSGW_ATTRHTML_CHECKBOX 4
  57. #define DSGW_ATTRHTML_PASSWORD 5
  58. static char *attrhtmltypes[] = {
  59. "hidden",
  60. "text",
  61. "textarea",
  62. "radio",
  63. "checkbox",
  64. "password",
  65. NULL
  66. };
  67. static int attrhtmlvals[] = {
  68. DSGW_ATTRHTML_HIDDEN,
  69. DSGW_ATTRHTML_TEXT,
  70. DSGW_ATTRHTML_TEXTAREA,
  71. DSGW_ATTRHTML_RADIO,
  72. DSGW_ATTRHTML_CHECKBOX,
  73. DSGW_ATTRHTML_PASSWORD,
  74. };
  75. #define DSGW_ATTROPT_SORT 0x00000001
  76. #define DSGW_ATTROPT_NOLINK 0x00000002
  77. #define DSGW_ATTROPT_DNTAGS 0x00000004
  78. #define DSGW_ATTROPT_DATEONLY 0x00000008 /* only for syntax=time */
  79. #define DSGW_ATTROPT_READONLY 0x00000010 /* over-rides ..._EDITABLE */
  80. #define DSGW_ATTROPT_DNPICKER 0x00000020 /* display dns for find-n-add */
  81. #define DSGW_ATTROPT_UNIQUE 0x00000040 /* attr values must be unique */
  82. #define DSGW_ATTROPT_LINK 0x00000080 /* link to attribute value */
  83. #define DSGW_ATTROPT_TYPEONLY 0x00000100 /* retrieve attr. type only */
  84. #define DSGW_ATTROPT_NO_ENTITIES 0x00000200 /* don't use entities */
  85. #define DSGW_ATTROPT_HEX 0x00000400 /* display as hex value */
  86. #define DSGW_ATTROPT_DECIMAL 0x00000800 /* display as decimal value */
  87. #define DSGW_ATTROPT_QUOTED 0x00001000 /* quote the result */
  88. #define DSGW_ATTROPT_EDITABLE 0x10000000 /* not exposed in HTML */
  89. #define DSGW_ATTROPT_ADDING 0x20000000 /* not exposed in HTML */
  90. #define DSGW_ATTROPT_LINK2EDIT 0x40000000 /* not exposed in HTML */
  91. static char *attroptions[] = {
  92. "sort",
  93. "nolink",
  94. "dntags",
  95. "dateonly",
  96. "readonly",
  97. "dnpicker",
  98. "unique",
  99. "link",
  100. "typeonly",
  101. "noentities",
  102. "hex",
  103. "decimal",
  104. "quoted",
  105. NULL
  106. };
  107. static unsigned long attroptvals[] = {
  108. DSGW_ATTROPT_SORT,
  109. DSGW_ATTROPT_NOLINK,
  110. DSGW_ATTROPT_DNTAGS,
  111. DSGW_ATTROPT_DATEONLY,
  112. DSGW_ATTROPT_READONLY,
  113. DSGW_ATTROPT_DNPICKER,
  114. DSGW_ATTROPT_UNIQUE,
  115. DSGW_ATTROPT_LINK,
  116. DSGW_ATTROPT_TYPEONLY,
  117. DSGW_ATTROPT_NO_ENTITIES,
  118. DSGW_ATTROPT_HEX,
  119. DSGW_ATTROPT_DECIMAL,
  120. DSGW_ATTROPT_QUOTED,
  121. };
  122. #define DSGW_ATTRARG_ATTR "attr"
  123. #define DSGW_ATTRARG_SYNTAX "syntax"
  124. #define DSGW_ATTRARG_HTMLTYPE "type"
  125. #define DSGW_ATTRARG_OPTIONS "options"
  126. #define DSGW_ATTRARG_DEFAULT "defaultvalue"
  127. #define DSGW_ATTRARG_WITHIN "within" /* overrides href & hrefextra */
  128. #define DSGW_ATTRARG_HREF "href"
  129. #define DSGW_ATTRARG_HREFEXTRA "hrefextra"
  130. #define DSGW_ATTRARG_LABEL "label" /* only used with syntax=dn */
  131. #define DSGW_ATTRARG_DNCOMP "dncomponents" /* only used with syntax=dn */
  132. #define DSGW_ATTRARG_TRUESTR "true" /* only used with syntax=bool */
  133. #define DSGW_ATTRARG_FALSESTR "false" /* only used with syntax=bool */
  134. #define DSGW_ATTRARGS_SIZE "size"
  135. #define DSGW_ATTRARGS_ROWS "rows"
  136. #define DSGW_ATTRARGS_COLS "cols"
  137. #define DSGW_ATTRARGS_NUMFIELDS "numfields"
  138. #define DSGW_ATTRARGS_VALUE "value"
  139. #define DSGW_ATTRARG_MIMETYPE "mimetype"
  140. #define DSGW_ATTRARG_SCRIPT "script"
  141. #define DSGW_ARG_BUTTON_PROMPT "prompt"
  142. #define DSGW_ARG_BUTTON_TEMPLATE "template"
  143. #define DSGW_ARG_BUTTON_CHECKSUBMIT "checksubmit"
  144. #define DSGW_ARG_BUTTON_TOPIC "topic"
  145. #define DSGW_ARG_DNEDIT_LABEL "label"
  146. #define DSGW_ARG_DNEDIT_TEMPLATE "template"
  147. #define DSGW_ARG_DNEDIT_ATTR "attr"
  148. #define DSGW_ARG_DNEDIT_DESC "desc"
  149. #define DSGW_ARG_FABUTTON_LABEL "label"
  150. #define DSGW_ARG_FABUTTON_ATTRNAME "attr"
  151. #define DSGW_ARG_FABUTTON_ATTRDESC "attrdesc"
  152. #define DSGW_ARG_AVSET_SET "set"
  153. /*
  154. * structure used simply to avoid passing a lot of parameters in call to
  155. * the attribute syntax handlers
  156. */
  157. struct dsgw_attrdispinfo {
  158. struct attr_handler *adi_handlerp;
  159. char *adi_attr;
  160. int adi_argc;
  161. char **adi_argv;
  162. char **adi_vals;
  163. char *adi_rdn; /* a copy of adi_vals[i] (possibly NULL) */
  164. int adi_htmltype;
  165. unsigned long adi_opts;
  166. };
  167. /* adi_rdn should be generalized, to support an RDN
  168. that contains several values of one attribute type.
  169. */
  170. typedef void (*attrdisplay)( struct dsgw_attrdispinfo *adip );
  171. typedef void (*attredit)( struct dsgw_attrdispinfo *adip );
  172. struct attr_handler {
  173. char *ath_syntax; /* dn, tel, cis, etc. */
  174. attrdisplay ath_display; /* function to display values */
  175. attredit ath_edit; /* function to display for editing */
  176. int ath_compare; /* compare function */
  177. };
  178. /* functions local to this file */
  179. static void append_to_array( char ***ap, int *countp, char *s );
  180. static unsigned long get_attr_options( int argc, char **argv );
  181. static void output_prelude( dsgwtmplinfo *tip );
  182. static void output_nonentry_line( dsgwtmplinfo *tip, char *line );
  183. static struct attr_handler *syntax2attrhandler( char *syntax );
  184. static int numfields( int argc, char **argv, int valcount );
  185. static void element_sizes( int argc, char **argv, char **vals, int valcount,
  186. int *rowsp, int *colsp );
  187. #define DSGW_TEXTOPT_FOCUSHANDLERS 0x0001
  188. #define DSGW_TEXTOPT_CHANGEHANDLERS 0x0002
  189. static void output_text_elements( int argc, char **argv, char *attr,
  190. char **vals, const char* rdn, char *prefix, int htmltype, unsigned long opts );
  191. static void output_textarea( int argc, char **argv, char *attr,
  192. char **vals, int valcount, char *prefix, unsigned long opts );
  193. static void emit_value( char *val, int quote_html_specials );
  194. static void output_text_checkbox_or_radio( struct dsgw_attrdispinfo *adip,
  195. char *prefix, int htmltype );
  196. static void do_attribute( dsgwtmplinfo *tip, char *dn, unsigned long dispopts,
  197. int argc, char **argv );
  198. static void do_orgchartlink( dsgwtmplinfo *tip, char *dn, unsigned long dispopts,
  199. int argc, char **argv );
  200. static void do_attrvalset( dsgwtmplinfo *tip, char *dn, unsigned long dispopts,
  201. int argc, char **argv );
  202. static void do_editbutton( char *dn, char *encodeddn, int argc, char **argv );
  203. static void do_savebutton( unsigned long dispopts, int argc, char **argv );
  204. static void do_deletebutton( int argc, char **argv );
  205. #if 0
  206. static void do_renamebutton( char *dn, int argc, char **argv );
  207. #endif
  208. static void do_editasbutton( int argc, char **argv );
  209. static void do_dneditbutton( unsigned long dispopts, int argc, char **argv );
  210. static void do_searchdesc( dsgwtmplinfo *tip, int argc, char **argv );
  211. static void do_passwordfield( unsigned long dispopts, int argc, char **argv,
  212. char *fieldname );
  213. static void do_helpbutton( unsigned long dispopts, int argc, char **argv );
  214. static void do_closebutton( unsigned long dispopts, int argc, char **argv );
  215. static void do_viewswitcher( char *template, char *dn, int argc, char **argv );
  216. static int did_output_as_special( int argc, char **argv, char *label,
  217. char *val );
  218. static char *time2text( char *ldtimestr, int dateonly );
  219. static long gtime( struct tm *tm );
  220. static int looks_like_dn( char *s );
  221. static void do_std_completion_js( char *template, int argc, char **argv );
  222. static int condition_is_true( int argc, char **argv, void *arg );
  223. static char ** dsgw_get_values( LDAP *ld, LDAPMessage *entry,
  224. const char *target, int binary_value );
  225. static void dsgw_value_free( void **ldvals, int binary ) ;
  226. static char *dsgw_time(time_t secs_since_1970);
  227. /* attribute syntax handler routines */
  228. static void ntdomain_display( struct dsgw_attrdispinfo *adip );
  229. static void ntuserid_display( struct dsgw_attrdispinfo *adip );
  230. static void str_display( struct dsgw_attrdispinfo *adip );
  231. static void str_edit( struct dsgw_attrdispinfo *adip );
  232. static void dn_display( struct dsgw_attrdispinfo *adip );
  233. static void dn_edit( struct dsgw_attrdispinfo *adip );
  234. static void mail_display( struct dsgw_attrdispinfo *adip );
  235. static void mls_display( struct dsgw_attrdispinfo *adip );
  236. static void mls_edit( struct dsgw_attrdispinfo *adip );
  237. static void binvalue_display( struct dsgw_attrdispinfo *adip );
  238. static void url_display( struct dsgw_attrdispinfo *adip );
  239. static void bool_display( struct dsgw_attrdispinfo *adip );
  240. static void bool_edit( struct dsgw_attrdispinfo *adip );
  241. static void time_display( struct dsgw_attrdispinfo *adip );
  242. /* static variables */
  243. #define DSGW_MOD_PREFIX_NORMAL 0
  244. #define DSGW_MOD_PREFIX_UNIQUE 1
  245. static char *replace_prefixes[] = { "replace_", "replace_unique_" };
  246. static char *replace_mls_prefixes[] = { "replace_mls_", "replace_mls_unique_" };
  247. static char *add_prefixes[] = { "add_", "add_unique_" };
  248. static char *add_mls_prefixes[] = { "add_mls_", "add_mls_unique_" };
  249. struct attr_handler attrhandlers[] = {
  250. { "cis", str_display, str_edit, CASE_INSENSITIVE },
  251. { "dn", dn_display, dn_edit, CASE_INSENSITIVE },
  252. { "mail", mail_display, str_edit, CASE_INSENSITIVE },
  253. { "mls", mls_display, mls_edit, CASE_INSENSITIVE },
  254. { "tel", str_display, str_edit, CASE_INSENSITIVE },
  255. { "url", url_display, str_edit, CASE_EXACT },
  256. { "ces", str_display, str_edit, CASE_EXACT },
  257. { "bool", bool_display, bool_edit, CASE_INSENSITIVE },
  258. { "time", time_display, str_edit, CASE_INSENSITIVE },
  259. { "ntuserid", ntuserid_display, str_edit, CASE_INSENSITIVE },
  260. { "ntgroupname", ntuserid_display, str_edit, CASE_INSENSITIVE },
  261. { "binvalue", binvalue_display, str_edit, CASE_INSENSITIVE },
  262. };
  263. #define DSGW_AH_COUNT ( sizeof( attrhandlers ) / sizeof( struct attr_handler ))
  264. static char *
  265. template_filename( int tmpltype, char *template )
  266. {
  267. char *fn, *prefix, *suffix = ".html";
  268. if ( tmpltype == DSGW_TMPLTYPE_LIST ) {
  269. prefix = DSGW_CONFIG_LISTPREFIX;
  270. } else if ( tmpltype == DSGW_TMPLTYPE_EDIT ) {
  271. prefix = DSGW_CONFIG_EDITPREFIX;
  272. } else if ( tmpltype == DSGW_TMPLTYPE_ADD ) {
  273. prefix = DSGW_CONFIG_ADDPREFIX;
  274. } else {
  275. prefix = DSGW_CONFIG_DISPLAYPREFIX;
  276. }
  277. fn = dsgw_ch_malloc( strlen( prefix ) + strlen( template )
  278. + strlen( suffix ) + 1 );
  279. sprintf( fn, "%s%s%s", prefix, template, suffix );
  280. return( fn );
  281. }
  282. static void
  283. do_postedvalue( int argc, char **argv )
  284. {
  285. dsgw_emits( "VALUE=\"" );
  286. dsgw_emit_cgi_var( argc, argv );
  287. dsgw_emits( "\"\n" );
  288. }
  289. static int
  290. dsgw_display_line( dsgwtmplinfo *tip, char *line, int argc, char **argv )
  291. {
  292. if ( dsgw_directive_is( line, DRCT_DS_POSTEDVALUE )) {
  293. do_postedvalue( argc, argv );
  294. } else if ( dsgw_directive_is( line, DRCT_DS_HELPBUTTON )) {
  295. do_helpbutton( tip->dsti_options, argc, argv );
  296. } else if ( dsgw_directive_is( line, DRCT_DS_CLOSEBUTTON )) {
  297. do_closebutton( tip->dsti_options, argc, argv );
  298. } else if ( dsgw_directive_is( line, DRCT_DS_OBJECTCLASS )) {
  299. /* omit objectClass lines */
  300. } else if ( dsgw_directive_is( line, DRCT_HEAD )) {
  301. dsgw_head_begin();
  302. dsgw_emits ("\n");
  303. } else {
  304. return 0;
  305. }
  306. return 1;
  307. }
  308. dsgwtmplinfo *
  309. dsgw_display_init( int tmpltype, char *template, unsigned long options )
  310. {
  311. dsgwtmplinfo *tip;
  312. int argc, attrcount, attrsonlycount, skip_line, in_entry;
  313. char **argv, *attr, *filename, line[ BIG_LINE ];
  314. unsigned long aopts;
  315. tip = (dsgwtmplinfo *)dsgw_ch_malloc( sizeof( dsgwtmplinfo ));
  316. memset( tip, 0, sizeof( dsgwtmplinfo ));
  317. tip->dsti_type = tmpltype;
  318. tip->dsti_options = options;
  319. tip->dsti_template = dsgw_ch_strdup( template );
  320. if (( options & DSGW_DISPLAY_OPT_ADDING ) != 0 ) {
  321. options |= DSGW_DISPLAY_OPT_EDITABLE; /* add implies editable */
  322. if ( tmpltype != DSGW_TMPLTYPE_ADD ) {
  323. /*
  324. * if we are going to display an "add" view of an entry and
  325. * an add template has not been explicitly requested, first look
  326. * for a file called "add-TEMPLATE.html" and fall back on using
  327. * whatever we would use if just editing an existing entry.
  328. */
  329. filename = template_filename( DSGW_TMPLTYPE_ADD, template );
  330. tip->dsti_fp = dsgw_open_html_file( filename, DSGW_ERROPT_IGNORE );
  331. free( filename );
  332. }
  333. }
  334. if ( tip->dsti_fp == NULL && ( options & DSGW_DISPLAY_OPT_EDITABLE ) != 0
  335. && tmpltype != DSGW_TMPLTYPE_EDIT ) {
  336. /*
  337. * if we are going to display an editable view of an entry and
  338. * an edit template has not been explicitly requested, first look
  339. * for a file called "edit-TEMPLATE.html" and fall back on using
  340. * "list-TEMPLATE.html" or "display-TEMPLATE.html", as indicated by
  341. * the value of tmpltype.
  342. */
  343. filename = template_filename( DSGW_TMPLTYPE_EDIT, template );
  344. tip->dsti_fp = dsgw_open_html_file( filename, DSGW_ERROPT_IGNORE );
  345. free( filename );
  346. }
  347. if ( tip->dsti_fp == NULL ) {
  348. filename = template_filename( tmpltype, template );
  349. tip->dsti_fp = dsgw_open_html_file( filename, DSGW_ERROPT_EXIT );
  350. free( filename );
  351. }
  352. tip->dsti_preludelines = dsgw_savelines_alloc();
  353. tip->dsti_entrylines = dsgw_savelines_alloc();
  354. in_entry = 0;
  355. /* prime attrs array so we always retrieve objectClass values */
  356. attrcount = 1;
  357. tip->dsti_attrs = (char **)dsgw_ch_realloc( tip->dsti_attrs,
  358. 2 * sizeof( char * ));
  359. tip->dsti_attrs[ 0 ] = dsgw_ch_strdup( DSGW_ATTRTYPE_OBJECTCLASS );
  360. tip->dsti_attrs[ 1 ] = NULL;
  361. attrsonlycount = 0;
  362. tip->dsti_attrsonly_attrs = NULL;
  363. while ( dsgw_next_html_line( tip->dsti_fp, line )) {
  364. skip_line = 0;
  365. if ( dsgw_parse_line( line, &argc, &argv, 1, condition_is_true, tip )) {
  366. if ( in_entry && dsgw_directive_is( line, DRCT_DS_ENTRYEND )) {
  367. dsgw_argv_free( argv );
  368. break; /* the rest is read inside dsgw_display_done */
  369. }
  370. if ( dsgw_directive_is( line, DRCT_DS_ENTRYBEGIN )) {
  371. in_entry = skip_line = 1;
  372. } else if ( dsgw_directive_is( line, DRCT_DS_ATTRIBUTE ) ||
  373. dsgw_directive_is( line, DRCT_DS_ATTRVAL_SET )) {
  374. aopts = get_attr_options( argc, argv );
  375. if (( attr = get_arg_by_name( DSGW_ATTRARG_ATTR, argc,
  376. argv )) != NULL && strcasecmp( attr, "dn" ) != 0 &&
  377. (strcasecmp(attr,DSGW_ATTRTYPE_AIMSTATUSTEXT) != 0 || gc->gc_aimpresence == 1) &&
  378. ( aopts & DSGW_ATTROPT_LINK ) == 0 ) {
  379. if (( aopts & DSGW_ATTROPT_TYPEONLY ) == 0 ) {
  380. append_to_array( &tip->dsti_attrs, &attrcount, attr );
  381. } else {
  382. append_to_array( &tip->dsti_attrsonly_attrs,
  383. &attrsonlycount, attr );
  384. }
  385. }
  386. } else if ( dsgw_directive_is( line, DRCT_DS_ORGCHARTLINK )) {
  387. aopts = get_attr_options( argc, argv );
  388. if (( aopts & DSGW_ATTROPT_TYPEONLY ) == 0 ) {
  389. append_to_array( &tip->dsti_attrs, &attrcount, gc->gc_orgchartsearchattr );
  390. } else {
  391. append_to_array( &tip->dsti_attrsonly_attrs,
  392. &attrsonlycount, gc->gc_orgchartsearchattr);
  393. }
  394. } else if ( dsgw_directive_is( line, DRCT_DS_SORTENTRIES )) {
  395. if (( attr = get_arg_by_name( DSGW_ATTRARG_ATTR, argc,
  396. argv )) == NULL ) {
  397. tip->dsti_sortbyattr = NULL; /* no attr=, so sort by DN */
  398. } else {
  399. tip->dsti_sortbyattr = dsgw_ch_strdup( attr );
  400. }
  401. skip_line = 1; /* completely done with directive */
  402. }
  403. dsgw_argv_free( argv );
  404. }
  405. if ( !skip_line ) {
  406. if ( in_entry ) { /* in entry */
  407. dsgw_savelines_save( tip->dsti_entrylines, line );
  408. } else { /* in prelude */
  409. dsgw_savelines_save( tip->dsti_preludelines, line );
  410. }
  411. }
  412. }
  413. if ( attrcount > 0 ) {
  414. tip->dsti_attrflags = (unsigned long *)dsgw_ch_malloc( attrcount
  415. * sizeof( unsigned long ));
  416. memset( tip->dsti_attrflags, 0, attrcount * sizeof( unsigned long ));
  417. }
  418. /*
  419. * Add the sortattr to the list of attrs retrieved, if it's not
  420. * already in the list.
  421. */
  422. if ( tip->dsti_sortbyattr != NULL ) {
  423. int i, found = 0;
  424. for ( i = 0; i < attrcount; i++ ) {
  425. if ( !strcasecmp( tip->dsti_sortbyattr, tip->dsti_attrs[ i ])) {
  426. found = 1;
  427. break;
  428. }
  429. }
  430. if ( !found ) {
  431. append_to_array( &tip->dsti_attrs, &attrcount,
  432. tip->dsti_sortbyattr );
  433. }
  434. }
  435. return( tip );
  436. }
  437. void
  438. dsgw_display_entry( dsgwtmplinfo *tip, LDAP *ld, LDAPMessage *entry,
  439. LDAPMessage *attrsonly_entry, char *dn )
  440. {
  441. int argc, editable, adding;
  442. char **argv, *encodeddn, *line;
  443. editable = (( tip->dsti_options & DSGW_DISPLAY_OPT_EDITABLE ) != 0 );
  444. adding = (( tip->dsti_options & DSGW_DISPLAY_OPT_ADDING ) != 0 );
  445. if ( entry == NULL && !adding ) {
  446. dsgw_error( DSGW_ERR_MISSINGINPUT, NULL, DSGW_ERROPT_EXIT, 0, NULL );
  447. }
  448. tip->dsti_ld = ld;
  449. tip->dsti_entry = entry;
  450. tip->dsti_attrsonly_entry = attrsonly_entry;
  451. if ( dn == NULL ) {
  452. if ( entry == NULL ) {
  453. dn = "dn=unknown";
  454. } else if (( dn = ldap_get_dn( ld, entry )) == NULL ) {
  455. dsgw_ldap_error( ld, DSGW_ERROPT_EXIT );
  456. }
  457. }
  458. tip->dsti_entrydn = dsgw_ch_strdup( dn );
  459. encodeddn = dsgw_strdup_escaped( dn );
  460. if ( adding ) {
  461. tip->dsti_rdncomps = dsgw_rdn_values( dn );
  462. }
  463. if ( tip->dsti_preludelines != NULL ) {
  464. output_prelude( tip );
  465. }
  466. dsgw_savelines_rewind( tip->dsti_entrylines );
  467. while (( line = dsgw_savelines_next( tip->dsti_entrylines )) != NULL ) {
  468. if ( dsgw_parse_line( line, &argc, &argv, 0, condition_is_true, tip )) {
  469. if ( dsgw_directive_is( line, DRCT_DS_ATTRIBUTE )) {
  470. do_attribute( tip, dn, tip->dsti_options, argc, argv );
  471. } else if ( dsgw_directive_is( line, DRCT_DS_ATTRVAL_SET )) {
  472. do_attrvalset( tip, dn, tip->dsti_options, argc, argv );
  473. } else if ( dsgw_directive_is( line, DRCT_DS_ORGCHARTLINK )) {
  474. do_orgchartlink( tip, dn, tip->dsti_options, argc, argv );
  475. } else if ( dsgw_directive_is( line, DRCT_DS_EMIT_BASE_HREF )) {
  476. char *p;
  477. char *sname = dsgw_ch_strdup( getenv( "SCRIPT_NAME" ));
  478. if (( p = strrchr( sname, '/' )) != NULL ) {
  479. *p = '\0';
  480. }
  481. dsgw_emitf( "<BASE HREF=\"%s%s/\">\n",
  482. getenv( "SERVER_URL" ), sname );
  483. } else if ( dsgw_directive_is( line, DRCT_DS_BEGIN_DNSEARCHFORM )) {
  484. dsgw_form_begin ( "searchForm", "action=\"%s\" %s %s",
  485. dsgw_getvp( DSGW_CGINUM_DOSEARCH ),
  486. "target=stagingFrame",
  487. "onSubmit=\"return parent.processSearch(searchForm);\"" );
  488. dsgw_emitf( "\n<INPUT TYPE=\"hidden\" NAME=\"dn\" VALUE=\"%s\";>\n", encodeddn );
  489. } else if ( dsgw_directive_is( line, DRCT_DS_BEGIN_ENTRYFORM )) {
  490. if ( editable ) {
  491. dsgw_form_begin("modifyEntryForm","ACTION=\"%s\"",
  492. dsgw_getvp( DSGW_CGINUM_DOMODIFY ));
  493. dsgw_emits( "\n<INPUT TYPE=hidden NAME=\"changetype\">\n" );
  494. dsgw_emitf( "<INPUT TYPE=hidden NAME=\"dn\" VALUE=\"%s\">\n",
  495. encodeddn );
  496. dsgw_emits( "<INPUT TYPE=hidden NAME=\"changed_DN\" VALUE=false>\n");
  497. dsgw_emits( "<INPUT TYPE=hidden NAME=\"deleteoldrdn\" VALUE=true>\n");
  498. } else {
  499. dsgw_form_begin("editEntryForm", "action=\"%s\" %s",
  500. dsgw_getvp( DSGW_CGINUM_AUTH ),
  501. "target=\"_blank\"" );
  502. dsgw_emits( "\n" );
  503. }
  504. } else if ( dsgw_directive_is( line, DRCT_DS_END_ENTRYFORM )) {
  505. dsgw_emitf( "</FORM>\n" );
  506. dsgw_emit_confirmForm();
  507. } else if ( dsgw_directive_is( line, DRCT_DS_END_DNSEARCHFORM )) {
  508. dsgw_emitf( "</FORM>\n" );
  509. dsgw_emit_alertForm();
  510. dsgw_emit_confirmForm();
  511. } else if ( dsgw_directive_is( line, DRCT_DS_EDITBUTTON )) {
  512. if ( !editable ) do_editbutton( dn, encodeddn, argc, argv );
  513. } else if ( dsgw_directive_is( line, DRCT_DS_DELETEBUTTON )) {
  514. if ( editable && !adding ) do_deletebutton( argc, argv );
  515. } else if ( dsgw_directive_is( line, DRCT_DS_RENAMEBUTTON )) {
  516. /* if ( editable && !adding ) do_renamebutton( dn, argc, argv ); */
  517. } else if ( dsgw_directive_is( line, DRCT_DS_EDITASBUTTON )) {
  518. if ( editable ) do_editasbutton( argc, argv );
  519. } else if ( dsgw_directive_is( line, DRCT_DS_SAVEBUTTON )) {
  520. if ( editable ) do_savebutton( tip->dsti_options, argc, argv );
  521. } else if ( dsgw_display_line( tip, line, argc, argv )) {
  522. } else if ( dsgw_directive_is( line, DRCT_DS_NEWPASSWORD )) {
  523. if ( editable ) do_passwordfield( tip->dsti_options, argc,
  524. argv, "newpasswd" );
  525. } else if ( dsgw_directive_is( line, DRCT_DS_CONFIRM_NEWPASSWORD )) {
  526. if ( editable ) do_passwordfield( tip->dsti_options, argc,
  527. argv, "newpasswdconfirm" );
  528. } else if ( dsgw_directive_is( line, DRCT_DS_OLDPASSWORD )) {
  529. if ( editable ) do_passwordfield( tip->dsti_options, argc,
  530. argv, "passwd" );
  531. } else if ( dsgw_directive_is( line, DRCT_DS_DNATTR )) {
  532. if ( dsgw_dnattr != NULL ) dsgw_emits( dsgw_dnattr );
  533. } else if ( dsgw_directive_is( line, DRCT_DS_DNDESC )) {
  534. if ( dsgw_dndesc != NULL ) dsgw_emits( dsgw_dndesc );
  535. } else if ( dsgw_directive_is( line, DRCT_DS_DNEDITBUTTON )) {
  536. if ( editable ) {
  537. do_dneditbutton( tip->dsti_options, argc, argv );
  538. }
  539. } else if ( dsgw_directive_is( line, "DS_DNADDBUTTON" )) {
  540. dsgw_emits ("<INPUT TYPE=SUBMIT");
  541. {
  542. auto char* v = get_arg_by_name (DSGW_ATTRARGS_VALUE, argc, argv);
  543. if (v) dsgw_emitf (" VALUE=\"%s\"", v);
  544. }
  545. dsgw_emits (">\n");
  546. } else if ( dsgw_directive_is( line, "DS_DNREMOVEBUTTON" )) {
  547. dsgw_emits ("<INPUT TYPE=BUTTON");
  548. {
  549. auto char* v = get_arg_by_name (DSGW_ATTRARGS_VALUE, argc, argv);
  550. if (v) dsgw_emitf (" VALUE=\"%s\"", v);
  551. }
  552. dsgw_emits (" onClick=\"if (parent.processSearch(searchForm)) {"
  553. "searchForm.faMode.value='remove';"
  554. "searchForm.submit();"
  555. "searchForm.searchstring.select();"
  556. "searchForm.searchstring.focus();"
  557. "}\">\n");
  558. } else if ( dsgw_directive_is( line, DRCT_DS_VIEW_SWITCHER ) &&
  559. tip->dsti_entry != NULL ) {
  560. do_viewswitcher( tip->dsti_template, tip->dsti_entrydn,
  561. argc, argv );
  562. } else if ( dsgw_directive_is( line, DRCT_DS_STD_COMPLETION_JS )) {
  563. do_std_completion_js( tip->dsti_template, argc, argv );
  564. } else {
  565. dsgw_emits( line );
  566. }
  567. dsgw_argv_free( argv );
  568. }
  569. }
  570. free( encodeddn );
  571. }
  572. static void
  573. dsgw_setstr (char** into, const char* from)
  574. {
  575. if (from) {
  576. auto const size_t len = strlen (from) + 1;
  577. *into = dsgw_ch_realloc (*into, len);
  578. memmove (*into, from, len);
  579. } else if (*into) {
  580. free (*into);
  581. *into = NULL;
  582. }
  583. }
  584. void
  585. dsgw_set_searchdesc( dsgwtmplinfo *tip, char *s2, char *s3, char *s4 )
  586. {
  587. dsgw_setstr( &(tip->dsti_search2s), s2 );
  588. dsgw_setstr( &(tip->dsti_search3s), s3 );
  589. dsgw_setstr( &(tip->dsti_search4s), s4 );
  590. }
  591. void
  592. dsgw_set_search_result( dsgwtmplinfo *tip, int entrycount, char *searcherror,
  593. char *lderrtxt )
  594. {
  595. tip->dsti_entrycount = entrycount;
  596. dsgw_setstr( &(tip->dsti_searcherror), searcherror );
  597. dsgw_setstr( &(tip->dsti_searchlderrtxt), lderrtxt );
  598. }
  599. void
  600. dsgw_display_done( dsgwtmplinfo *tip )
  601. {
  602. char line[ BIG_LINE ], *jscomp;
  603. if ( tip->dsti_preludelines != NULL ) {
  604. output_prelude( tip );
  605. }
  606. while ( dsgw_next_html_line( tip->dsti_fp, line )) {
  607. output_nonentry_line( tip, line );
  608. }
  609. /*
  610. * check for "completion_javascript" form var and
  611. * execute it if present.
  612. */
  613. jscomp = dsgw_get_cgi_var( "completion_javascript",
  614. DSGW_CGIVAR_OPTIONAL );
  615. if ( jscomp != NULL ) {
  616. dsgw_emits( "<SCRIPT LANGUAGE=\"JavaScript\">\n" );
  617. dsgw_emitf( "eval('%s');\n", jscomp );
  618. dsgw_emits( "</SCRIPT>\n" );
  619. }
  620. fflush( stdout );
  621. fflush( stdout );
  622. dsgw_savelines_free( tip->dsti_entrylines );
  623. fclose( tip->dsti_fp );
  624. if ( tip->dsti_attrs != NULL ) {
  625. ldap_value_free( tip->dsti_attrs );
  626. }
  627. if ( tip->dsti_attrflags != NULL ) {
  628. free( tip->dsti_attrflags );
  629. }
  630. if ( tip->dsti_rdncomps != NULL ) {
  631. ldap_value_free( tip->dsti_rdncomps );
  632. }
  633. free( tip );
  634. }
  635. static void
  636. output_prelude( dsgwtmplinfo *tip )
  637. {
  638. int editable, adding;
  639. char *line, *encodeddn;
  640. if ( tip->dsti_preludelines != NULL ) { /* output the prelude */
  641. dsgw_savelines_rewind( tip->dsti_preludelines );
  642. while (( line = dsgw_savelines_next( tip->dsti_preludelines ))
  643. != NULL ) {
  644. output_nonentry_line( tip, line );
  645. }
  646. dsgw_savelines_free( tip->dsti_preludelines );
  647. tip->dsti_preludelines = NULL;
  648. }
  649. /* output any JavaScript functions we want to include before the entry */
  650. dsgw_emits( "<SCRIPT LANGUAGE=\"JavaScript\">\n" );
  651. dsgw_emits( "<!-- Hide from non-JavaScript-capable browsers\n" );
  652. dsgw_emits( "var emptyFrame = '';\n" );
  653. editable = ( tip->dsti_options & DSGW_DISPLAY_OPT_EDITABLE ) != 0;
  654. adding = ( tip->dsti_options & DSGW_DISPLAY_OPT_ADDING ) != 0;
  655. if ( !editable ) {
  656. char *urlprefix = dsgw_ch_malloc( strlen(gc->gc_urlpfxmain) + 128);
  657. sprintf(urlprefix, "%semptyFrame.html", gc->gc_urlpfxmain);
  658. /* include the functions used to support "Edit" buttons */
  659. /* function haveAuthCookie() */
  660. dsgw_emits( "function haveAuthCookie()\n{\n" );
  661. dsgw_emitf( " return ( document.cookie.indexOf( '%s=' ) >= 0 "
  662. "&& document.cookie.indexOf( '%s=%s' ) < 0 );\n}\n\n",
  663. DSGW_AUTHCKNAME, DSGW_AUTHCKNAME, DSGW_UNAUTHSTR );
  664. /* function authOrEdit() -- calls haveAuthCookie() */
  665. dsgw_emits( "function authOrEdit(encodeddn)\n{\n" );
  666. dsgw_emitf( " editURL = '%s?context=%s&dn=' + encodeddn;\n",
  667. dsgw_getvp( DSGW_CGINUM_EDIT ), context);
  668. dsgw_emits( " if ( haveAuthCookie()) {\n" );
  669. dsgw_emits( "\tnw = open(editURL, \"_blank\");\n" );
  670. dsgw_emits( "\twindow.location.href = " );
  671. dsgw_quote_emits (QUOTATION_JAVASCRIPT, urlprefix);
  672. dsgw_emits( ";\n"
  673. " } else {\n"
  674. "\tdocument.editEntryForm.authdesturl.value = editURL;\n"
  675. "\ta = open(");
  676. dsgw_quote_emits (QUOTATION_JAVASCRIPT, urlprefix);
  677. free(urlprefix);
  678. urlprefix = NULL;
  679. dsgw_emits(", 'AuthWin');\n"
  680. "\ta.opener = self;\n"
  681. "\ta.closewin = true;\n"
  682. "\tdocument.editEntryForm.target = 'AuthWin';\n"
  683. "\tdocument.editEntryForm.submit();\n"
  684. " }\n}\n" );
  685. } else {
  686. /* include variables and functions used to support edit mode */
  687. dsgw_emits( "var changesHaveBeenMade = 0;\n\n" );
  688. dsgw_emits( "var possiblyChangedAttr = null;\n\n" );
  689. /* function aChg() -- called from onChange and onClick handlers */
  690. dsgw_emits( "function aChg(attr)\n{\n" );
  691. if ( !adding ) {
  692. dsgw_emits( " cmd = 'document.modifyEntryForm.changed_' + "
  693. "attr + '.value = \"true\"';\n" );
  694. dsgw_emits( " eval( cmd );\n possiblyChangedAttr = null;\n" );
  695. }
  696. dsgw_emits( " changesHaveBeenMade = 1;\n}\n\n" );
  697. if ( !adding ) {
  698. /* function aFoc() -- called when text area gets focus. */
  699. dsgw_emits( "function aFoc(attr)\n{\n"
  700. " possiblyChangedAttr = attr;\n}\n\n" );
  701. }
  702. /* function submitModify() */
  703. dsgw_emits( "function submitModify(changetype)\n{\n" );
  704. if ( !adding ) {
  705. dsgw_emits( "\tif ( possiblyChangedAttr != null ) "
  706. "aChg(possiblyChangedAttr);\n" );
  707. }
  708. dsgw_emits( "\tdocument.modifyEntryForm.changetype.value = changetype;\n" );
  709. dsgw_emits( "\tdocument.modifyEntryForm.submit();\n}\n" );
  710. /* function confirmModify() */
  711. dsgw_emits( "var changetype = '';\n\n" );
  712. dsgw_emits( "function confirmModify(ctype, prompt)\n{\n" );
  713. dsgw_emits( " changetype = ctype;\n" );
  714. dsgw_emit_confirm (NULL, "opener.submitModify(opener.changetype);", NULL/*no*/,
  715. NULL /* options */, 0, "prompt");
  716. dsgw_emits( "}\n" );
  717. /* function EditEntryAs() */
  718. /*
  719. dsgw_emits( "function EditEntryAs(template)\n{\n" );
  720. dsgw_emits( " newurl = window.location.protocol + '//' +\n"
  721. "\twindow.location.host +\n"
  722. "\twindow.location.pathname + '?' + template;\n" );
  723. dsgw_emits( "\twindow.location.href = newurl;\n}\n" );
  724. */
  725. if ( tip->dsti_entrydn != NULL ) {
  726. encodeddn = dsgw_strdup_escaped( tip->dsti_entrydn );
  727. dsgw_emits( "function EditEntryAs(template)\n{\n" );
  728. dsgw_emitf( " newurl = '%s?' + template + '&context=%s&dn=%s';\n",
  729. dsgw_getvp( DSGW_CGINUM_EDIT ), context, encodeddn );
  730. dsgw_emits( "\twindow.location.href = newurl;\n}\n" );
  731. }
  732. /* function DNEdit() */
  733. if ( tip->dsti_entrydn != NULL ) {
  734. encodeddn = dsgw_strdup_escaped( tip->dsti_entrydn );
  735. dsgw_emits( "var DNEditURL;\n" );
  736. dsgw_emits( "function DNEdit(template, attr, desc)\n{\n" );
  737. dsgw_emitf( " DNEditURL = '%s?template=' + template + "
  738. "'&dn=%s&context=%s&ATTR=' + attr + '&DESC=' + escape(desc);\n",
  739. dsgw_getvp( DSGW_CGINUM_DNEDIT ), encodeddn, context );
  740. dsgw_emits( " if( !changesMade() ) window.location.href = DNEditURL;\n"
  741. " else {\n");
  742. dsgw_emit_confirm( NULL, "opener.location.href = opener.DNEditURL;", NULL/*no*/,
  743. XP_GetClientStr(DBT_continueWithoutSavingWindow_), 1,
  744. XP_GetClientStr(DBT_continueWithoutSaving_));
  745. dsgw_emits( " }\n");
  746. dsgw_emits( "}\n" );
  747. }
  748. /* function changesMade() */
  749. dsgw_emits( "function changesMade()\n{\n" );
  750. if ( !adding ) {
  751. dsgw_emits( "\tif ( possiblyChangedAttr != null ) "
  752. "aChg(possiblyChangedAttr);\n" );
  753. }
  754. dsgw_emits( " return( changesHaveBeenMade );\n}\n" );
  755. /* function closeIfOK() */
  756. dsgw_emits( "function closeIfOK()\n{\n"
  757. " if ( !changesMade() ) top.close();\n"
  758. " else {\n" );
  759. dsgw_emit_confirm( NULL, "opener.top.close();", NULL/*no*/,
  760. XP_GetClientStr(DBT_discardChangesWindow_), 1,
  761. XP_GetClientStr(DBT_discardChanges_));
  762. dsgw_emits( " }\n}\n" );
  763. /* set unload handler to catch unsaved changes */
  764. dsgw_emits( "document.onUnload = \""
  765. "return ( !changesMade() || prompt( 'Discard Changes?' ));\"\n" );
  766. }
  767. dsgw_emits( "// End hiding -->\n</SCRIPT>\n" );
  768. }
  769. static void
  770. output_nonentry_line( dsgwtmplinfo *tip, char *line )
  771. {
  772. int argc;
  773. char **argv;
  774. if ( dsgw_parse_line( line, &argc, &argv, 0, condition_is_true, tip )) {
  775. if ( dsgw_directive_is( line, DRCT_DS_SEARCHDESC )) {
  776. do_searchdesc( tip, argc, argv );
  777. } else if ( dsgw_display_line ( tip, line, argc, argv )) {
  778. } else {
  779. dsgw_emits( line );
  780. }
  781. dsgw_argv_free( argv );
  782. }
  783. }
  784. static char*
  785. find_RDN (char* DN, char* attr, char** vals)
  786. /* Return a copy of the vals[i] that is
  787. part of the RDN of the given DN.
  788. */
  789. {
  790. if (DN && *DN && vals && *vals) {
  791. auto char** RDNs = ldap_explode_dn (DN, 0);
  792. auto char** AVAs = ldap_explode_rdn (RDNs[0], 0);
  793. ldap_value_free (RDNs);
  794. if (AVAs) {
  795. auto char** val = NULL;
  796. auto char** AVA;
  797. for (AVA = AVAs; *AVA; ++AVA) {
  798. auto char* RDN = strchr (*AVA, '=');
  799. if (RDN) {
  800. *RDN++ = '\0';
  801. if (!strcasecmp (*AVA, attr)) {
  802. for (val = vals; *val; ++val) {
  803. if (!strcmp (RDN, *val)) {
  804. break;
  805. }
  806. }
  807. if (*val) break;
  808. /* bug: what if there are other AVAs
  809. that also match attr and one of vals?
  810. Even if this algorithm could find them,
  811. it couldn't return them (the function
  812. return value can't express multiple
  813. values).
  814. */
  815. }
  816. }
  817. }
  818. ldap_value_free (AVAs);
  819. if (val) return *val;
  820. }
  821. }
  822. return NULL;
  823. }
  824. /*static int
  825. *is_aim_online(dsgwtmplinfo *tip)
  826. *{
  827. * char **ldvals = (char **) dsgw_get_values(tip->dsti_ld, tip->dsti_entry, DSGW_ATTRTYPE_AIMSTATUSTEXT, 0);
  828. *
  829. * if (ldvals == NULL || *ldvals == NULL || strcmp(*ldvals, "") == 0 ) {
  830. * return(0);
  831. * }
  832. * return(1);
  833. *
  834. *}
  835. */
  836. static void
  837. do_orgchartlink( dsgwtmplinfo *tip, char *dn, unsigned long dispopts,
  838. int argc, char **argv )
  839. {
  840. char **ldvals = (char **) dsgw_get_values(tip->dsti_ld, tip->dsti_entry, gc->gc_orgchartsearchattr, 0);
  841. char *escaped_value;
  842. if (gc->gc_orgcharturl == NULL || ldvals == NULL || *ldvals == NULL || strcmp(*ldvals,"") == 0) {
  843. dsgw_emits("\"javascript:void(0)\"");
  844. return;
  845. }
  846. dsgw_emits("\"");
  847. dsgw_emits(gc->gc_orgcharturl);
  848. escaped_value = dsgw_ch_malloc( 3 * strlen( ldvals[0] ) + 1 );
  849. *escaped_value = '\0';
  850. dsgw_strcat_escaped( escaped_value, ldvals[0]);
  851. dsgw_emits(escaped_value);
  852. dsgw_emits("\"\n");
  853. return;
  854. }
  855. static void
  856. do_attribute( dsgwtmplinfo *tip, char *dn, unsigned long dispopts,
  857. int argc, char **argv )
  858. {
  859. char *attr, *syntax, *defval, *tmpvals[ 2 ], *s;
  860. char **ldvals, **vals;
  861. unsigned long options;
  862. int i, len, attrindex, htmltype;
  863. struct dsgw_attrdispinfo adi;
  864. int editable = 0;
  865. int tagged_attrs = 0;
  866. int binary_value = 0;
  867. if (( attr = get_arg_by_name( DSGW_ATTRARG_ATTR, argc, argv )) == NULL ) {
  868. dsgw_emitf( XP_GetClientStr(DBT_missingS_), DSGW_ATTRARG_ATTR );
  869. return;
  870. }
  871. if (( syntax = get_arg_by_name( DSGW_ATTRARG_SYNTAX, argc, argv ))
  872. == NULL ) {
  873. syntax = "cis";
  874. }
  875. if (( s = get_arg_by_name( DSGW_ATTRARG_HTMLTYPE, argc, argv )) == NULL ) {
  876. htmltype = DSGW_ATTRHTML_TEXT;
  877. } else {
  878. for ( i = 0; attrhtmltypes[ i ] != NULL; ++i ) {
  879. if ( strcasecmp( s, attrhtmltypes[ i ] ) == 0 ) {
  880. htmltype = attrhtmlvals[ i ];
  881. break;
  882. }
  883. }
  884. if ( attrhtmltypes[ i ] == NULL ) {
  885. dsgw_emitf( XP_GetClientStr(DBT_unknownSS_), DSGW_ATTRARG_HTMLTYPE, s );
  886. return;
  887. }
  888. }
  889. options = get_attr_options( argc, argv );
  890. if (( options & DSGW_ATTROPT_TYPEONLY ) != 0 ) {
  891. return; /* don't actually display attr. if we only retrieved types */
  892. }
  893. if (( options & DSGW_ATTROPT_LINK ) != 0 ) {
  894. /*
  895. * Output a "dosearch" URL that will retrieve this attribute.
  896. * These used to look like:
  897. * .../dosearch/<host>:<port>?dn=<encodeddn>&<attr>&<mimetype>&<valindex>
  898. *
  899. * Now, thanks to me, they look like:
  900. * .../dosearch?context=<blah>&hp=<host>:<port>&dn=<encodeddn>&ldq=<the rest>
  901. * - RJP
  902. */
  903. char *urlprefix, *escapeddn, *mimetype, *prefix, *suffix;
  904. urlprefix = dsgw_build_urlprefix();
  905. escapeddn = dsgw_strdup_escaped( dn );
  906. mimetype = get_arg_by_name( DSGW_ATTRARG_MIMETYPE, argc, argv );
  907. if (( prefix = get_arg_by_name( "prefix", argc, argv )) == NULL ) {
  908. prefix = "";
  909. }
  910. if (( suffix = get_arg_by_name( "suffix", argc, argv )) == NULL ) {
  911. suffix = "";
  912. }
  913. /* XXXmcs
  914. * always reference first value for now ( "&0" ) unless returning
  915. * link to a vCard (in which case we leave the &0 off)
  916. */
  917. dsgw_emitf("%s\"%s%s&ldq=%s&%s%s\"%s\n", prefix, urlprefix, escapeddn, attr,
  918. ( mimetype == NULL ) ? "" : mimetype,
  919. ( strcasecmp( "_vcard", attr ) == 0 ) ? "" : "&0", suffix );
  920. free( urlprefix );
  921. free( escapeddn );
  922. return;
  923. }
  924. if (( dispopts & DSGW_DISPLAY_OPT_EDITABLE ) != 0
  925. && ( options & DSGW_ATTROPT_READONLY ) == 0 ) {
  926. options |= DSGW_ATTROPT_EDITABLE;
  927. editable = 1;
  928. if (( dispopts & DSGW_DISPLAY_OPT_ADDING ) != 0 ) {
  929. options |= DSGW_ATTROPT_ADDING;
  930. }
  931. }
  932. if (( dispopts & DSGW_DISPLAY_OPT_LINK2EDIT ) != 0 ) {
  933. options |= DSGW_ATTROPT_LINK2EDIT;
  934. }
  935. if ((options & DSGW_ATTROPT_QUOTED ) != 0 ) {
  936. options &= ~DSGW_ATTROPT_EDITABLE;/* always read-only */
  937. options &= ~DSGW_ATTROPT_ADDING; /* always read-only */
  938. options |= DSGW_ATTROPT_READONLY;
  939. }
  940. ldvals = vals = NULL;
  941. if ( strcasecmp( attr, "dn" ) == 0 ) { /* dn pseudo-attribute */
  942. tmpvals[ 0 ] = dn;
  943. tmpvals[ 1 ] = NULL;
  944. vals = tmpvals;
  945. options &= ~DSGW_ATTROPT_EDITABLE; /* always read-only */
  946. options &= ~DSGW_ATTROPT_ADDING; /* always read-only */
  947. options |= DSGW_ATTROPT_READONLY;
  948. } else if( strcasecmp( syntax, "binvalue" ) == 0) {
  949. binary_value = 1;
  950. /* Only display tagged stuff on searches */
  951. if (editable){
  952. ldvals = (char **) ldap_get_values_len(tip->dsti_ld, tip->dsti_entry, attr);
  953. tagged_attrs = 0;
  954. } else {
  955. ldvals = (char **) dsgw_get_values(tip->dsti_ld, tip->dsti_entry, attr, 1 /*binary value*/);
  956. tagged_attrs = 1;
  957. }
  958. if (ldvals != NULL) {
  959. vals = ldvals;
  960. }
  961. } else if ( tip->dsti_entry != NULL) {
  962. /* Only display tagged stuff on searches */
  963. if ( editable){
  964. ldvals = (char **) ldap_get_values( tip->dsti_ld, tip->dsti_entry, attr);
  965. tagged_attrs = 0;
  966. } else {
  967. ldvals = (char **) dsgw_get_values( tip->dsti_ld, tip->dsti_entry, attr, 0 );
  968. tagged_attrs = 1;
  969. }
  970. if (ldvals != NULL) {
  971. vals = ldvals;
  972. }
  973. }
  974. if (vals == NULL && (options & DSGW_ATTROPT_QUOTED ) != 0 ) {
  975. dsgw_emits( "\"\"" );
  976. return;
  977. }
  978. if ( vals == NULL && tip->dsti_rdncomps != NULL
  979. && ( options & DSGW_ATTROPT_ADDING ) != 0 ) {
  980. /*
  981. * include values from the DN of new entry being added
  982. */
  983. len = strlen( attr );
  984. ldvals = NULL;
  985. for ( i = 0; tip->dsti_rdncomps[ i ] != NULL; ++i ) {
  986. if (( s = strchr( tip->dsti_rdncomps[ i ], '=' )) != NULL &&
  987. s - tip->dsti_rdncomps[ i ] == len &&
  988. strncasecmp( attr, tip->dsti_rdncomps[ i ], len ) == 0 ) {
  989. tmpvals[ 0 ] = ++s;
  990. tmpvals[ 1 ] = NULL;
  991. vals = tmpvals;
  992. break;
  993. }
  994. }
  995. }
  996. if ( vals == NULL && ( defval = get_arg_by_name( DSGW_ATTRARG_DEFAULT,
  997. argc, argv )) != NULL ) {
  998. tmpvals[ 0 ] = defval;
  999. tmpvals[ 1 ] = NULL;
  1000. vals = tmpvals;
  1001. }
  1002. if ( vals == NULL && ( options & DSGW_ATTROPT_EDITABLE ) == 0 ) {
  1003. if ( htmltype != DSGW_ATTRHTML_HIDDEN ) {
  1004. dsgw_HTML_emits( DSGW_UTF8_NBSP );
  1005. }
  1006. } else {
  1007. if (( adi.adi_handlerp = syntax2attrhandler( syntax )) == NULL ) {
  1008. dsgw_emitf( XP_GetClientStr(DBT_unknownSyntaxSN_), syntax );
  1009. } else {
  1010. if ( vals != NULL && vals[1] != NULL
  1011. && ( options & DSGW_ATTROPT_SORT ) != 0 ) {
  1012. ldap_sort_values( tip->dsti_ld, vals,
  1013. dsgw_valcmp (adi.adi_handlerp->ath_compare));
  1014. }
  1015. adi.adi_attr = attr;
  1016. adi.adi_argc = argc;
  1017. adi.adi_argv = argv;
  1018. adi.adi_vals = vals;
  1019. adi.adi_rdn = NULL;
  1020. adi.adi_htmltype = htmltype;
  1021. adi.adi_opts = options;
  1022. if (( options & DSGW_ATTROPT_EDITABLE ) == 0 ) {
  1023. (*adi.adi_handlerp->ath_display)( &adi );
  1024. } else {
  1025. if (( options & DSGW_ATTROPT_ADDING ) == 0 ) {
  1026. /* set flag to track attrs. we have seen */
  1027. for ( attrindex = 0; tip->dsti_attrs[ attrindex ] != NULL;
  1028. ++attrindex ) {
  1029. if ( strcasecmp( attr, tip->dsti_attrs[ attrindex ] )
  1030. == 0 ) {
  1031. break;
  1032. }
  1033. }
  1034. if ( tip->dsti_attrs[ attrindex ] != NULL ) {
  1035. if ( ! (tip->dsti_attrflags[ attrindex ] & DSGW_DSTI_ATTR_SEEN)) {
  1036. tip->dsti_attrflags[ attrindex ] |= DSGW_DSTI_ATTR_SEEN;
  1037. dsgw_emitf( "<INPUT TYPE=hidden NAME=\"changed_%s\" VALUE=false>\n",
  1038. attr );
  1039. }
  1040. adi.adi_rdn = find_RDN( dn, attr, vals );
  1041. }
  1042. }
  1043. /* display for editing */
  1044. (*adi.adi_handlerp->ath_edit)( &adi );
  1045. }
  1046. }
  1047. }
  1048. if ( ldvals != NULL ) {
  1049. if (tagged_attrs) {
  1050. dsgw_value_free( (void **) ldvals, binary_value );
  1051. } else {
  1052. if (binary_value) {
  1053. ldap_value_free_len( (struct berval **) ldvals );
  1054. } else {
  1055. ldap_value_free( ldvals );
  1056. }
  1057. }
  1058. }
  1059. }
  1060. static void
  1061. append_to_array( char ***ap, int *countp, char *s )
  1062. {
  1063. char **a;
  1064. int count;
  1065. a = *ap;
  1066. count = *countp;
  1067. a = (char **)dsgw_ch_realloc( a, ( count + 2 ) * sizeof( char * ));
  1068. a[ count++ ] = dsgw_ch_strdup( s );
  1069. a[ count ] = NULL;
  1070. *ap = a;
  1071. *countp = count;
  1072. }
  1073. static unsigned long
  1074. get_attr_options( int argc, char **argv )
  1075. {
  1076. int i;
  1077. unsigned long opts;
  1078. char *s;
  1079. opts = 0;
  1080. if (( s = get_arg_by_name( DSGW_ATTRARG_OPTIONS, argc, argv )) != NULL ) {
  1081. char *p, *q;
  1082. for ( p = dsgw_ch_strdup( s ); p != NULL; p = q ) {
  1083. if (( q = strchr( p, ',' )) != NULL ) {
  1084. *q++ = '\0';
  1085. }
  1086. for ( i = 0; attroptions[ i ] != NULL; ++i ) {
  1087. if ( strcasecmp( p, attroptions[ i ] ) == 0 ) {
  1088. opts |= attroptvals[ i ];
  1089. break;
  1090. }
  1091. }
  1092. if ( attroptions[ i ] == NULL ) {
  1093. dsgw_emitf( XP_GetClientStr(DBT_unknownOptionS_), p );
  1094. break;
  1095. }
  1096. }
  1097. free( p );
  1098. }
  1099. return( opts );
  1100. }
  1101. static struct attr_handler *
  1102. syntax2attrhandler( char *syntax )
  1103. {
  1104. int i;
  1105. for ( i = 0; i < DSGW_AH_COUNT; ++i ) {
  1106. if ( strcasecmp( syntax, attrhandlers[ i ].ath_syntax ) == 0 ) {
  1107. return( &attrhandlers[ i ] );
  1108. }
  1109. }
  1110. return( NULL );
  1111. }
  1112. static int
  1113. numfields( int argc, char **argv, int valcount )
  1114. {
  1115. char *s;
  1116. int fields;
  1117. if (( s = get_arg_by_name( DSGW_ATTRARGS_NUMFIELDS, argc,
  1118. argv )) == NULL ) {
  1119. fields = 1;
  1120. } else {
  1121. if ( *s == '+' || *s == ' ') {
  1122. /* "numfields=+N" means show N more than number of values */
  1123. fields = valcount + atoi( s + 1 );
  1124. } else {
  1125. if ( *s == '>' ) ++s;
  1126. /* "numfields=N" or "=>N" means show at least N fields */
  1127. fields = atoi( s );
  1128. }
  1129. }
  1130. if ( fields < 1 ) {
  1131. fields = 1;
  1132. } else if ( fields < valcount ) {
  1133. fields = valcount;
  1134. }
  1135. return( fields );
  1136. }
  1137. /*
  1138. * calculate size of TEXT or TEXTAREA elements based on arguments,
  1139. * the number of values, and the length of longest value.
  1140. */
  1141. static void
  1142. element_sizes( int argc, char **argv, char **vals, int valcount,
  1143. int *rowsp, int *colsp )
  1144. {
  1145. int i, len, maxlen;
  1146. char *s;
  1147. /* set *colsp (number of columns in each input item) */
  1148. if ( colsp != NULL ) {
  1149. /*
  1150. * columns are set using the "cols=N" or "size=N" argument
  1151. * "cols=>N" can be used to indicate at least N columns should be shown
  1152. * "cols=+N" can be used to size to N more than longest value
  1153. * in the absence of any of these, we set columns to one more than
  1154. * the longest value in the "vals" array
  1155. */
  1156. if (( s = get_arg_by_name( DSGW_ATTRARGS_COLS, argc, argv )) == NULL ) {
  1157. s = get_arg_by_name( DSGW_ATTRARGS_SIZE, argc, argv );
  1158. }
  1159. if ( s != NULL && *s != '+' && *s != ' ' && *s != '>' ) {
  1160. *colsp = atoi( s ); /* extact width specified */
  1161. } else if ( valcount == 0 ) {
  1162. if ( s != NULL && *s == '>' ) {
  1163. *colsp = atoi( s + 1 );
  1164. } else {
  1165. *colsp = 0; /* use default width */
  1166. }
  1167. } else {
  1168. /* determine ( length of longest value ) + 1 */
  1169. maxlen = 0;
  1170. for ( i = 0; i < valcount; ++i ) {
  1171. if (( len = strlen( vals[ i ] )) > maxlen ) {
  1172. maxlen = len;
  1173. }
  1174. }
  1175. ++maxlen;
  1176. if ( s != NULL ) {
  1177. i = atoi( s + 1 );
  1178. if ( *s == ' ' || *s == '+' ) {
  1179. maxlen += i;
  1180. } else { /* '>' */
  1181. if ( maxlen < i ) {
  1182. maxlen = i;
  1183. }
  1184. }
  1185. }
  1186. *colsp = maxlen;
  1187. }
  1188. }
  1189. /* set *rowsp (number of rows in each input item) */
  1190. if ( rowsp != NULL ) {
  1191. /*
  1192. * rows are set using "rows=M" ("=>M" and "=+M" are supported also)
  1193. * in the absense of this, we set it to the number of values in the
  1194. * "vals" array
  1195. */
  1196. if (( s = get_arg_by_name( DSGW_ATTRARGS_ROWS, argc, argv )) == NULL ) {
  1197. *rowsp = valcount;
  1198. } else if ( *s == ' ' || *s == '+' ) {
  1199. *rowsp = valcount + atoi( s + 1 );
  1200. } else if ( *s == '>' ) {
  1201. if (( *rowsp = atoi( s + 1 )) < valcount ) {
  1202. *rowsp = valcount;
  1203. }
  1204. } else {
  1205. *rowsp = atoi( s );
  1206. }
  1207. }
  1208. }
  1209. static void
  1210. output_text_elements( int argc, char **argv, char *attr, char **vals,
  1211. const char* rdn, char *prefix, int htmltype, unsigned long opts )
  1212. {
  1213. int i, valcount, fields, cols;
  1214. if ( vals == NULL ) {
  1215. valcount = 0;
  1216. } else {
  1217. for ( valcount = 0; vals[ valcount ] != NULL; ++valcount ) {
  1218. /* just count vals */
  1219. }
  1220. }
  1221. fields = numfields( argc, argv, valcount );
  1222. element_sizes( argc, argv, vals, valcount, NULL, &cols );
  1223. for ( i = 0; i < fields; ++i ) {
  1224. auto const int is_rdn = (i < valcount && vals[ i ] == rdn);
  1225. dsgw_emitf( "<INPUT TYPE=\"%s\"", attrhtmltypes[ htmltype ] );
  1226. dsgw_emitf( " NAME=\"%s%s%s\"", prefix, is_rdn ? "DN_" : "", attr );
  1227. if ( cols > 0 ) {
  1228. dsgw_emitf( " SIZE=%d", cols );
  1229. }
  1230. if ( i < valcount ) {
  1231. dsgw_emitf( " VALUE=\"%s\"", vals[ i ] );
  1232. }
  1233. if (( opts & DSGW_TEXTOPT_CHANGEHANDLERS ) != 0 ) {
  1234. dsgw_emitf( " onChange=\"aChg('%s')\"", is_rdn ? "DN" : attr );
  1235. }
  1236. if (( opts & DSGW_TEXTOPT_FOCUSHANDLERS ) != 0 ) {
  1237. dsgw_emitf( " onFocus=\"aFoc('%s')\"", is_rdn ? "DN" : attr );
  1238. }
  1239. dsgw_emitf( ">%s\n%s",
  1240. is_rdn ? " DN" : "",
  1241. ( i < fields - 1 &&
  1242. htmltype != DSGW_ATTRHTML_HIDDEN ) ? "<BR>\n" : "" );
  1243. }
  1244. }
  1245. static void
  1246. output_textarea( int argc, char **argv, char *attr, char **vals,
  1247. int valcount, char *prefix, unsigned long opts )
  1248. {
  1249. int i, rows, cols;
  1250. element_sizes( argc, argv, vals, valcount, &rows, &cols );
  1251. dsgw_emits( "<TEXTAREA" );
  1252. dsgw_emitf( " NAME=\"%s%s\"", prefix, attr );
  1253. if ( rows > 0 ) {
  1254. if ( rows == 1 ) {
  1255. rows = 2; /* one line TEXTAREAs are ugly! */
  1256. }
  1257. dsgw_emitf( " ROWS=%d", rows );
  1258. }
  1259. if ( cols > 0 ) {
  1260. dsgw_emitf( " COLS=%d", cols );
  1261. }
  1262. if (( opts & DSGW_TEXTOPT_CHANGEHANDLERS ) != 0 ) {
  1263. dsgw_emitf( " onChange=\"aChg('%s')\"", attr );
  1264. }
  1265. if (( opts & DSGW_TEXTOPT_FOCUSHANDLERS ) != 0 ) {
  1266. dsgw_emitf( " onFocus=\"aFoc('%s')\"", attr );
  1267. }
  1268. dsgw_emits( ">\n" );
  1269. for ( i = 0; i < valcount; ++i ) {
  1270. dsgw_emits( vals[ i ] );
  1271. dsgw_emits( "\n" );
  1272. }
  1273. dsgw_emits( "</TEXTAREA>\n" );
  1274. }
  1275. static void
  1276. output_text_checkbox_or_radio( struct dsgw_attrdispinfo *adip, char *prefix,
  1277. int htmltype )
  1278. {
  1279. int i, checked;
  1280. char *value;
  1281. /*
  1282. * for checkboxes or radio buttons that are associated with string values,
  1283. * we "check the box" if the value found in the "value=XXX" parameter is
  1284. * present.
  1285. */
  1286. checked = 0;
  1287. if (( value = get_arg_by_name( DSGW_ATTRARGS_VALUE, adip->adi_argc,
  1288. adip->adi_argv )) == NULL ) {
  1289. value = "TRUE"; /* assume LDAP Boolean value */
  1290. }
  1291. if ( adip->adi_vals == NULL ) {
  1292. if ( *value == '\0' ) {
  1293. /*
  1294. * There are no existing values in the entry and this checkbox or
  1295. * radio button has a zero-length value associated with it. We
  1296. * check this box/enable this radio button as a special case to
  1297. * support an "off" or "none of the rest" scenario.
  1298. */
  1299. checked = 1;
  1300. }
  1301. } else {
  1302. for ( i = 0; adip->adi_vals[ i ] != NULL; ++i ) {
  1303. if ( dsgw_valcmp(adip->adi_handlerp->ath_compare)( (const char **)&value,
  1304. (const char **)&(adip->adi_vals[ i ]) ) == 0 ) {
  1305. checked = 1;
  1306. break;
  1307. }
  1308. }
  1309. }
  1310. dsgw_emitf( "<INPUT TYPE=\"%s\" NAME=\"%s%s\" "
  1311. "VALUE=\"%s\"%s onClick=\"aChg('%s')\">\n",
  1312. ( htmltype == DSGW_ATTRHTML_RADIO ) ? "radio" : "checkbox",
  1313. prefix, adip->adi_attr, value, checked ? " CHECKED" : "",
  1314. adip->adi_attr );
  1315. }
  1316. static void
  1317. emit_value( char *val, int quote_html_specials )
  1318. {
  1319. int freeit;
  1320. if ( quote_html_specials ) {
  1321. val = dsgw_strdup_with_entities( val, &freeit );
  1322. } else {
  1323. freeit = 0;
  1324. }
  1325. dsgw_emits( val );
  1326. if ( freeit ) {
  1327. free( val );
  1328. }
  1329. }
  1330. /*
  1331. * Default display handler for binary values
  1332. */
  1333. static void
  1334. binvalue_display( struct dsgw_attrdispinfo *adip )
  1335. {
  1336. int i;
  1337. struct berval **list_of_binvals;
  1338. char *checked = " CHECKED";
  1339. char *selected = " SELECTED";
  1340. int iValue;
  1341. list_of_binvals = (struct berval **)adip->adi_vals;
  1342. for ( i = 0; list_of_binvals[ i ] != NULL; ++i )
  1343. {
  1344. char szFlags[512], szFormat[512];
  1345. struct berval bin_data = *list_of_binvals[i];
  1346. if( !bin_data.bv_val || !bin_data.bv_len )
  1347. continue;
  1348. /* Now interpret the binary value if it has NT semantics */
  1349. if( !strcasecmp( adip->adi_attr, "ntuserpriv") )
  1350. {
  1351. memcpy( &iValue, bin_data.bv_val, sizeof( iValue ) );
  1352. fprintf( stdout, "<INPUT TYPE=\"radio\" NAME=\"%s\" "
  1353. "VALUE=\"TRUE\"%s>%s<BR>\n", adip->adi_attr,
  1354. (iValue == USER_PRIV_GUEST) ? checked : "", DSGW_NT_UP_GUEST);
  1355. fprintf( stdout, "<INPUT TYPE=\"radio\" NAME=\"%s\" "
  1356. "VALUE=\"TRUE\"%s>%s<BR>\n", adip->adi_attr,
  1357. (iValue == USER_PRIV_USER) ? checked : "", DSGW_NT_UP_USER);
  1358. fprintf( stdout, "<INPUT TYPE=\"radio\" NAME=\"%s\" "
  1359. "VALUE=\"TRUE\"%s>%s<BR>\n", adip->adi_attr,
  1360. (iValue == USER_PRIV_ADMIN) ? checked : "", DSGW_NT_UP_ADMIN);
  1361. }
  1362. else if ( strcasecmp( adip->adi_attr, "ntuserflags" ) == 0 )
  1363. {
  1364. memcpy( &iValue, bin_data.bv_val, sizeof( iValue ) );
  1365. fprintf( stdout, "<FONT size=-1><SELECT MULTIPLE name=\"%s\" size=5>\n", adip->adi_attr);
  1366. fprintf( stdout, "<OPTION value=\"%s\" %s>%s\n", DSGW_NT_UF_SCRIPT,
  1367. (iValue & UF_SCRIPT) ? selected : "", DSGW_NT_UF_SCRIPT );
  1368. fprintf( stdout, "<OPTION value=\"%s\" %s>%s\n", DSGW_NT_UF_ACCOUNT_DISABLED,
  1369. (iValue & UF_ACCOUNTDISABLE) ? selected : "",
  1370. DSGW_NT_UF_ACCOUNT_DISABLED);
  1371. fprintf( stdout, "<OPTION value=\"%s\" %s>%s\n", DSGW_NT_UF_HOMEDIR_REQD,
  1372. (iValue & UF_HOMEDIR_REQUIRED) ? selected : "",
  1373. DSGW_NT_UF_HOMEDIR_REQD);
  1374. fprintf( stdout, "<OPTION value=\"%s\" %s>%s\n", DSGW_NT_UF_PASSWD_NOTREQD,
  1375. (iValue & UF_PASSWD_NOTREQD) ? selected : "",
  1376. DSGW_NT_UF_PASSWD_NOTREQD);
  1377. fprintf( stdout, "<OPTION value=\"%s\" %s>%s\n", DSGW_NT_UF_PASSWD_CANT_CHANGE,
  1378. (iValue & UF_PASSWD_CANT_CHANGE) ? selected : "",
  1379. DSGW_NT_UF_PASSWD_CANT_CHANGE);
  1380. fprintf( stdout, "<OPTION value=\"%s\" %s>%s\n", DSGW_NT_UF_LOCKOUT,
  1381. (iValue & UF_LOCKOUT) ? selected : "", DSGW_NT_UF_LOCKOUT);
  1382. fprintf( stdout, "<OPTION value=\"%s\" %s>%s\n", DSGW_NT_UF_DONT_EXPIRE_PASSWORD,
  1383. (iValue & UF_DONT_EXPIRE_PASSWD) ? selected : "",
  1384. DSGW_NT_UF_DONT_EXPIRE_PASSWORD);
  1385. fprintf( stdout, "<OPTION value=\"%s\" %s>%s\n", DSGW_NT_UF_NORMAL_ACCOUNT,
  1386. (iValue & UF_NORMAL_ACCOUNT) ? selected : "",
  1387. DSGW_NT_UF_NORMAL_ACCOUNT);
  1388. fprintf( stdout, "<OPTION value=\"%s\" %s>%s\n", DSGW_NT_UF_TEMP_DUPLICATE_ACCOUNT,
  1389. (iValue & UF_TEMP_DUPLICATE_ACCOUNT) ? selected : "",
  1390. DSGW_NT_UF_TEMP_DUPLICATE_ACCOUNT);
  1391. fprintf( stdout, "<OPTION value=\"%s\" %s>%s\n", DSGW_NT_UF_TEMP_WRKSTN_TRUST_ACCOUNT,
  1392. (iValue & UF_WORKSTATION_TRUST_ACCOUNT) ? selected : "",
  1393. DSGW_NT_UF_TEMP_WRKSTN_TRUST_ACCOUNT);
  1394. fprintf( stdout, "<OPTION value=\"%s\" %s>%s\n", DSGW_NT_UF_TEMP_SERVER_TRUST_ACCOUNT,
  1395. (iValue & UF_SERVER_TRUST_ACCOUNT) ? selected : "",
  1396. DSGW_NT_UF_TEMP_SERVER_TRUST_ACCOUNT);
  1397. fprintf( stdout, "<OPTION value=\"%s\" %s>%s\n", DSGW_NT_UF_TEMP_INTERDOMAIN_TRUST_ACCOUNT,
  1398. (iValue & UF_INTERDOMAIN_TRUST_ACCOUNT) ? selected : "",
  1399. DSGW_NT_UF_TEMP_INTERDOMAIN_TRUST_ACCOUNT);
  1400. fprintf( stdout, "</SELECT><FONT size=+1>\n" );
  1401. }
  1402. else if ( strcasecmp( adip->adi_attr, "ntuserauthflags" ) == 0 )
  1403. {
  1404. memcpy( &iValue, bin_data.bv_val, sizeof( iValue ) );
  1405. fprintf( stdout, "<FONT size=-1><SELECT MULTIPLE name=\"%s\" "
  1406. "size=4>\n", adip->adi_attr);
  1407. fprintf( stdout, "<OPTION value=\"%s\" %s>%s\n", DSGW_NT_AF_OP_PRINT,
  1408. (iValue & AF_OP_PRINT) ? selected : "", DSGW_NT_AF_OP_PRINT);
  1409. fprintf( stdout, "<OPTION value=\"%s\" %s>%s\n", DSGW_NT_AF_OP_COMM,
  1410. (iValue & AF_OP_COMM) ? selected : "", DSGW_NT_AF_OP_COMM);
  1411. fprintf( stdout, "<OPTION value=\"%s\" %s>%s\n", DSGW_NT_AF_OP_SERVER,
  1412. (iValue & AF_OP_SERVER) ? selected : "", DSGW_NT_AF_OP_SERVER);
  1413. fprintf( stdout, "<OPTION value=\"%s\" %s>%s\n", DSGW_NT_AF_OP_ACCOUNTS,
  1414. (iValue & AF_OP_ACCOUNTS) ? selected : "", DSGW_NT_AF_OP_ACCOUNTS);
  1415. fprintf( stdout, "</SELECT><FONT size=+1>\n" );
  1416. }
  1417. else if ( bin_data.bv_val && ( bin_data.bv_len != 0 ))
  1418. {
  1419. if( bin_data.bv_len == 4 )
  1420. {
  1421. memcpy( &iValue, bin_data.bv_val, sizeof( iValue ) );
  1422. if(( adip->adi_opts & DSGW_ATTROPT_DECIMAL ) != 0 )
  1423. PR_snprintf( szFormat, 512, "%%lu" );
  1424. else
  1425. PR_snprintf( szFormat, 512, "%%#0%lu.%lux", bin_data.bv_len*2, bin_data.bv_len*2 );
  1426. PR_snprintf( szFlags, 512, szFormat, iValue );
  1427. fputs( szFlags, stdout );
  1428. if ( list_of_binvals[ i + 1 ] != NULL )
  1429. {
  1430. fputs( "<BR>\n", stdout );
  1431. }
  1432. }
  1433. }
  1434. }
  1435. }
  1436. /*
  1437. * display handler for NT Domain Identifier string
  1438. */
  1439. static void
  1440. ntdomain_display( struct dsgw_attrdispinfo *adip )
  1441. {
  1442. int i;
  1443. /* Write values with a break (<BR>) separating them,
  1444. removing all after ":" */
  1445. for ( i = 0; adip->adi_vals[ i ] != NULL; ++i ) {
  1446. if ( !did_output_as_special( adip->adi_argc, adip->adi_argv,
  1447. adip->adi_vals[ i ], adip->adi_vals[ i ] )) {
  1448. char *pch = strchr( adip->adi_vals[ i ], DSGW_NTDOMAINID_SEP );
  1449. if( pch )
  1450. *pch = (char )NULL;
  1451. if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
  1452. dsgw_emits( "\"" );
  1453. }
  1454. fputs( adip->adi_vals[ i ], stdout );
  1455. if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
  1456. dsgw_emits( "\"" );
  1457. }
  1458. }
  1459. if ( adip->adi_vals[ i + 1 ] != NULL ) {
  1460. fputs( "<BR>\n", stdout );
  1461. }
  1462. }
  1463. }
  1464. /*
  1465. * display handler for simple strings
  1466. */
  1467. static void
  1468. str_display( struct dsgw_attrdispinfo *adip )
  1469. {
  1470. int i;
  1471. if ( adip->adi_htmltype == DSGW_ATTRHTML_CHECKBOX ||
  1472. adip->adi_htmltype == DSGW_ATTRHTML_RADIO ) {
  1473. output_text_checkbox_or_radio( adip, "", adip->adi_htmltype );
  1474. return;
  1475. }
  1476. /* just write values with a break (<BR>) separating them */
  1477. for ( i = 0; adip->adi_vals[ i ] != NULL; ++i ) {
  1478. if ( !did_output_as_special( adip->adi_argc, adip->adi_argv,
  1479. adip->adi_vals[ i ], adip->adi_vals[ i ] ) &&
  1480. adip->adi_htmltype != DSGW_ATTRHTML_HIDDEN ) {
  1481. if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
  1482. dsgw_emits( "\"" );
  1483. }
  1484. emit_value( adip->adi_vals[ i ],
  1485. (( adip->adi_opts & DSGW_ATTROPT_NO_ENTITIES ) == 0 ));
  1486. if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
  1487. dsgw_emits( "\"" );
  1488. }
  1489. }
  1490. if ( adip->adi_htmltype != DSGW_ATTRHTML_HIDDEN &&
  1491. adip->adi_vals[ i + 1 ] != NULL ) {
  1492. dsgw_emits( "<BR>\n" );
  1493. }
  1494. }
  1495. }
  1496. static void
  1497. ntuserid_display( struct dsgw_attrdispinfo *adip )
  1498. {
  1499. int i;
  1500. for ( i = 0; adip->adi_vals[ i ] != NULL; ++i ) {
  1501. if ( !did_output_as_special( adip->adi_argc, adip->adi_argv,
  1502. adip->adi_vals[ i ], adip->adi_vals[ i ] )) {
  1503. char *pch = adip->adi_vals[ i ];
  1504. if( pch ) {
  1505. if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
  1506. dsgw_emits( "\"" );
  1507. }
  1508. fputs( pch, stdout );
  1509. if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
  1510. dsgw_emits( "\"" );
  1511. }
  1512. }
  1513. }
  1514. if ( adip->adi_vals[ i + 1 ] != NULL ) {
  1515. fputs( "<BR>\n", stdout );
  1516. }
  1517. }
  1518. }
  1519. /*
  1520. * edit handler for simple strings
  1521. */
  1522. static void
  1523. str_edit( struct dsgw_attrdispinfo *adip )
  1524. {
  1525. int valcount, adding, pre_idx;
  1526. char *prefix;
  1527. unsigned long textopts;
  1528. adding = (( adip->adi_opts & DSGW_ATTROPT_ADDING ) != 0 );
  1529. if (( adip->adi_opts & DSGW_ATTROPT_UNIQUE ) == 0 ) {
  1530. pre_idx = DSGW_MOD_PREFIX_NORMAL;
  1531. } else {
  1532. pre_idx = DSGW_MOD_PREFIX_UNIQUE;
  1533. }
  1534. prefix = adding ? add_prefixes[ pre_idx ] : replace_prefixes[ pre_idx ];
  1535. textopts = DSGW_TEXTOPT_CHANGEHANDLERS;
  1536. if ( !adding ) {
  1537. textopts |= DSGW_TEXTOPT_FOCUSHANDLERS;
  1538. }
  1539. switch( adip->adi_htmltype ) {
  1540. case DSGW_ATTRHTML_TEXTAREA:
  1541. if ( adip->adi_vals == NULL ) {
  1542. valcount = 0;
  1543. } else {
  1544. for ( valcount = 0; adip->adi_vals[ valcount ] != NULL;
  1545. ++valcount ) {
  1546. ;
  1547. }
  1548. }
  1549. output_textarea( adip->adi_argc, adip->adi_argv, adip->adi_attr,
  1550. adip->adi_vals, valcount, prefix, textopts );
  1551. break;
  1552. case DSGW_ATTRHTML_TEXT:
  1553. case DSGW_ATTRHTML_HIDDEN:
  1554. output_text_elements( adip->adi_argc, adip->adi_argv, adip->adi_attr,
  1555. adip->adi_vals, adip->adi_rdn, prefix, adip->adi_htmltype, textopts );
  1556. break;
  1557. case DSGW_ATTRHTML_CHECKBOX:
  1558. case DSGW_ATTRHTML_RADIO:
  1559. output_text_checkbox_or_radio( adip, prefix, adip->adi_htmltype );
  1560. break;
  1561. default:
  1562. dsgw_emitf( XP_GetClientStr(DBT_HtmlTypeSNotSupportedBrN_),
  1563. attrhtmltypes[ adip->adi_htmltype ] );
  1564. }
  1565. }
  1566. /*
  1567. * display handler for multi-line strings, e.g. postalAddress
  1568. * these are funny in that over LDAP, lines are separated by " $ "
  1569. * this only support "htmltype=text"
  1570. */
  1571. static void
  1572. mls_display( struct dsgw_attrdispinfo *adip )
  1573. {
  1574. int i;
  1575. for ( i = 0; adip->adi_vals[ i ] != NULL; ++i ) {
  1576. if ( !did_output_as_special( adip->adi_argc, adip->adi_argv,
  1577. adip->adi_vals[ i ], adip->adi_vals[ i ] )) {
  1578. (void)dsgw_mls_convertlines( adip->adi_vals[ i ], "<BR>\n", NULL,
  1579. 1, ( adip->adi_opts & DSGW_ATTROPT_NO_ENTITIES ) == 0 );
  1580. }
  1581. if ( adip->adi_vals[ i + 1 ] != NULL ) {
  1582. dsgw_emits( "<BR><BR>\n" );
  1583. }
  1584. }
  1585. }
  1586. /*
  1587. * edit handler for multi-line strings
  1588. */
  1589. static void
  1590. mls_edit( struct dsgw_attrdispinfo *adip )
  1591. {
  1592. char *prefix, **valscopy, *tval[ 2 ];
  1593. int i, valcount, adding, pre_idx, *lines;
  1594. unsigned long textopts;
  1595. adding = (( adip->adi_opts & DSGW_ATTROPT_ADDING ) != 0 );
  1596. textopts = DSGW_TEXTOPT_CHANGEHANDLERS;
  1597. if ( !adding ) {
  1598. textopts |= DSGW_TEXTOPT_FOCUSHANDLERS;
  1599. }
  1600. if (( adip->adi_opts & DSGW_ATTROPT_UNIQUE ) == 0 ) {
  1601. pre_idx = DSGW_MOD_PREFIX_NORMAL;
  1602. } else {
  1603. pre_idx = DSGW_MOD_PREFIX_UNIQUE;
  1604. }
  1605. prefix = adding ? add_mls_prefixes[ pre_idx ] :
  1606. replace_mls_prefixes[ pre_idx ];
  1607. if ( adip->adi_vals == NULL ) {
  1608. valscopy = NULL;
  1609. } else {
  1610. for ( valcount = 0; adip->adi_vals[ valcount ] != NULL; ++valcount ) {
  1611. ;
  1612. }
  1613. valscopy = (char **)dsgw_ch_malloc( (valcount + 1) * sizeof( char * ));
  1614. lines = (int *)dsgw_ch_malloc( valcount * sizeof( int ));
  1615. for ( i = 0; i < valcount; ++i ) {
  1616. valscopy[ i ] = dsgw_mls_convertlines( adip->adi_vals[ i ], "\n",
  1617. &lines[ i ], 0, 0 );
  1618. }
  1619. valscopy[ valcount ] = NULL;
  1620. }
  1621. if ( adip->adi_htmltype == DSGW_ATTRHTML_TEXTAREA ) {
  1622. if ( adip->adi_vals == NULL ) {
  1623. output_textarea( adip->adi_argc, adip->adi_argv, adip->adi_attr,
  1624. NULL, 0, prefix, textopts );
  1625. } else {
  1626. tval[ 1 ] = NULL;
  1627. for ( i = 0; i < valcount; ++i ) {
  1628. tval[ 0 ] = valscopy[ i ];
  1629. output_textarea( adip->adi_argc, adip->adi_argv,
  1630. adip->adi_attr, tval, 1, prefix, textopts );
  1631. if ( i < valcount - 1 ) {
  1632. dsgw_emits( "<BR>\n" );
  1633. }
  1634. }
  1635. }
  1636. } else {
  1637. output_text_elements( adip->adi_argc, adip->adi_argv, adip->adi_attr,
  1638. valscopy, NULL, prefix, adip->adi_htmltype, textopts );
  1639. /* Bug: what if adip->adi_rdn != NULL? In this case,
  1640. the element of valscopy that is a copy of adi_rdn
  1641. should be passed to output_text_elements (as the rdn).
  1642. */
  1643. }
  1644. if ( valscopy != NULL ) {
  1645. ldap_value_free( valscopy );
  1646. free( lines );
  1647. }
  1648. }
  1649. /*
  1650. * convert all occurrences of "$" in val to sep
  1651. * un-escape any \HH sequences
  1652. * if linesp != NULL, set *linesp equal to number of lines in val
  1653. * if emitlines is zero, a malloc'd string is returned.
  1654. * if emitlines is non-zero, values are written to stdout (respecting the
  1655. * quote_html_specials flag) and NULL is returned.
  1656. */
  1657. char *
  1658. dsgw_mls_convertlines( char *val, char *sep, int *linesp, int emitlines,
  1659. int quote_html_specials )
  1660. {
  1661. char *valcopy, *p, *q, *curline;
  1662. int i, c, lines, seplen;
  1663. if ( sep == NULL ) {
  1664. sep = "";
  1665. seplen = 0;
  1666. } else {
  1667. seplen = strlen( sep );
  1668. }
  1669. lines = 0;
  1670. for ( q = val; *q != '\0'; ++q ) {
  1671. if ( *q == '$' ) {
  1672. ++lines;
  1673. }
  1674. }
  1675. if ( linesp != NULL ) {
  1676. *linesp = lines;
  1677. }
  1678. valcopy = dsgw_ch_malloc( strlen( val ) + lines * seplen + 1 );
  1679. /*
  1680. * p points to the place we are copying to
  1681. * q points to the place within the original value that we are examining
  1682. * curline points to the start of the current line
  1683. */
  1684. p = curline = valcopy;
  1685. for ( q = val; *q != '\0'; ++q ) {
  1686. if ( *q == '$' ) { /* line separator */
  1687. if ( emitlines ) {
  1688. *p = '\0';
  1689. emit_value( curline, quote_html_specials );
  1690. emit_value( sep, 0 );
  1691. }
  1692. strcpy( p, sep );
  1693. p += seplen;
  1694. curline = p;
  1695. } else if ( *q == '\\' ) { /* undo hex escapes */
  1696. if ( *++q == '\0' ) {
  1697. break;
  1698. }
  1699. c = toupper( *q );
  1700. i = ( c >= 'A' ? ( c - 'A' + 10 ) : c - '0' );
  1701. i <<= 4;
  1702. if ( *++q == '\0' ) {
  1703. break;
  1704. }
  1705. c = toupper( *q );
  1706. i += ( c >= 'A' ? ( c - 'A' + 10 ) : c - '0' );
  1707. *p++ = i;
  1708. } else {
  1709. *p++ = *q;
  1710. }
  1711. }
  1712. *p = '\0';
  1713. if ( emitlines ) {
  1714. if ( p > curline ) {
  1715. emit_value( curline, quote_html_specials );
  1716. }
  1717. free( valcopy );
  1718. valcopy = NULL;
  1719. }
  1720. return( valcopy );
  1721. }
  1722. static void
  1723. dn_edit( struct dsgw_attrdispinfo *adip )
  1724. {
  1725. if (( adip->adi_opts & DSGW_ATTROPT_DNPICKER ) != 0 ) {
  1726. dn_display( adip );
  1727. } else {
  1728. str_edit( adip );
  1729. }
  1730. return;
  1731. }
  1732. static void
  1733. dn_display( struct dsgw_attrdispinfo *adip )
  1734. {
  1735. int i, j, len, dncomps;
  1736. char *p, *staticlabel, *tmps = NULL, *label, *urlprefix, **rdns = NULL;
  1737. staticlabel = get_arg_by_name( DSGW_ATTRARG_LABEL, adip->adi_argc,
  1738. adip->adi_argv );
  1739. if (( p = get_arg_by_name( DSGW_ATTRARG_DNCOMP, adip->adi_argc,
  1740. adip->adi_argv )) == NULL ) {
  1741. dncomps = 1;
  1742. } else {
  1743. dncomps = atoi( p ); /* 0 or "all" means show all components */
  1744. }
  1745. if (( adip->adi_opts & DSGW_ATTROPT_LINK2EDIT ) != 0 ) {
  1746. auto const char* vp = dsgw_getvp( DSGW_CGINUM_EDIT );
  1747. /* urlprefix = vp + "?&context=CONTEXT&dn=": */
  1748. auto const size_t vplen = strlen (vp);
  1749. urlprefix = dsgw_ch_malloc (vplen + 6 + strlen(context) + 9);
  1750. memcpy( urlprefix, vp, vplen );
  1751. strcat( urlprefix, "?&context=");
  1752. strcat( urlprefix, context);
  1753. strcat( urlprefix, "&dn=");
  1754. } else {
  1755. urlprefix = dsgw_build_urlprefix();
  1756. }
  1757. #ifdef DSGW_DEBUG
  1758. dsgw_log( "dn_display: urlprefix is %s\n", urlprefix );
  1759. #endif
  1760. for ( i = 0; adip->adi_vals != NULL && adip->adi_vals[ i ] != NULL; ++i ) {
  1761. if ( staticlabel != NULL ) {
  1762. label = staticlabel;
  1763. } else if ( !looks_like_dn( adip->adi_vals[ i ]) ||
  1764. ( rdns = ldap_explode_dn( adip->adi_vals[ i ],
  1765. ( adip->adi_opts & DSGW_ATTROPT_DNTAGS ) == 0 )) == NULL ) {
  1766. /* explode DN failed -- show entire DN */
  1767. label = adip->adi_vals[ i ];
  1768. tmps = NULL;
  1769. } else {
  1770. len = 1; /* room for zero-termination */
  1771. for ( j = 0; rdns[ j ] != NULL && ( dncomps == 0 || j < dncomps );
  1772. ++ j ) {
  1773. len += ( 2 + strlen( rdns[ j ] )); /* rdn + ", " */
  1774. }
  1775. label = p = tmps = dsgw_ch_malloc( len );
  1776. for ( j = 0; rdns[ j ] != NULL && ( dncomps == 0 || j < dncomps );
  1777. ++ j ) {
  1778. if ( j > 0 ) {
  1779. strcpy( p, ", " );
  1780. p += 2;
  1781. }
  1782. strcpy( p, rdns[ j ] );
  1783. p += strlen( p );
  1784. }
  1785. }
  1786. if ( !did_output_as_special( adip->adi_argc, adip->adi_argv, label,
  1787. adip->adi_vals[ i ] )) {
  1788. if (( adip->adi_opts & DSGW_ATTROPT_NOLINK ) == 0 &&
  1789. looks_like_dn( adip->adi_vals[ i ] )) {
  1790. if (( adip->adi_opts & DSGW_ATTROPT_DNPICKER ) != 0 ) {
  1791. dsgw_emits( "<TR><TD>" );
  1792. }
  1793. /* Don't display a link for the rootdn */
  1794. if ( gc->gc_rootdn && dsgw_dn_cmp(adip->adi_vals[i], gc->gc_rootdn)) {
  1795. if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
  1796. dsgw_emits( "\"" );
  1797. }
  1798. dsgw_emits( label );
  1799. if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
  1800. dsgw_emits( "\"" );
  1801. }
  1802. } else {
  1803. dsgw_html_href( urlprefix, adip->adi_vals[ i ], label,
  1804. adip->adi_vals[ i ],
  1805. get_arg_by_name( DSGW_ATTRARG_HREFEXTRA,
  1806. adip->adi_argc, adip->adi_argv ));
  1807. }
  1808. if (( adip->adi_opts & DSGW_ATTROPT_DNPICKER ) != 0 ) {
  1809. dsgw_emits( "</TD>\n<TD ALIGN=CENTER><INPUT TYPE=CHECKBOX " );
  1810. dsgw_emitf( "VALUE=\"%s\" NAME=delete_%s ",
  1811. adip->adi_vals[ i ], adip->adi_attr );
  1812. dsgw_emitf( "onClick=\"aChg('%s');\"</TD>\n</TR>\n",
  1813. adip->adi_attr );
  1814. }
  1815. } else {
  1816. if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
  1817. dsgw_emits( "\"" );
  1818. }
  1819. emit_value( label,
  1820. (( adip->adi_opts & DSGW_ATTROPT_NO_ENTITIES ) == 0 ));
  1821. if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
  1822. dsgw_emits( "\"" );
  1823. }
  1824. }
  1825. }
  1826. if ( !( adip->adi_opts & DSGW_ATTROPT_DNPICKER ) &&
  1827. adip->adi_vals[ i + 1 ] != NULL ) {
  1828. dsgw_emits( "<BR>\n" );
  1829. }
  1830. if ( tmps != NULL ) {
  1831. free( tmps );
  1832. }
  1833. if ( rdns != NULL ) {
  1834. ldap_value_free( rdns );
  1835. }
  1836. }
  1837. /* Output a javascript array of values for this attribute */
  1838. if (( adip->adi_opts & DSGW_ATTROPT_DNPICKER ) != 0 ) {
  1839. dsgw_emits( "<SCRIPT LANGUAGE=\"JavaScript\">\n" );
  1840. dsgw_emits( "<!-- Hide from non-JavaScript-capable browsers\n" );
  1841. dsgw_emitf( "var %s_values = new Object;\n", adip->adi_attr );
  1842. for ( i = 0; adip->adi_vals != NULL && adip->adi_vals[ i ] != NULL; ++i ) {
  1843. char *edn;
  1844. edn = dsgw_strdup_escaped( adip->adi_vals[ i ]);
  1845. dsgw_emitf( "%s_values[%d] = \"%s\";\n", adip->adi_attr, i,
  1846. edn );
  1847. free( edn );
  1848. }
  1849. dsgw_emitf( "%s_values.count = %d;\n", adip->adi_attr, i );
  1850. dsgw_emits( "// End hiding -->\n" );
  1851. dsgw_emits( "</SCRIPT>\n" );
  1852. }
  1853. free( urlprefix );
  1854. }
  1855. static void
  1856. mail_display( struct dsgw_attrdispinfo *adip )
  1857. {
  1858. int i;
  1859. for ( i = 0; adip->adi_vals[ i ] != NULL; ++i ) {
  1860. if ( !did_output_as_special( adip->adi_argc, adip->adi_argv,
  1861. adip->adi_vals[ i ], adip->adi_vals[ i ] )) {
  1862. if (( adip->adi_opts & DSGW_ATTROPT_NOLINK ) == 0 ) {
  1863. dsgw_html_href( "mailto:", adip->adi_vals[ i ], adip->adi_vals[ i ], NULL,
  1864. get_arg_by_name( DSGW_ATTRARG_HREFEXTRA,
  1865. adip->adi_argc, adip->adi_argv ));
  1866. } else {
  1867. if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
  1868. dsgw_emits( "\"" );
  1869. }
  1870. emit_value( adip->adi_vals[ i ],
  1871. (( adip->adi_opts & DSGW_ATTROPT_NO_ENTITIES ) == 0 ));
  1872. if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
  1873. dsgw_emits( "\"" );
  1874. }
  1875. }
  1876. }
  1877. if ( adip->adi_vals[ i + 1 ] != NULL ) {
  1878. dsgw_emits( "<BR>\n" );
  1879. }
  1880. }
  1881. }
  1882. static void
  1883. url_display( struct dsgw_attrdispinfo *adip )
  1884. {
  1885. int i;
  1886. char *savep, *label;
  1887. for ( i = 0; adip->adi_vals[ i ] != NULL; ++i ) {
  1888. if (( label = strchr( adip->adi_vals[ i ], ' ' )) == NULL ) {
  1889. label = adip->adi_vals[ i ];
  1890. savep = NULL;
  1891. } else {
  1892. savep = label;
  1893. *label++ = '\0';
  1894. }
  1895. if ( !did_output_as_special( adip->adi_argc, adip->adi_argv, label,
  1896. adip->adi_vals[ i ] )) {
  1897. if (( adip->adi_opts & DSGW_ATTROPT_NOLINK ) == 0 ) {
  1898. dsgw_html_href( NULL, adip->adi_vals[ i ], label, NULL,
  1899. get_arg_by_name( DSGW_ATTRARG_HREFEXTRA,
  1900. adip->adi_argc, adip->adi_argv ));
  1901. } else {
  1902. if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
  1903. dsgw_emits( "\"" );
  1904. }
  1905. emit_value( adip->adi_vals[ i ],
  1906. (( adip->adi_opts & DSGW_ATTROPT_NO_ENTITIES ) == 0 ));
  1907. if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
  1908. dsgw_emits( "\"" );
  1909. }
  1910. }
  1911. }
  1912. if ( savep != NULL ) {
  1913. *savep = ' ';
  1914. }
  1915. if ( adip->adi_vals[ i + 1 ] != NULL ) {
  1916. dsgw_emits( "<BR>\n" );
  1917. }
  1918. }
  1919. }
  1920. static void
  1921. bool_display( struct dsgw_attrdispinfo *adip )
  1922. {
  1923. int boolval, free_onclick, pre_idx;
  1924. char *usestr, *truestr, *falsestr, *checked;
  1925. char *nameprefix, *onclick;
  1926. if ( adip->adi_vals == NULL || adip->adi_vals[ 0 ] == NULL ) {
  1927. return;
  1928. }
  1929. checked = " CHECKED";
  1930. if (( adip->adi_opts & DSGW_ATTROPT_EDITABLE ) == 0 ) {
  1931. nameprefix = onclick = "";
  1932. free_onclick = 0;
  1933. } else {
  1934. char *onclickfmt = " onClick=\"aChg('%s')\"";
  1935. if (( adip->adi_opts & DSGW_ATTROPT_UNIQUE ) == 0 ) {
  1936. pre_idx = DSGW_MOD_PREFIX_NORMAL;
  1937. } else {
  1938. pre_idx = DSGW_MOD_PREFIX_UNIQUE;
  1939. }
  1940. nameprefix = (( adip->adi_opts & DSGW_ATTROPT_ADDING ) == 0 ) ?
  1941. replace_prefixes[ pre_idx ] : add_prefixes[ pre_idx ];
  1942. onclick = dsgw_ch_malloc( strlen( onclickfmt ) +
  1943. strlen( adip->adi_attr ) + 1 );
  1944. sprintf( onclick, onclickfmt, adip->adi_attr );
  1945. free_onclick = 1;
  1946. }
  1947. if (( truestr = get_arg_by_name( DSGW_ATTRARG_TRUESTR, adip->adi_argc,
  1948. adip->adi_argv )) == NULL ) {
  1949. truestr = DSGW_ATTRARG_TRUESTR;
  1950. }
  1951. if (( falsestr = get_arg_by_name( DSGW_ATTRARG_FALSESTR, adip->adi_argc,
  1952. adip->adi_argv )) == NULL ) {
  1953. falsestr = DSGW_ATTRARG_FALSESTR;
  1954. }
  1955. boolval = ( toupper( adip->adi_vals[ 0 ][ 0 ] ) == 'T' );
  1956. if ( adip->adi_htmltype == DSGW_ATTRHTML_RADIO ) {
  1957. dsgw_emitf( "<INPUT TYPE=\"radio\" NAME=\"%s%s\" "
  1958. "VALUE=\"TRUE\"%s%s>%s<BR>\n", nameprefix, adip->adi_attr,
  1959. boolval ? checked : "", onclick, truestr );
  1960. dsgw_emitf( "<INPUT TYPE=\"radio\" NAME=\"%s%s\" "
  1961. "VALUE=\"FALSE\"%s%s>%s<BR>\n", nameprefix, adip->adi_attr,
  1962. boolval ? "" : checked, onclick, falsestr );
  1963. } else if ( adip->adi_htmltype == DSGW_ATTRHTML_CHECKBOX ) {
  1964. dsgw_emitf( "<INPUT TYPE=\"checkbox\" NAME=\"%s%s\" "
  1965. "VALUE=\"TRUE\"%s%s\">%s\n", nameprefix, adip->adi_attr,
  1966. boolval ? checked : "", onclick, truestr );
  1967. } else {
  1968. usestr = boolval ? truestr : falsestr;
  1969. if ( !did_output_as_special( adip->adi_argc, adip->adi_argv, usestr,
  1970. adip->adi_vals[ 0 ] )) {
  1971. if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
  1972. dsgw_emits( "\"" );
  1973. }
  1974. dsgw_emits( boolval ? truestr : falsestr );
  1975. if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
  1976. dsgw_emits( "\"" );
  1977. }
  1978. }
  1979. }
  1980. }
  1981. static void
  1982. bool_edit( struct dsgw_attrdispinfo *adip )
  1983. {
  1984. if ( adip->adi_htmltype == DSGW_ATTRHTML_RADIO ||
  1985. adip->adi_htmltype == DSGW_ATTRHTML_CHECKBOX ) {
  1986. bool_display( adip );
  1987. } else {
  1988. str_edit( adip );
  1989. }
  1990. }
  1991. static void
  1992. time_display( struct dsgw_attrdispinfo *adip )
  1993. {
  1994. int i;
  1995. for ( i = 0; adip->adi_vals[ i ] != NULL; ++i ) {
  1996. if ( !did_output_as_special( adip->adi_argc, adip->adi_argv,
  1997. adip->adi_vals[ i ], adip->adi_vals[ i ] )) {
  1998. if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
  1999. dsgw_emits( "\"" );
  2000. }
  2001. dsgw_emits( time2text( adip->adi_vals[ i ],
  2002. ( adip->adi_opts & DSGW_ATTROPT_DATEONLY ) != 0 ) );
  2003. if ((adip->adi_opts & DSGW_ATTROPT_QUOTED ) != 0 ) {
  2004. dsgw_emits( "\"" );
  2005. }
  2006. }
  2007. if ( adip->adi_vals[ i + 1 ] != NULL ) {
  2008. dsgw_emits( "<BR>\n" );
  2009. }
  2010. }
  2011. }
  2012. /*
  2013. * handle special "within=", "href=", and "script=" options
  2014. * return 0 if nothing was output or 1 if something was.
  2015. */
  2016. static int
  2017. did_output_as_special( int argc, char **argv, char *label, char *val )
  2018. {
  2019. char *href = NULL;
  2020. char *within = NULL;
  2021. char *script = NULL;
  2022. char *newval = NULL;
  2023. if (( href = get_arg_by_name( DSGW_ATTRARG_HREF, argc, argv )) == NULL &&
  2024. ( within = get_arg_by_name( DSGW_ATTRARG_WITHIN, argc,
  2025. argv )) == NULL &&
  2026. ( script = get_arg_by_name( DSGW_ATTRARG_SCRIPT, argc,
  2027. argv )) == NULL ) {
  2028. return( 0 );
  2029. }
  2030. if ( within != NULL ) {
  2031. dsgw_substitute_and_output( within, "--value--", val, 1 );
  2032. } else if (href != NULL) {
  2033. dsgw_html_href( NULL, href, label, val,
  2034. get_arg_by_name( DSGW_ATTRARG_HREFEXTRA, argc, argv ));
  2035. } else if (script != NULL) {
  2036. newval = dsgw_strdup_escaped ( val );
  2037. if (newval != NULL && *newval != '\0') {
  2038. fputs( newval, stdout );
  2039. free( newval );
  2040. }
  2041. }
  2042. return( 1 );
  2043. }
  2044. /*
  2045. * The GET2BYTENUM() macro, time2text(), and gtime() functions are taken
  2046. * with slight changes (to handle 4-digit years) from libldap/tmplout.c
  2047. */
  2048. #define GET2BYTENUM( p ) (( *p - '0' ) * 10 + ( *(p+1) - '0' ))
  2049. #define BSIZ 1024
  2050. static char *
  2051. time2text( char *ldtimestr, int dateonly )
  2052. {
  2053. int len;
  2054. struct tm t;
  2055. char *p, zone;
  2056. time_t gmttime;
  2057. char *timestr = NULL;
  2058. memset( (char *)&t, 0, sizeof( struct tm ));
  2059. if (( len = strlen( ldtimestr )) < 13 ) {
  2060. return( ldtimestr );
  2061. }
  2062. if ( len > 15 ) { /* throw away excess from 4-digit year time string */
  2063. len = 15;
  2064. } else if ( len == 14 ) {
  2065. len = 13; /* assume we have a time w/2-digit year (len=13) */
  2066. }
  2067. for ( p = ldtimestr; p - ldtimestr + 1 < len; ++p ) {
  2068. if ( !ldap_utf8isdigit( p )) {
  2069. return( ldtimestr );
  2070. }
  2071. }
  2072. p = ldtimestr;
  2073. t.tm_year = GET2BYTENUM( p ); p += 2;
  2074. if ( len == 15 ) {
  2075. t.tm_year = 100 * (t.tm_year - 19);
  2076. t.tm_year += GET2BYTENUM( p ); p += 2;
  2077. }
  2078. else {
  2079. /* 2 digit years...assumed to be in the range (19)70 through
  2080. (20)69 ...less than 70 (for now, 38) means 20xx */
  2081. if(t.tm_year < 70) {
  2082. t.tm_year += 100;
  2083. }
  2084. }
  2085. t.tm_mon = GET2BYTENUM( p ) - 1; p += 2;
  2086. t.tm_mday = GET2BYTENUM( p ); p += 2;
  2087. t.tm_hour = GET2BYTENUM( p ); p += 2;
  2088. t.tm_min = GET2BYTENUM( p ); p += 2;
  2089. t.tm_sec = GET2BYTENUM( p ); p += 2;
  2090. if (( zone = *p ) == 'Z' ) { /* GMT */
  2091. zone = '\0'; /* no need to indicate on screen, so we make it null */
  2092. }
  2093. gmttime = gtime( &t );
  2094. /* Try to get the localized string */
  2095. timestr = dsgw_time(gmttime);
  2096. /* Localized time string getter failed, try ctime()*/
  2097. if (timestr == NULL){
  2098. timestr = ctime( &gmttime );
  2099. /* replace trailing newline */
  2100. timestr[ strlen( timestr ) - 1 ] = zone;
  2101. if ( dateonly ) {
  2102. strcpy( timestr + 11, timestr + 20 );
  2103. }
  2104. }
  2105. return(timestr);
  2106. }
  2107. /* gtime.c - inverse gmtime */
  2108. #if !defined( MACOS ) && !defined( _WINDOWS ) && !defined( DOS )
  2109. #include <sys/time.h>
  2110. #endif /* !MACOS */
  2111. /* gtime(): the inverse of localtime().
  2112. This routine was supplied by Mike Accetta at CMU many years ago.
  2113. */
  2114. static int dmsize[] = {
  2115. 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  2116. };
  2117. #define dysize(y) \
  2118. (((y) % 4) ? 365 : (((y) % 100) ? 366 : (((y) % 400) ? 365 : 366)))
  2119. /*
  2120. #define YEAR(y) ((y) >= 100 ? (y) : (y) + 1900)
  2121. */
  2122. #define YEAR(y) (((y) < 1900) ? ((y) + 1900) : (y))
  2123. /* */
  2124. static long gtime ( struct tm *tm )
  2125. {
  2126. register int i,
  2127. sec,
  2128. mins,
  2129. hour,
  2130. mday,
  2131. mon,
  2132. year;
  2133. register long result;
  2134. if ((sec = tm -> tm_sec) < 0 || sec > 59
  2135. || (mins = tm -> tm_min) < 0 || mins > 59
  2136. || (hour = tm -> tm_hour) < 0 || hour > 24
  2137. || (mday = tm -> tm_mday) < 1 || mday > 31
  2138. || (mon = tm -> tm_mon + 1) < 1 || mon > 12)
  2139. return ((long) -1);
  2140. if (hour == 24) {
  2141. hour = 0;
  2142. mday++;
  2143. }
  2144. year = YEAR (tm -> tm_year);
  2145. result = 0L;
  2146. for (i = 1970; i < year; i++)
  2147. result += dysize (i);
  2148. if (dysize (year) == 366 && mon >= 3)
  2149. result++;
  2150. while (--mon)
  2151. result += dmsize[mon - 1];
  2152. result += mday - 1;
  2153. result = 24 * result + hour;
  2154. result = 60 * result + mins;
  2155. result = 60 * result + sec;
  2156. return result;
  2157. }
  2158. static int
  2159. looks_like_dn( char *s )
  2160. {
  2161. return( strchr( s, '=' ) != NULL );
  2162. }
  2163. static void
  2164. do_searchdesc( dsgwtmplinfo *tip, int argc, char** argv)
  2165. {
  2166. auto unsigned fmt = 0;
  2167. auto unsigned opt = 0;
  2168. {
  2169. auto int i;
  2170. for (i = 0; i < argc; ++i) {
  2171. if (!strcasecmp (argv[i], "VERBOSE")) {
  2172. opt |= 1;
  2173. }
  2174. }
  2175. }
  2176. switch ( tip->dsti_entrycount ) {
  2177. case 0:
  2178. fmt = opt & 1
  2179. ? ((tip->dsti_options & DSGW_DISPLAY_OPT_CUSTOM_SEARCHDESC)
  2180. ? DBT_SearchFound0Entries_
  2181. : DBT_SearchFound0EntriesWhere_)
  2182. : ((tip->dsti_options & DSGW_DISPLAY_OPT_CUSTOM_SEARCHDESC)
  2183. ? DBT_Found0Entries_
  2184. : DBT_Found0EntriesWhere_);
  2185. case 1:
  2186. fmt = opt & 1
  2187. ? ((tip->dsti_options & DSGW_DISPLAY_OPT_CUSTOM_SEARCHDESC)
  2188. ? DBT_SearchFound1Entry_
  2189. : DBT_SearchFound1EntryWhere_)
  2190. : ((tip->dsti_options & DSGW_DISPLAY_OPT_CUSTOM_SEARCHDESC)
  2191. ? DBT_Found1Entry_
  2192. : DBT_Found1EntryWhere_);
  2193. default:
  2194. fmt = opt & 1
  2195. ? ((tip->dsti_options & DSGW_DISPLAY_OPT_CUSTOM_SEARCHDESC)
  2196. ? DBT_SearchFoundEntries_
  2197. : DBT_SearchFoundEntriesWhere_)
  2198. : ((tip->dsti_options & DSGW_DISPLAY_OPT_CUSTOM_SEARCHDESC)
  2199. ? DBT_FoundEntries_
  2200. : DBT_FoundEntriesWhere_);
  2201. }
  2202. {
  2203. auto char* format = XP_GetClientStr (fmt);
  2204. if (format == NULL || *format == '\0') {
  2205. format = "Found %1$li entries where the %2$s %3$s '%4$s'.\n";
  2206. }
  2207. dsgw_emitf (format, (long)tip->dsti_entrycount, /* %1$li */
  2208. tip->dsti_search2s ? tip->dsti_search2s : "", /* %2$s */
  2209. tip->dsti_search3s ? tip->dsti_search3s : "", /* %3$s */
  2210. tip->dsti_search4s ? tip->dsti_search4s : "");/* %4$s */
  2211. }
  2212. if ( tip->dsti_searcherror != NULL && *tip->dsti_searcherror != '\0' ) {
  2213. dsgw_emitf( "<BR>%s\n", tip->dsti_searcherror );
  2214. }
  2215. if ( tip->dsti_searchlderrtxt != NULL &&
  2216. *tip->dsti_searchlderrtxt != '\0' ) {
  2217. dsgw_emitf( "<BR>(%s)\n", tip->dsti_searchlderrtxt );
  2218. }
  2219. }
  2220. static void
  2221. do_editbutton( char *dn, char *encodeddn, int argc, char **argv )
  2222. {
  2223. char *buttonlabel, **rdns;
  2224. if (( buttonlabel = get_arg_by_name( DSGW_ARG_BUTTON_LABEL, argc,
  2225. argv )) == NULL ) {
  2226. buttonlabel = XP_GetClientStr(DBT_edit_);
  2227. }
  2228. if (( rdns = ldap_explode_dn( dn, 1 )) != NULL ) {
  2229. dsgw_emitf(
  2230. "<INPUT TYPE=\"hidden\" NAME=\"authhint\" VALUE=\"%s\">\n",
  2231. rdns[ 0 ] );
  2232. ldap_value_free( rdns );
  2233. }
  2234. dsgw_emitf( "<INPUT TYPE=\"hidden\" NAME=\"authdesturl\">\n"
  2235. "<INPUT TYPE=\"button\" VALUE=\"%s\" "
  2236. "onClick=\"authOrEdit('%s')\">\n", buttonlabel, encodeddn );
  2237. }
  2238. static void
  2239. do_savebutton( unsigned long dispopts, int argc, char **argv )
  2240. {
  2241. char *buttonlabel, *checksubmit;
  2242. if (( buttonlabel = get_arg_by_name( DSGW_ARG_BUTTON_LABEL, argc,
  2243. argv )) == NULL ) {
  2244. buttonlabel = XP_GetClientStr(DBT_saveChanges_);
  2245. }
  2246. dsgw_emitf( "<INPUT TYPE=\"button\" VALUE=\"%s\" onClick=\"",
  2247. buttonlabel );
  2248. if (( checksubmit = get_arg_by_name( DSGW_ARG_BUTTON_CHECKSUBMIT, argc,
  2249. argv )) != NULL ) {
  2250. dsgw_emitf( "if (%s) ", checksubmit );
  2251. }
  2252. dsgw_emitf( "submitModify('%s')\">\n",
  2253. ( dispopts & DSGW_DISPLAY_OPT_ADDING ) == 0
  2254. ? "modify" : "add" );
  2255. }
  2256. static void
  2257. do_deletebutton( int argc, char **argv )
  2258. {
  2259. char *buttonlabel, *prompt;
  2260. if (( buttonlabel = get_arg_by_name( DSGW_ARG_BUTTON_LABEL, argc,
  2261. argv )) == NULL ) {
  2262. buttonlabel = XP_GetClientStr(DBT_delete_);
  2263. }
  2264. if (( prompt = get_arg_by_name( DSGW_ARG_BUTTON_PROMPT, argc,
  2265. argv )) == NULL ) {
  2266. prompt = XP_GetClientStr(DBT_deleteThisEntry_);
  2267. }
  2268. dsgw_emitf("<INPUT TYPE=BUTTON VALUE=\"%s\"", buttonlabel);
  2269. dsgw_emits(" onClick=\"confirmModify('delete', ");
  2270. dsgw_quote_emits(QUOTATION_JAVASCRIPT, prompt);
  2271. dsgw_emits(")\">\n");
  2272. }
  2273. #if 0
  2274. static void
  2275. do_renamebutton( char *dn, int argc, char **argv )
  2276. {
  2277. char *buttonlabel, *prompt, *oldname, **rdns, *tag;
  2278. int len;
  2279. if (( buttonlabel = get_arg_by_name( DSGW_ARG_BUTTON_LABEL, argc,
  2280. argv )) == NULL ) {
  2281. buttonlabel = XP_GetClientStr(DBT_rename_);
  2282. }
  2283. if (( prompt = get_arg_by_name( DSGW_ARG_BUTTON_PROMPT, argc,
  2284. argv )) == NULL ) {
  2285. prompt = XP_GetClientStr(DBT_enterANewNameForThisEntry_);
  2286. }
  2287. if (( rdns = ldap_explode_dn( dn, 0 )) != NULL &&
  2288. ( oldname = strchr( rdns[ 0 ], '=' )) != NULL ) {
  2289. *oldname++ = '\0';
  2290. tag = rdns[ 0 ];
  2291. if ( *oldname == '"' ) {
  2292. ++oldname;
  2293. if (( len = strlen( oldname )) > 0
  2294. && oldname[ len - 1 ] == '"' ) {
  2295. oldname[ len - 1 ] = '\0';
  2296. }
  2297. }
  2298. } else {
  2299. oldname = dn;
  2300. tag = "";
  2301. }
  2302. dsgw_emitf( "<INPUT TYPE=\"button\" VALUE=\"%s\""
  2303. " onClick=\"renameEntry('%s','%s',", buttonlabel, tag, prompt );
  2304. dsgw_quote_emits( QUOTATION_JAVASCRIPT, oldname );
  2305. dsgw_emits( ")\">\n" );
  2306. if ( rdns != NULL ) {
  2307. ldap_value_free( rdns );
  2308. }
  2309. }
  2310. #endif
  2311. static void
  2312. do_editasbutton( int argc, char **argv )
  2313. {
  2314. char *template, *buttonlabel;
  2315. if (( template = get_arg_by_name( DSGW_ARG_BUTTON_TEMPLATE, argc,
  2316. argv )) == NULL ) {
  2317. template = "";
  2318. }
  2319. if (( buttonlabel = get_arg_by_name( DSGW_ARG_BUTTON_LABEL, argc,
  2320. argv )) == NULL ) {
  2321. buttonlabel = XP_GetClientStr(DBT_editAs_);
  2322. }
  2323. dsgw_emitf( "<INPUT TYPE=\"button\" VALUE=\"%s\""
  2324. " onClick=\"EditEntryAs('%s')\">\n", buttonlabel, template );
  2325. }
  2326. static void
  2327. do_passwordfield( unsigned long dispopts, int argc, char **argv,
  2328. char *fieldname )
  2329. {
  2330. output_text_elements( argc, argv, fieldname, NULL, NULL, "",
  2331. DSGW_ATTRHTML_PASSWORD, dispopts );
  2332. }
  2333. static void
  2334. do_helpbutton( unsigned long dispopts, int argc, char **argv )
  2335. {
  2336. char *topic;
  2337. if (( topic = get_arg_by_name( DSGW_ARG_BUTTON_TOPIC, argc,
  2338. argv )) == NULL ) {
  2339. topic = "";
  2340. }
  2341. dsgw_emit_helpbutton( topic );
  2342. }
  2343. static void
  2344. do_closebutton( unsigned long dispopts, int argc, char **argv )
  2345. {
  2346. dsgw_emit_button( argc, argv, "onClick=\"%s\"",
  2347. ( dispopts & DSGW_DISPLAY_OPT_EDITABLE ) == 0
  2348. ? "top.close()" : "closeIfOK()" );
  2349. }
  2350. static void
  2351. do_dneditbutton( unsigned long dispopts, int argc, char **argv )
  2352. {
  2353. char *label, *template, *attr, *desc;
  2354. if (( label = get_arg_by_name( DSGW_ARG_DNEDIT_LABEL, argc,
  2355. argv )) == NULL ) {
  2356. label = XP_GetClientStr(DBT_edit_1);
  2357. }
  2358. if (( template = get_arg_by_name( DSGW_ARG_DNEDIT_TEMPLATE, argc,
  2359. argv )) == NULL ) {
  2360. template = "dnedit";
  2361. }
  2362. if (( attr = get_arg_by_name( DSGW_ARG_DNEDIT_ATTR, argc,
  2363. argv )) == NULL ) {
  2364. dsgw_emits( "<!-- Error: missing attr= argument in DS_DNEDITBUTTON "
  2365. "directive -->\n" );
  2366. return;
  2367. }
  2368. if (( desc = get_arg_by_name( DSGW_ARG_DNEDIT_DESC, argc,
  2369. argv )) == NULL ) {
  2370. desc = attr;
  2371. }
  2372. dsgw_emitf( "<INPUT TYPE=\"button\" VALUE=\"%s\""
  2373. " onClick=\"DNEdit('%s', '%s', '%s')\">\n", label, template,
  2374. attr, desc );
  2375. }
  2376. static void
  2377. do_viewswitcher( char *template, char *dn, int argc, char **argv )
  2378. {
  2379. dsgwtmplset *tsp;
  2380. dsgwview *vp;
  2381. char *s, *altprefix, *altsuffix, *curprefix, *cursuffix;
  2382. /* first we see if this template is part of a template set */
  2383. for ( tsp = gc->gc_tmplsets; tsp != NULL; tsp = tsp->dstset_next ) {
  2384. for ( vp = tsp->dstset_viewlist; vp != NULL; vp = vp->dsview_next ) {
  2385. if ( strcasecmp( vp->dsview_template, template ) == 0 ) {
  2386. break;
  2387. }
  2388. }
  2389. if ( vp != NULL ) {
  2390. break;
  2391. }
  2392. }
  2393. if ( tsp == NULL || tsp->dstset_viewcount == 1 ) {
  2394. return; /* not part of a set at all or only one view in the set */
  2395. }
  2396. /* emit view switcher prefix */
  2397. if (( s = get_arg_by_name( "prefix", argc, argv )) == NULL ) {
  2398. s = "<TABLE CELLPADDING=6 BORDER=0><TR VALIGN=center>\n";
  2399. }
  2400. dsgw_emits( s );
  2401. /* retrieve view item prefix and suffix arguments */
  2402. if (( altprefix = get_arg_by_name( "altprefix", argc, argv )) == NULL ) {
  2403. altprefix = "<TD BGCOLOR=#B0B0B0>\n";
  2404. }
  2405. if (( altsuffix = get_arg_by_name( "altsuffix", argc, argv )) == NULL ) {
  2406. altsuffix = "</TD>\n";
  2407. }
  2408. if (( curprefix = get_arg_by_name( "curprefix", argc, argv )) ==
  2409. NULL ) {
  2410. curprefix = "<TD BGCOLOR=#808080><FONT COLOR=#000000><B>\n";
  2411. }
  2412. if (( cursuffix = get_arg_by_name( "currentsuffix", argc, argv )) ==
  2413. NULL ) {
  2414. cursuffix = "</B></FONT></TD>\n";
  2415. }
  2416. /* emit one table cell item (or similar) for each available view */
  2417. for ( vp = tsp->dstset_viewlist; vp != NULL; vp = vp->dsview_next ) {
  2418. if ( strcasecmp( vp->dsview_template, template ) == 0 ) {
  2419. dsgw_emitf( "%s%s%s", curprefix, vp->dsview_caption,
  2420. cursuffix );
  2421. } else {
  2422. dsgw_emitf( "%s\n<A HREF=\"", altprefix );
  2423. if ( vp->dsview_jscript == NULL ) {
  2424. dsgw_emitf( "javascript:EditEntryAs('%s')",
  2425. vp->dsview_template );
  2426. } else {
  2427. dsgw_substitute_and_output( vp->dsview_jscript, "--dn--",
  2428. dn, 1 );
  2429. }
  2430. dsgw_emitf( "\">%s</A>\n%s", vp->dsview_caption, altsuffix );
  2431. }
  2432. }
  2433. /* emit view switcher suffix */
  2434. if (( s = get_arg_by_name( "suffix", argc, argv )) == NULL ) {
  2435. s = "</TR></TABLE>\n";
  2436. }
  2437. dsgw_emits( s );
  2438. }
  2439. static void
  2440. do_attrvalset( dsgwtmplinfo *tip, char *dn, unsigned long dispopts,
  2441. int argc, char **argv )
  2442. {
  2443. dsgwavset *avp;
  2444. char *s, *valuearg, *prefix, *suffix;
  2445. int i, setpos, len, maxvallen;
  2446. /*
  2447. * locate "set" element in argv array so we can replace it later
  2448. * with "value="
  2449. */
  2450. if (( setpos = dsgw_get_arg_pos_by_name( DSGW_ARG_AVSET_SET, argc,
  2451. argv )) < 0 ) {
  2452. dsgw_emitf( XP_GetClientStr(DBT_missingSN_), DSGW_ARG_AVSET_SET );
  2453. return;
  2454. }
  2455. s = &argv[ setpos ][ 4 ];
  2456. for ( avp = gc->gc_avsets; avp != NULL; avp = avp->dsavset_next ) {
  2457. if ( strcasecmp( s, avp->dsavset_handle ) == 0 ) {
  2458. break;
  2459. }
  2460. }
  2461. if ( avp == NULL ) {
  2462. dsgw_emitf( XP_GetClientStr(DBT_unknownSetSN_), s );
  2463. return;
  2464. }
  2465. prefix = get_arg_by_name( "prefix", argc, argv );
  2466. suffix = get_arg_by_name( "suffix", argc, argv );
  2467. /* repeatedly call on do_attribute() to perform all the difficult work */
  2468. maxvallen = 0;
  2469. valuearg = NULL;
  2470. for ( i = 0; i < avp->dsavset_itemcount; ++i ) {
  2471. if ( prefix != NULL ) {
  2472. dsgw_emits( prefix );
  2473. }
  2474. dsgw_emits( avp->dsavset_prefixes[ i ] );
  2475. /* construct "value=XXX" arg. and place in argv array */
  2476. if (( len = strlen( avp->dsavset_values[ i ] )) > maxvallen ||
  2477. valuearg == NULL ) {
  2478. maxvallen = len;
  2479. valuearg = dsgw_ch_realloc( valuearg, maxvallen + 7 );
  2480. }
  2481. PR_snprintf( valuearg, maxvallen + 7, "value=%s", avp->dsavset_values[ i ] );
  2482. argv[ setpos ] = valuearg;
  2483. do_attribute( tip, dn, dispopts, argc, argv );
  2484. dsgw_emits( avp->dsavset_suffixes[ i ] );
  2485. if ( suffix != NULL ) {
  2486. dsgw_emitf( "%s\n", suffix );
  2487. }
  2488. }
  2489. }
  2490. static void
  2491. do_std_completion_js( char *template, int argc, char **argv )
  2492. {
  2493. if ( template != NULL ) {
  2494. dsgw_emitf(
  2495. "<INPUT TYPE=\"hidden\" NAME=\"completion_javascript\" VALUE=\""
  2496. "if (dsmodify_dn.length == 0) "
  2497. "document.writeln( \\'<FONT SIZE=+1>\\' + dsmodify_info +"
  2498. " \\'</FONT>\\' );"
  2499. " else "
  2500. "parent.document.location.href=\\'%s?%s"
  2501. "&context=%s&dn=\\' + dsmodify_dn + \\'&info=\\' + escape(dsmodify_info)\">\n",
  2502. dsgw_getvp( DSGW_CGINUM_EDIT ), template, context );
  2503. }
  2504. }
  2505. /*
  2506. * function called back by dsgw_parse_line() to evaluate IF directives.
  2507. * return non-zero for true, zero for false.
  2508. */
  2509. static int
  2510. condition_is_true( int argc, char **argv, void *arg )
  2511. {
  2512. dsgwtmplinfo *tip;
  2513. if ( argc < 1 ) {
  2514. return( 0 );
  2515. }
  2516. tip = (dsgwtmplinfo *)arg;
  2517. if ( strcasecmp( argv[0], DSGW_COND_FOUNDENTRIES ) == 0 ) {
  2518. return( tip->dsti_entrycount > 0 );
  2519. }
  2520. if ( strcasecmp( argv[0], DSGW_COND_ADDING ) == 0 ) {
  2521. return(( tip->dsti_options & DSGW_DISPLAY_OPT_ADDING ) != 0 );
  2522. }
  2523. if ( strcasecmp( argv[0], DSGW_COND_EDITING ) == 0 ) {
  2524. return(( tip->dsti_options & DSGW_DISPLAY_OPT_EDITABLE ) != 0 &&
  2525. ( tip->dsti_options & DSGW_DISPLAY_OPT_ADDING ) == 0 );
  2526. }
  2527. if ( strcasecmp( argv[0], DSGW_COND_DISPLAYING ) == 0 ) {
  2528. return(( tip->dsti_options & DSGW_DISPLAY_OPT_EDITABLE ) == 0 );
  2529. }
  2530. if ( strcasecmp( argv[0], DSGW_COND_BOUND ) == 0 ) {
  2531. return( dsgw_get_binddn() != NULL );
  2532. }
  2533. if ( strcasecmp( argv[0], DSGW_COND_BOUNDASTHISENTRY ) == 0 ) {
  2534. return( dsgw_bound_as_dn( tip->dsti_entrydn, 0 ));
  2535. }
  2536. if ( strcasecmp( argv[0], DSGW_COND_DISPLAYORGCHART ) == 0 ) {
  2537. return(gc->gc_orgcharturl != NULL && ((tip->dsti_options & DSGW_DISPLAY_OPT_ADDING ) == 0));
  2538. }
  2539. if ( strcasecmp( argv[0], DSGW_COND_DISPLAYAIMPRESENCE ) == 0 ) {
  2540. return((gc->gc_aimpresence == 1) && ((tip->dsti_options & DSGW_DISPLAY_OPT_ADDING ) == 0));
  2541. }
  2542. if ( strcasecmp( argv[0], DSGW_COND_ATTRHASVALUES ) == 0 ) {
  2543. /*
  2544. * format of IF statment is:
  2545. * <-- IF "AttributeHasValues" "ATTRIBUTE" "MINIMUM_COUNT" -->
  2546. * MINIMUM_COUNT is an optional number.
  2547. */
  2548. char **vals;
  2549. int rc, minimum;
  2550. if ( argc < 2 || tip->dsti_entry == NULL ||
  2551. ( vals = (char **) ldap_get_values( tip->dsti_ld, tip->dsti_entry,
  2552. argv[1])) == NULL ) {
  2553. /* check "attrsonly" information if applicable */
  2554. if ( argc < 3 && tip->dsti_attrsonly_entry != NULL ) {
  2555. (void)ldap_get_values( tip->dsti_ld, tip->dsti_attrsonly_entry, argv[1]);
  2556. if ( ldap_get_lderrno( tip->dsti_ld, NULL, NULL )
  2557. == LDAP_SUCCESS ) {
  2558. return( 1 );
  2559. }
  2560. }
  2561. return( 0 );
  2562. }
  2563. minimum = ( argc < 3 ) ? 1 : atoi( argv[ 2 ] );
  2564. rc = ( minimum <= 1 || ldap_count_values( vals ) >= minimum );
  2565. ldap_value_free( vals );
  2566. return( rc );
  2567. }
  2568. if ( strcasecmp( argv[0], DSGW_COND_ATTRHASTHISVALUE ) == 0 ) {
  2569. /*
  2570. * format of IF statment is:
  2571. * <-- IF "AttributeHasThisValue" "ATTRIBUTE" "SYNTAX" "VALUE" -->
  2572. */
  2573. char **vals;
  2574. int i, rc;
  2575. struct attr_handler *ahp;
  2576. if ( argc < 4 || tip->dsti_entry == NULL ||
  2577. ( vals = (char **) ldap_get_values( tip->dsti_ld, tip->dsti_entry,
  2578. argv[1])) == NULL ) {
  2579. return( 0 );
  2580. }
  2581. if (( ahp = syntax2attrhandler( argv[2] )) == NULL ) {
  2582. dsgw_emitf( XP_GetClientStr(DBT_unknownSyntaxSN_1), argv[2] );
  2583. return( 0 );
  2584. }
  2585. rc = 0;
  2586. for ( i = 0; vals[ i ] != NULL; ++i ) {
  2587. if ( dsgw_valcmp(ahp->ath_compare)( (const char **)&vals[i],
  2588. (const char **)&argv[3] ) == 0 ) {
  2589. rc = 1;
  2590. break;
  2591. }
  2592. }
  2593. ldap_value_free( vals );
  2594. return( rc );
  2595. }
  2596. /* pass unrecognized conditionals to simple conditional handler */
  2597. return( dsgw_simple_cond_is_true( argc, argv, NULL ));
  2598. }
  2599. /*
  2600. * Function: dsgw_get_values
  2601. *
  2602. * Returns: an array of values
  2603. *
  2604. * Description: This function returns the values of
  2605. * an attribute, taking into account any
  2606. * possible language or phonetic tags.
  2607. * pass in something like "cn" and this function
  2608. * will return all cn's, tagged or not.
  2609. * If binary_value is 1, then it'll handle
  2610. * everything as binary values.
  2611. *
  2612. * Author: RJP
  2613. *
  2614. */
  2615. static char **
  2616. dsgw_get_values( LDAP *ld, LDAPMessage *entry,
  2617. const char *target, int binary_value )
  2618. {
  2619. BerElement *ber = NULL;
  2620. char *attr = NULL;
  2621. char *new_target = NULL;
  2622. int new_target_size = 0;
  2623. char **val_youse = NULL;
  2624. char **temp_vals = NULL;
  2625. int i = 0;
  2626. int j = 0;
  2627. int temp_val_count = 0;
  2628. /* Allocate a new target that is the original plus a semicolon*/
  2629. new_target = (char *) dsgw_ch_malloc (sizeof(char) * (strlen(target) + 2) );
  2630. sprintf (new_target, "%s;", target);
  2631. new_target_size = strlen(new_target);
  2632. /*
  2633. * Go through the attributes and
  2634. * compare the new_target with the attr name
  2635. */
  2636. for ( attr = ldap_first_attribute( ld, entry, &ber ); attr != NULL;
  2637. attr = ldap_next_attribute( ld, entry, ber ) ) {
  2638. /* If the "target;" matches the attribute name, get the values*/
  2639. if ( strcasecmp(attr, target) == 0 ||
  2640. strncasecmp (attr, new_target, new_target_size) == 0) {
  2641. if (binary_value) {
  2642. temp_vals = (char **) ldap_get_values_len( ld, entry, attr );
  2643. } else {
  2644. temp_vals = (char **) ldap_get_values( ld, entry, attr );
  2645. }
  2646. if (temp_vals == NULL) {
  2647. continue;
  2648. }
  2649. /* Find the next open spot in val_youse*/
  2650. if (val_youse) {
  2651. for (; val_youse[i] != NULL; i++) ;
  2652. }
  2653. /* Count the number of values in temp_vals */
  2654. for (temp_val_count = 0; temp_vals[temp_val_count] != NULL;
  2655. temp_val_count++);
  2656. /* Realloc */
  2657. val_youse = (char **) dsgw_ch_realloc (val_youse, sizeof(char *) * (temp_val_count + i + 1) );
  2658. /* Start there and copy over the pointers from temp_vals */
  2659. for (j = 0; j < temp_val_count; j++, i++) {
  2660. val_youse[i] = temp_vals[j];
  2661. }
  2662. val_youse[i] = NULL;
  2663. ldap_memfree(temp_vals);
  2664. }
  2665. }
  2666. /* Free the BerElement from memory when done */
  2667. if ( ber != NULL ) {
  2668. ldap_ber_free( ber, 0 );
  2669. }
  2670. free (new_target);
  2671. return(val_youse);
  2672. }
  2673. /*
  2674. * Function: dsgw_value_free
  2675. *
  2676. * Returns: nothing
  2677. *
  2678. * Description: frees a half libldap and half dsge malloc'd array.
  2679. * Sorry. This really sucks, I know, but I didn't
  2680. * want to copy all that data around.
  2681. *
  2682. * Author: RJP
  2683. *
  2684. */
  2685. static void
  2686. dsgw_value_free( void **ldvals, int binary )
  2687. {
  2688. int i;
  2689. for (i = 0; ldvals[i] != NULL; i ++) {
  2690. if (binary) {
  2691. struct berval *delete_me = NULL;
  2692. delete_me = (struct berval *) ldvals[i];
  2693. ldap_memfree(delete_me->bv_val);
  2694. ldap_memfree(delete_me);
  2695. } else {
  2696. ldap_memfree (ldvals[i]);
  2697. }
  2698. }
  2699. free(ldvals);
  2700. }
  2701. /*
  2702. * Function: dsgw_time
  2703. *
  2704. * Returns: a string not unlike the string returned from ctime()
  2705. * except it's localized
  2706. *
  2707. * Description: this function takes the number of seconds since 1970
  2708. * and converts it to a localized string version of that.
  2709. * First it tries to use the clientLanguage, if that fails,
  2710. * It tries the default language. if that fails, it returns
  2711. * NULL
  2712. *
  2713. * Author: RJP
  2714. *
  2715. */
  2716. static char *
  2717. dsgw_time(time_t secs_since_1970)
  2718. {
  2719. UDateFormat *edatefmt;
  2720. UErrorCode err = U_ZERO_ERROR;
  2721. UChar *dstr0;
  2722. static char obuf[BSIZ];
  2723. UDate tmp_dat;
  2724. char *locale = NULL;
  2725. int32_t myStrlen = 0;
  2726. /* Create a Date/Time Format using the locale */
  2727. if (countri) {
  2728. locale = PR_smprintf("%s_%s", langwich, countri);
  2729. } else {
  2730. locale = PR_smprintf("%s", langwich);
  2731. }
  2732. edatefmt = udat_open(
  2733. UDAT_DEFAULT, /* default date style for locale */
  2734. UDAT_DEFAULT, /* default time style for locale */
  2735. locale,
  2736. NULL, 0, /* use default timezone */
  2737. NULL, 0, /* no pattern */
  2738. &err);
  2739. PR_smprintf_free(locale);
  2740. locale = NULL;
  2741. if (!edatefmt || (err != U_ZERO_ERROR)) {
  2742. if (edatefmt) {
  2743. udat_close(edatefmt);
  2744. }
  2745. err = U_ZERO_ERROR;
  2746. edatefmt = udat_open(
  2747. UDAT_DEFAULT, /* default date style for locale */
  2748. UDAT_DEFAULT, /* default time style for locale */
  2749. gc->gc_DefaultLanguage, /* default language */
  2750. NULL, 0, /* use default timezone */
  2751. NULL, 0, /* no pattern */
  2752. &err);
  2753. }
  2754. if (!edatefmt || (err != U_ZERO_ERROR)) {
  2755. dsgw_error( DSGW_ERR_LDAPGENERAL, NULL, DSGW_ERROPT_EXIT, err, NULL );
  2756. /*fprintf(stderr, "ERROR: NLS_NewDateTimeFormat(0): %d\n", err);*/
  2757. }
  2758. /* Get Current Date/Time */
  2759. tmp_dat = (UDate) secs_since_1970;
  2760. tmp_dat *= 1000.00;
  2761. /* Format using the first Date/Time format */
  2762. myStrlen = udat_format(edatefmt, tmp_dat, NULL, myStrlen, NULL, &err);
  2763. if(err == U_BUFFER_OVERFLOW_ERROR){
  2764. err = U_ZERO_ERROR;
  2765. dstr0 = (UChar*)dsgw_ch_malloc(sizeof(UChar) * (myStrlen+1) );
  2766. myStrlen = udat_format(edatefmt, tmp_dat, dstr0, myStrlen+1, NULL, &err);
  2767. }
  2768. if (err != U_ZERO_ERROR) {
  2769. dsgw_error( DSGW_ERR_LDAPGENERAL, NULL, DSGW_ERROPT_EXIT, err, NULL );
  2770. /*fprintf(stderr, "ERROR: NLS_FormatDate(1): %d\n", err);*/
  2771. }
  2772. /* convert to utf8 */
  2773. u_strToUTF8(obuf, BSIZ, NULL, dstr0, myStrlen, &err);
  2774. if (err != U_ZERO_ERROR) {
  2775. dsgw_error( DSGW_ERR_LDAPGENERAL, NULL, DSGW_ERROPT_EXIT, err, NULL );
  2776. /*fprintf(stderr, "ERROR: NLS_NewEncodingConverter(0): %d\n", err);*/
  2777. }
  2778. /*fprintf(stdout, "Date(0): %s\n", obuf);*/
  2779. /* Clean up -- but may not be enough... :) */
  2780. free(dstr0);
  2781. udat_close(edatefmt);
  2782. edatefmt = NULL;
  2783. return( (char *) obuf);
  2784. }