entrydisplay.c 92 KB

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