htp-1.19/0000775000175000017500000000000012543301704012374 5ustar hoenickehoenickehtp-1.19/CLARIFIED_ARTISTIC0000664000175000017500000001455712525674213015127 0ustar hoenickehoenicke The Clarified Artistic License Preamble The intent of this document is to state the conditions under which a Package may be copied, such that the Copyright Holder maintains some semblance of artistic control over the development of the package, while giving the users of the package the right to use and distribute the Package in a more-or-less customary fashion, plus the right to make reasonable modifications. Definitions: "Package" refers to the collection of files distributed by the Copyright Holder, and derivatives of that collection of files created through textual modification. "Standard Version" refers to such a Package if it has not been modified, or has been modified in accordance with the wishes of the Copyright Holder as specified below. "Copyright Holder" is whoever is named in the copyright or copyrights for the package. "You" is you, if you're thinking about copying or distributing this Package. "Distribution fee" is a fee you charge for providing a copy of this Package to another party. "Freely Available" means that no fee is charged for the right to use the item, though there may be fees involved in handling the item. It also means that recipients of the item may redistribute it under the same conditions they received it. 1. You may make and give away verbatim copies of the source form of the Standard Version of this Package without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may apply bug fixes, portability fixes and other modifications derived from the Public Domain, or those made Freely Available, or from the Copyright Holder. A Package modified in such a way shall still be considered the Standard Version. 3. You may otherwise modify your copy of this Package in any way, provided that you insert a prominent notice in each changed file stating how and when you changed that file, and provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or placing the modifications on a major network archive site allowing unrestricted access to them, or by allowing the Copyright Holder to include your modifications in the Standard Version of the Package. b) use the modified Package only within your corporation or organization. c) rename any non-standard executables so the names do not conflict with standard executables, which must also be provided, and provide a separate manual page for each non-standard executable that clearly documents how it differs from the Standard Version. d) make other distribution arrangements with the Copyright Holder. e) permit and encourge anyone who receives a copy of the modified Package permission to make your modifications Freely Available in some specific way. 4. You may distribute the programs of this Package in object code or executable form, provided that you do at least ONE of the following: a) distribute a Standard Version of the executables and library files, together with instructions (in the manual page or equivalent) on where to get the Standard Version. b) accompany the distribution with the machine-readable source of the Package with your modifications. c) give non-standard executables non-standard names, and clearly document the differences in manual pages (or equivalent), together with instructions on where to get the Standard Version. d) make other distribution arrangements with the Copyright Holder. e) offer the machine-readable source of the Package, with your modifications, by mail order. 5. You may charge a distribution fee for any distribution of this Package. If you offer support for this Package, you may charge any fee you choose for that support. You may not charge a license fee for the right to use this Package itself. You may distribute this Package in aggregate with other (possibly commercial and possibly nonfree) programs as part of a larger (possibly commercial and possibly nonfree) software distribution, and charge license fees for other parts of that software distribution, provided that you do not advertise this Package as a product of your own. If the Package includes an interpreter, You may embed this Package's interpreter within an executable of yours (by linking); this shall be construed as a mere form of aggregation, provided that the complete Standard Version of the interpreter is so embedded. 6. The scripts and library files supplied as input to or produced as output from the programs of this Package do not automatically fall under the copyright of this Package, but belong to whoever generated them, and may be sold commercially, and may be aggregated with this Package. If such scripts or library files are aggregated with this Package via the so-called "undump" or "unexec" methods of producing a binary executable image, then distribution of such an image shall neither be construed as a distribution of this Package nor shall it fall under the restrictions of Paragraphs 3 and 4, provided that you do not represent such an executable image as a Standard Version of this Package. 7. C subroutines (or comparably compiled subroutines in other languages) supplied by you and linked into this Package in order to emulate subroutines and variables of the language defined by this Package shall not be considered part of this Package, but are the equivalent of input as in Paragraph 6, provided these subroutines do not change the language in any way that would cause it to fail the regression tests for the language. 8. Aggregation of the Standard Version of the Package with a commercial distribution is always permitted provided that the use of this Package is embedded; that is, when no overt attempt is made to make this Package's interfaces visible to the end user of the commercial distribution. Such use shall not be construed as a distribution of this Package. 9. The name of the Copyright Holder may not be used to endorse or promote products derived from this software without specific prior written permission. 10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. The End htp-1.19/INSTALL0000664000175000017500000000072412525674213013440 0ustar hoenickehoenickeInstalling HTP Copyright (C) 2002-2014 Jochen Hoenicke Download and extract the tar file. As you are reading this you have probably already done this. Then edit Makefile.config and adapt it to your needs. Run "make all" to build the files. Run "make install" as root to install htp. If you don't want to install the documentation do "cd src; make install-bin". That's all. $Id: INSTALL,v 1.1 2002-03-25 17:05:42 hoenicke Exp $ htp-1.19/examples/0000775000175000017500000000000012543301704014212 5ustar hoenickehoenickehtp-1.19/examples/quine.htp0000664000175000017500000000305012525674213016056 0ustar hoenickehoenickeset i=1while not i=57use ltblock fuse iuse gtuse f$iuse lt/blockuse gtinc i/whileuse ltset lt="use lt"use gtuse ltset gt="use gt"use gtset i=1block fuse f${i}/blockwhile not i=57use ltuse f$iuse gtinc iuse f$iinc i/whileblock f/blockset lt=""set gt="" htp-1.19/examples/section.htp0000664000175000017500000000162612525674213016410 0ustar hoenickehoenicke
This is the introduction. More details are in .
In this section are some details.
The conclusions.

Some

text

to

demonstrate

page links.

 

Some

text

to

demonstrate

page links.

 

Some

text

to

demonstrate

page links.

 

Some

text

to

demonstrate

page links.

 

Some

text

to

demonstrate

page links.

 

htp-1.19/examples/album.htt0000664000175000017500000000207712525674213016051 0ustar hoenickehoenicke <use albumtitle>

<use chtitle$chap>
<<  <  /\   >  >>


htp-1.19/examples/Makefile.sub0000664000175000017500000000103012525674213016444 0ustar hoenickehoenicke# # makefile - htp # # HTML pre-processor # Copyright (c) 2002 Jochen Hoenicke # p$(dir) := $(d) d := $(dir) SRC$(d) := beer.htp prime.htp quine.htp section.htp DEF$(d) := $(d)/htp.def $(d)/section.def $(d)/section.htt SRC$(d) := $(SRC$(d):%=$(d)/%) HTML$(d) := $(SRC$(d):%.htp=%.html) HTML += $(HTML$(d)) DISTDIRS += $(d) DISTFILES += $(d)/Makefile.sub $(SRC$(d)) $(DEF$(d)) DISTFILES += $(d)/album.htt $(d)/album.hti CLEAN += $(d)/*~ $(d)/htp.rsp $(d)/*.html $(d)/htpdeb.out all: $(HTML$(d)) # restore parent dir d := $(p$(d)) htp-1.19/examples/prime.htp0000664000175000017500000000146212525674213016056 0ustar hoenickehoenicke Prime numbers up to <use limit>

The following numbers are prime

, htp-1.19/examples/htp.def0000664000175000017500000000001412525674213015470 0ustar hoenickehoenicke htp-1.19/examples/album.hti0000664000175000017500000000454412525674213016037 0ustar hoenickehoenicke

htp-1.19/examples/beer.htp0000664000175000017500000000201712525674213015654 0ustar hoenickehoenicke bottles of beer <use bbb>

on the wall,
.
Take one down, pass it around,
on the wall.

on the wall,
.
Go to the store and buy some more,
on the wall. Money is out and we go home,
no more bottles of beer on the wall.

htp-1.19/examples/section.def0000664000175000017500000000113412525674213016345 0ustar hoenickehoenicke section htp-1.19/examples/section.htt0000664000175000017500000000056712525674213016417 0ustar hoenickehoenicke <use title>

On this page:

.

.


Copyright (c) 2002, Jochen Hoenicke. htp-1.19/tests/0000775000175000017500000000000012543301704013536 5ustar hoenickehoenickehtp-1.19/tests/weser-ems.png0000664000175000017500000016620612525674213016176 0ustar hoenickehoenickePNG  IHDRvKl1%PLTE>N*vRğok"hqsS7=7bºRRQ{jʒ_P6:6ަ{QLz.f\sTsiSNEA>Z6B|>wp]ņĿ2>~zfnVZ9&PFNB9&^r6BZ 3C+yʈyN^xjvvC +RY|+3%ީcƊ^*6ZȊf꦳wFJFN.ƧVneddrP_DJ5FV뿡¢ΫvrčC*rB4.s͒#vQI=~VbYZY2( \FԺ.fāҞY56JvvT©~&rSb򶷀ڧohN}|BBLrzz6,VzOO8^6z*u{2BƲ֘ҏgYƒvPޖvnnnƆ4tRNS@fbKGDH pHYs  ~tIME(A IDATx t[{L@1YBBKY1'8upƌ(D3۞F3nA$4kaFIO,f>W)JNWEALQ}ik@%ӽ{WL'My Y\_P[d)wO$l 8ISve!y学~UUgm1NY'ӈ~cMuޕ+WN?ozoV^imm2ňΧ'QWTV6SƝ+ĮUQRQ-0],.v.6T\}Eyj31î4ss w.km[s啕ce!f|C%B g֕yĢ\Zvi@b YAe:"#y Q _{nۿw2]p`PĮ?q^>r%qp\.n+#ѬaOIf̩*֞{/M/,̔2ctKK؍؉ Jвnzk1 rmʷ׎ۻwzz:q_vQ[f4>t $JOKѱ@=?{Қ4D򄞫SdҲjQ ѕTnP.6Oڽ.^y`ɥT3bz4})IfKWRj ]l gm+3(P^31|gDzo+KoM䫧vh㮕s|HkOU3e`'))vWT)W"L2Gd\QQz%;@]7CTo{l;hQa9(\v{ۏ9z.clfI'GGrV{h=p" W3%,I$o<V sg0_5re?ӅBi 7QB*ިs`,v8=ZVIܟ;k3z (fCo4뼂rYDcL&y*h?R_m2i`1HfJv]2؅*?i緉1 w< #t+w]Q:xTc`}VWm_̅%|~ʌ\)coΓ; 2Hf6o{bv(W/3d6].v{镉N4`~kܥVXv}!EQgFWRu:C?+,髇>sDt/1`.PwEψFX{v((ܴFfB|;c^ǘ;r$ZnY9qxv)^}k%z[uح5vkjG<}yF23Ae(+ ؜Y%X¸ Ԭs !+]|.LBvT~2”*3%1ʘG[8vK1qwd_dxWAљ484>י|kXs%6\1|y+HDf\ 93M<=`f %ش!<ܼ Jx> ty2KR$TaY*JTX?b?]GvSe8rux^|?/w 0}!\I}=QuSs9apr=}}:$9gOp+276w /R'eL";* O,vd{}I*k]ץLo \&鴚מ}]?'vQޒ g`]%'d;P")d %E#C*Kި\mg R$:8%.H.,2aZM%$̶±%jPIT\@`a&s 푾? v*x=E`[QV\MBhCNJ@HxLeEi)L;un?1/{2#Ҷ7)%`Y)/(=8Ʌ'"`wWP9L3gJі@ޞ KOw`G=|ϭ\TxWz1{(,K MkHwYCN0\JW[)Ht,4od*)x@jDZRkd@2 ۠i(Y'_yzg=K^ep*@EX\23||Y%x Hm}-kj!:ydSA?-_mfFRJٔTZ5&YM<1ѺuL9TLqnTwdQôqjϫЮ (΀ۿ;ZI6d,~k:X6agvyK2dK+RtXALG8RY v RPعeO,6ȷZ=RwΧc"P@5fx/MM^bG\O!Uv`pvi Î=W/!鼱qev@]ϗI n:3t [!>s>eRs&= ʰ>|jd.W[_պ/_tmvj9D|-O;aunp;Q .F)|q qb?S}_0h mQvKמ{lxڮ4/XSDžH[m-PWedWg6B;WL6 .(9MD¨e3N yۛej"{U]/9&&֜i3~_+.N`}ǽ^Zr?% zjJ/;Sȝ:"o:/O;A"v8nG+^l׹u/kivLMT`&~&VV3PQ{㶂w%`6-u!0@w9;ڪt9_rv5;\usC8}4H;S-ZZQ(p|丸ѣcgV {^gyK`ى9aC_8G@̹w;¸W>8΄X3 1ؔiԟ2g`pŕ:ɤ2np08!ngkCi1nBI+7v땇Wv .qIݿ<6colx&Tumw$J:."q1Izw!_r=ٱ(;vphqkƝ/Ks믃6V4ZKJ6N\T%AӤVRpŵ\#v4kEK?ݟ|"; b,sݸ%v8)n9Ui;҂V DA#/()~sDAv,)نEEE3erfhf`3&&Rߖx >>Ny Ү}ESq_UAÆoa ܁}]|+Y枎ST? ܅)_a8L'jALvk; /')lq.iw_Р[&)Ǘ͋v T  BIcm˿IoAnj̍^\*,+f%lqօ (x_\q>  D/;df(W ; dz]= m o-^>v 7h٠%E"աD(A&awj&Z[As.n<[8yxyjrO}΃_-[~<ٷX|n^o :;:H;fHxb![/f-<veE8c2T6:0/2T_j u8dmKI͢+, tk>ع I.EcTq,&q1荦Rs^vvCY͞zpiV(PqQCobDysQ@k|\nDkg,ˍ\ܰ}}tI<îX(P!UP<wrg+~,f{@Yl"ɭ)5cNI"qZ .m{ vD' C|Gʐ)?g~XC Qb]B>|^,֍k2ߥw[#KGϰбcƎy($1wnEolKًb1UXH"_XbfIw\ᅱ9")J~fl6~ϒxWЌ;M6&UQ&%7ƾrЎwNRdNeHi0wQސX:d+N:Am5jdKv 5AEbgl _ۮ$3.\m*Zpʑ`X^ńO2|kd.Eԯ8k5)Fuxe"MrQҗEZ5M,sj4&Sدw3֚})F,_.pl.bO7D͖x[[puĴIe P.=}weͶ_DuGz=}CKYigOձGяmkި1W$z*ƚ\a>g29 4Wv8`"v#+ոlĈ^v=V],>h#_)1Z|t0Ս%|ػa[>_itca,v.Bv|wv$Œ/5 ~6qԜy}f%)aGjJ\J` LU C&0oKvJLlKx#[{5;u |, њ8Wkx_,T IDAT*zTUZiڳ^ݎ"IK:۳ ;*Ӝ?8bF5eYQXeég疚G<}Ϳreyrn?}(Xp+OW$% 2m ]Bw~Îw2yo; , 2W fKm]g'Ni.y%!n]n"74v60<Ŷmf˻EzHر]6L;XE(Yf1Hbs/c=%p1%00Ѧ V8Ya钼\3RWCF۽Na DT9lr cG[('=H\ay /^wLGGѩXX;$I7?X%Jr)X6I)njI9Wk7Z`p# ԝ!v^Od)*6}o6NF85kZ򭽽~"3g  '>D"iq|Cs ON!vY1H &D]ada7WԩGw_ˠe^&z oK( mXf0E#)M&wd$68UJȑ6Nz<^p&HSXKQ)lmPbY3:Ap!;;`G1r既\ ]\\K~d]ً Vtʻgc}lG)&-leةSݷvE+@MIqaĠa9Fvv] u32nEDrѪz)ds"!%%~ֈfOk۞iE-SQ7;,L^Ωh9[KH WrJco]4khTKh6RX>;S' A 1R pԣ_Y4i'VjtTR\ۅbBؕ6hڭ.B@2yy@mznݹA^prq<2ҋr,zYm7?M"u%QtbeS}xGmvY;w.섰]d4.oow \6w2aO,?,J>CѭJx:o{ T9c7Ž#]=}1!'9^pP1{0='nlbH8fJ&QUzI0'ŶsU6l`X~v&!X瘟6Ql5 wO}Ur~iѧ[O2;q2vnɾ%(Mj ꎎhx;Ab%)nX HahM6]E_׭T@$y!cXo]dno%&5(~ e uX<%d&@y$ٟ$h XxvlTȜDp?9eϴ/ 6" #%3KgJEyM#< lɔiһabRN,㷆dN;?݌LCq[a m>dkDbKѺ[?R.vgrLі عs0w1eG5۲bN4greݩv_TI~y͸3:7 +.6{<*(Ib&r𫢳^T/w7xQܔ\Lli^pY8#vN *N7p}ZP{Mu/> 65GcʷDufKJ81ھeyq`BR'نrNE)\(fB1iaCayRN%o t׎$nH1X %nڀTbwSN5ɥݝ(ػΊ̧E7Af$w۬ZpPӼNCaRƦAyd"Vݰ] eW݌%sb Ǝ fYyl,@'&uYVA%9[Q= E+pS`K@Mi7(P`%M&Lc}1MA]){gaxҳFm- wSl kx[Ƹ,j#si9#D[GEw~29`w#|aB;:œw]'%tc/5 T~p=My+].~bGQaɒ%E ^.\&;g Rc˝l^J+I!wΧ d=CI3$EZ*մcazƺ\Xqhƈ0lrd$R~y&(;1؅kODR^P˜4qF>xJO;%KhE;g;2Du}񞩅'K(=}$_XrD@!]FkM*&KglKܕԘQP}/D6-vWŲ<0.S4^[d3ϯa;d6IPC~A;Lz"z\Qb'Bq;O% /E]٦d)]L%1% x E C'>| w+:}CY{ކ8v5ٰ[<8;BLk&3^̏a6vYt~m*jpQi gi. -Nh-(iݖPR>y C2??6Pi϶* v)c%Y;E| 4jMR,̹?S._b١G}͆]ԱZZģd#)."v9%ة{1-j8=h8[{z෮Wx^v~*Azs)a}Op=ɤ1`);BH^jגZ?!˪,݊Fӄtx,w''N?$be"Ӹ-]C%[q\#nL]b 7fV%y+,ry:IPʁW>J;=+v}B~-c Kh=W٘λy;:`ζ$]=33]WXƩ}8ǔ}`~MrTK!ck7(ٺ[5K*ti]>.~L2/(נ vWK#% y 5HKq씲o>ݯ®"lMkM%b\k?6ͷ珩icQhomEEPP:"\[Vc#GcGܚ~'\tG塦t,c5`jP| D*pw#-seǚCrD+"ݑ;ưDMвzn专FoaP͏:O5Ά]|JMzp:_W}dT8Oe0|G\ٰcOiw!uyĀ/_"J'}iϞryGD2( YsB3Kc yx#lM䬫"2t/_vlc~8 oysgT xr Hv:V.;yX;~wQ&@8@ ]Xk+n(vJN)j LcD+1B1[G=^$c;Qr]n"/cjJFH54pY6V~T=|f-3f<8ڂB9EƷ$aגRyL2vcO~;xI[{<`ry弰M "sѮb'4KSv̼7L\0viDΜL`Utt5 J*ٟ *8 )`ax CG7ӎ'ĺF4T5!"ڕA+6lU @^CC,ޕ ;Ȉ`T~#n\OXNLK$V&'c ۟zl 1l3vퟏC%$EvΖ㝍5d()8t[56x6iK2 D۝n8wSk<)Z6e\p&n*+=JD Zh~}Q=:1F:N)*g2xpYW~kK96Aۺ YebzKEc8qf_[7ȭH;pfdlT_2sy IY=~+aGu~րta`THBI ƚa,[zGY3?%%Q~5.K]Xڄ(B׈KUs|PAq9RZX&"]K?>rQIgJo܁ μˉz@w,Dfs'rTa3 pӽ,tF/ǐC=g1Qz&֝YMHBxV΍Q@0^W,-6DzD[0kAE.;v-h+3PinfkjlnZ;1 DYxcAU$1*n_v>ĎW_R7xb2Sʦq,>jrM*֍lXD 5wx4h)n?f7$+Vq!15؁Dr937Yծ29F$qD75*[sF2:[|L[6M-S`+3E69 a7,M-S9EtT2 [nI1'I^iggWH$e3Ey=}}vȭa^xz[Xueqg'?bU3ζ:k]CP){PJhpKDzK:34TBˍ׆jFldod'}1,݊ZI!~m*Aޭč=b 88'w[`#;_fy%f]Z%Sַ+_{<Ԕ=a-K3>&-s3,io0Pec) h <iWy$G脃k{*|\9o잫ϖ`StZ gF ]k38<ۮw)pt]yv( C[}f[:E$F4] x\w?玏oxߒ,ȑ#`#mێ &6 ;Ax,vtpP\(es+ԟV]C Yfhkim$E(XaU6-ΰ]qkSISusA7%5Rx`մg{G;gL rvB29Y؅s,m䂞,6ZNJ{&VԔ"(N ]GȘK:wza}JĝMkS.q%F/T;HN+vh:>f۫u14ǎYy{6Ā.]wʪ{z :.`CΞ]= 0GiKn܊a T IDAT>Z]%H-UOKZ R$ ^WT6뎷!p-wH~f=:kWbٔSJuj7{쨝PIW۠2VSr;=n&a뫯>tcXmGD7P `H,MF\m^p*;OF & 2=eh jNiB1^#Lĕ1s {{STf ԍ ܥNֆsjL& ekf8vTZXm"U9Juՠn{aN-[ܱQ*UFq0I>]8- v$nO1܁+7n-rYk(lnSyEJ΋퓪y`ǽ͉-;:=vkTkjNp$&:eJ3)uzK䡯|o8RдUj ;tuEY:bqJإ)teS/ac0CӮqp CV7J"sIC1q-+C4M0H]wz;'e{Xxa,QH<#E6Ls}'s):wߪSZP[&.C>w޼ tPƽ];-n3:)ol&K5|f,1m-3.>zf{OȎSGBvcHjY7>" rPb+b?~SFZyd4V/T۟Œ;6:zJ*u^U?aCկo>[7-s8ҪRZ O&aṋ]pO wUrn N=nr`8eBC*պOoԕRݰtR5IѵG"6nt$Ȑ=ZlȒeȅA^PҞxMj5\3el". Xw)h#ūu 498%/\b;1X=;_sH]ORtڪ'tR[=ϒD$`tEISS66:Y֒Jٳo_ON a:&|/Si$UScHcę͘u;񇴯2b3;]hqW`]4سghO\tbMuG;vj)wHbB Xi0uTw!WEZškS[08e8]&H>xαi2i3RwmVVv4 zBS`b5!JˈG`.e?Y71퍱ᳩ.iRcx145Mi`gOn.=2œG0ʹwLT zuk)/VU9Ї^?{ޭ UWKՅ?q#͕l@p qMS_r jUzԔp " KM#rwA5&J 4,6|&SL0;4]ƅw\5]"C|L;I\`“ Npe8dJ]9HX> zS Ol|+eFu:F㻅w 㤎F 5pC(ExwXZXALَm\ŊXYJ`{R]\*q}R Ju55QUUl4vV2`R.NN. [dlEDyGC88 C6e8oN!\ǡ{zSӅ\+L&)WZOV,Mmۤҍ7JU2m ֫^v}S tcP0zBףAOb :z(8bGnt"&hƅQo;I8؏-r N4136ueW8.krĝ %X3i&xѺjjjU2{hE 53$M!y6y.dV)e &䠊e)|^b )(Ħ$b|? [$s ]6Gz@nܴLWzcYu[pT]|Tf)-EXZc?0P&C&դJpO6:(pl2v͇I.P8F|zb C(IxAk{t7PW<֡`pbl#Ysns+( [y: v6usέM"Qح|;טAņr4s}^EiH%3y+im:qihyhetH; 'F}O[tU,>NKy}>jMe3;G]ײjT/njSye]z?kPDzkMZUهtM՛6k{6MT}MMZCq~-7lQ]+f^.nn0P zF}j6%KaD jԑXҴ>-u Xl01a \0䁼5GiM@]+A"^Y%;ѺKϽ`g`ٶ?/b8!c=EsBbJi5si;~={c^lV1isc:R2p"vctؒ&=W4tڤJKպo Λ;[Z]-ꦤe; uRigrr$F˪mGqupC}aR92`:Y-UOrz፺[(|Q2V&I˅ەAQڷo$)~{t:=Μ4GI6MXp76j5;7j:pr&MQ8bzV  OtF>dۡMPGm'dD ;+{^[[ {л@ݵ֦Xq{1٬ W3i j{XuRԞाw\w۴ pHjGeU벪agjJZZ ~6zmVNEuɑM::pFKzPڳ)ezwplI]KN5AUzL(Fv5y}7BghDŽ as5˗֝? Uf%Mʥ'D1|Y~wj |FКmEl(*vgXn܍jRDzM)u5hD ģZ#عSp>֮U[Sk'&Uo R{Jmɑ{eEkL2Wb;.V1yD1aebb5T{R"os !w"a;MEGE]l??~D۳ҵt >qp`|4z/+Q^Mؕ}v[b؍%d+$(eDɖ.6mt4*{;Ҟ m궵w7V-^6jC'UΡƝ2ZyaZwu۪QMK){@R!7"+)&]$mϣA *sL;/}'v@0W)bʦ0sU uPH8`n"܁C~)3d2`UpU("f.rvZC8a9)yB;ΎNd4݌F&aǎ[b`5S) R̨0cKbUe [qGkMM3åmkU(}Y5 ?t"-M6z.URХOguۤ[~e# Fp$iĔVG';*S2ZMMM[N&j}Ta cD[[3q5|v9l2Ȣ3)/ߨr.`P. a9aODtsU`0jD n'gȆ rxNz1B!3hO͂]MUW-U/_mNm(- T_(סKDVu6Njl tuIkIZvIDFg$NI׽{M[̄%Z:\ ڦuoywrTP.Xzݠr^B)0.t_B X,yTz'(I:V9X!v[W>Sn?&wr{Q*e"Nx: 1/Rem;yEb ~_9' <7LK)`8>~Q nAӹ:?} +\ԇd4t2pȉ'u~@Is >^u/s)v4;QT5+Mmk{+r9tcz1:"Ma!}IE}}vcCw|MN*ȼ;y d|r]=qCx CCՎ[*ؑO4w'12dc'M(V3%&Zj=nEUjbZ < ##)zzۥnw31(ˮ%I@IWIYB?þمZi>^t1],;qϻ?FNJRrQhsD"|v?;#? NE3`Gҹ0Ҕa/4;7V,0l6f>OpfA$w\ˆpӢ }H]6 k}ݷÃ΃1n9;n=Î lDĉX|}$+=FQrn0~0-NA= tn||O7q֬}ˑD$)3.31*Ո*v o(N8UŊQplj&ZE2E$WLNlq8uBn8DB)LE֐[%[m9[2z~SCd!ܨj)gO .KlfYF L`R{xY)MWo54hބ%i(lld!L"r$E!\4pAg AU-kŋ8ܴ)وYP0FM0 7ծ],EN y>;nN_9lnv`ήRc;8d,XDaAq $ЃjWFw@v%$zk1E]yU SZ0%Rs]RY3$#ei7[ӆ ~; P+A/]\idI۷7PǎY>^vbS{}Oz:4vw/EBF1[iq|C&G'& WC^Ix1'#ˊk>[_(H& )j 6L3!ݸn [ʕ IDAT<ǭܼH&W?B8H?0rիb;y**Wq7`I%v9BGI^K\-wkvK{&([yz'1k;ˏXⵞ:/d !}Ru=W%5-WX,6EKW ᔖ: Wٙ!Az`⾑d4oVwYp&OTuzg2@F^0uS kSWwv\(ZXFFQ d:Aqbt6\.X3kr謸{߹}K$39)A<@gzrك=D}Zn{WC|@-~ fb~'Ά](r a{P f&d;L$.]_ҏ?n5(rφP_)2-%3W dgme-1KȂbcl`ZpLlAk֏v{e0T )ja}CFHO9[ok7Wߺz.\' ɥv8)6)l6lZu.^vݳgQuLlonY;^a#nRU\_MRci& aU*cmaL ͎(~IN EIϝ/do ,CZ=u VM" z;&[=,PE[/CG[!0 7"XoqU1^Ry_g#r<:Dھ[Wgh2\,!O`7v{/mvqm7g Vd}r3mIà̫wv?KMCE_+L<׭9]llrׇғ{҇mH"0 N~Q9yv9 oR*\͉ѩblq&&Y<ܛn4b`HN9[W[Oa4n's|;M~8hK_0Yb񵵕ˆ)N7nvK-p+{:nϹeZWw{,m%X#h޺ukuC;j DsVO}jj.ȦE+":ZYd{7q⑻MR LHgl{?yt&V=_=UŪCz,4Вc[ovEOڅŚeSqK,|rK=QR4xĜ+flCJ/Gʻ}7'gRMtts(䅗m-EyGGccfŖoG߱q \T.#pɥFH4ph\/.[yw aJ&406L]~j&Zj2NаvpF!Nh$oB=S'1a#v36+L(zt:&;ZbJϯoX&I7O'Ey]\RlvT1x'Q̿u}|݅ur Ϝ,0πNƕZIӁt"!݊իɩԞ9w*5NJ <+ooi$׬H7G m%>r)^xgK 9݌;UtbW `vT'$(oO! BN&Gѱ=y$׀dOHݫt[G,awh3O\ԹylAX#"=ĵ!lIS`b]_o*r7R3Y)A:\_?`Y gg.W #,48Ut^_?Z3!+_Tb!K7@ l}I f57wfJ=*fͻ[CdF 6ba}gZܾx3<3vdpbQxEӶ҅H|] /0GԌⓍk:$Z hK׹eˊ[+G e~61+t0}ZԤw6lgg0W~R6ɋ 0uepjsJ`WsߦgP+H4.s؍ &әΩ6~ =u( Z[{=dZP5=}7_+g^oafNNg5> z/4l:Lzvإ ʠݺ-DK-`n!xRv#nd~l+A'IA:յA-5E8nrʼnw#^sxTƘþ0FA,P8goov$[lA'%SI<*۵$]x$98h InQy5 .VMWd{ENzbb\(eR2sJIUI ZOQEq`}] B^^ 93/`f՞ĝQY[aշz)3Umm"3pyxD>_ikK][rḺ?**z啢bHSR #H1\Xg6fN/A띯`iصrJT2zik-A⊬J*xf_+W۵^k(16Xj77'ௐ%ţܺ#%`Z[3J v8Q?rf Q`KisnkeX+klP0^;6ʄ9R:"[I b&73wpxi3م9-!/I9-V6fQAAt6LO?u7hx?*C d@baa!B0ԑ2/A4}/Η=CN_ ;L)vRXX0 }W?)|¸DF k&jpQCdlcjq-nDYWE-;{15 [Vs@BV_?lfS?+-8ƮՏNH%(Cl !Urv$ HD&2P\aT֮`x{!^|l0X- IҺM6 8 <|KX=֕y]eLyrAw[/s)h&jT. Q;b|۷M"c+Lp!"Sf+0㺎|<_D ]j/pQO*<IJ;^_VPFlF)F$.YaNe8y`Q$!1gC7i"Vx}>C?G [bnec+Kjv,{/ Vג h3v&3_uT^N\l%ͳk4 v 1%.ԡhLmew@s2-7$dV=kfr)':=kH.*S%ucQֶ6&g>_!.i"pRg,LCE:ТвRVAuэZ[΂{}iD!A'Y(}Vg 3u5}jwc;)8 9D.NHI-* vdBSPF肢g _a)*LٟxH\cVQ+Qmy+ :+V$`W' 0 h+Y=1~=Qn>!sV޷Ӻշepqql&0QvnJ`E[Yں[hw=L20%JRr (I-I+v,٥c.̩ w|ZbA1L\,~LS}J4LH_~b"*V'ph^KX"r'i>p)D>n:ZNws`r, vܤBm)`Lim|t^n_S te~% [4SB`e6vFIu029Jn]k$UEn3CT T`o,E-mlǫ/J,bll&C)(Uf2  (m7F IDAT/L1~vŦv ʝjVOQf¶T!e"K[QIa[ӰZ k-n*,G^X5&h6DY*^uq3n?y,;+IbWN ۫ʝ" ݟRN@^/yqS]t` Hɔ=5sdL+/:ѱfʜ{4(_ ")4y(U=Rz+&!9Sɻp\),E5%U(m Ce2c,YXL;\䡉ÁfwHDN-b̠%SXL+Jra2n :~wee \SwubPIN?`H͘;߄T 7@< ɣ]'^,[TI1I(p%U|CeT#% 8SZ-+a j<8Y{rKde4D /Bf-l"] }ջ0=Tt7z&X @7|52n<2ϗ}<8~Ց͇:A(xtpWNvE"d\" }[)U9.AQj`QQuyHh4NTVxlxlkoi(Eֻ~SYݏޒ(O$`7S*/dɌԅJqNH꠿]LwH ZLSȪ{)y2R;]lpX# ~vwG_|2Pp4D1e?l{2;/̞++õ@ޡLjq)m46ಓz!p da7,PR^@TUfJB^s+P֖aVø-dªI`ɠF$p1B(+n]$ZQ'A(>kV.IpKc+;03/ĒBofSDJS6/H,S78QTQaD0ml OFs2 vY >F]8 -dnMuZP^łl:amV^*XA4GrD-iQ[[YZd,gEҐʴ d^e$riIfkSڤX8\RMY_L\.hHA̩_6ԩjfB8|19;RѶ3MN *-z(ͮϴ>h.ݱS$j5k@O[7*n-6zwxPp1mxaka%swR 7qFjmtyy-aG1aˊ+1O~<WeUVu\⚫ȵ Фhb v$ 56J\ʆ)?V<c$c%NNG{~ Ѷ7댍utݡ}/Lp\{ͪ<ʲ+ZofacXE"dQJ C&=I6~'h/d{9Q %kYs?Xcگ"4->?on@%} ^18#aNdqJdשF?\*Ãi cSBb:Ut} e:i`s;_kQW^T(4?,QmR!ʫ*-?b]bߢPcxt $WTnZ2o$ w3;i]0-v}2WQƠKho℄?{гm@;! xެ4"UɃm>ޱͻ6g +F8 S?0y`K={\ٳoZTd,AT"NitR[K-X+QZ^B²MV}oxG̋瓗[\2 uS`W`kڼkެl!k(b]Bc ZF 9ӔV&͍1g;NoT6iOcqT[ Dƥ)z$xT:zoi qVk!iBjƷ4;R1\m'`f0# H=5vn,Ξ~¸t{PX*.p.W|k8ggC⺃0M$ G*p~ǀG42!ZiɷQ)Sy_m|F(vtudX OMb; s6qGGxޣGwnjnGS;pG+`*$>?Ĺ"p,-C^1Idَy+OOq[x 7ݬ 喻h4-=tg,;/Zb%*7Wg7@!6Mr.nGubߨj[ v^Y*[AQi Dݳbr܈PŞ Mh?i;$8U!Ev}<#÷-D)Bԁi*Dn M[UOT ioH]lzϘ(o()dIguc'ICJXQ3l 7nλk[&BN#q>m%f#H.*·]j?`Dɻ2AR$8 qZl==lk+nM`<%VeypzjcF,pa< r{i{0 e7iV= K!3ydqyN6l#23:ɊYmRf!<2 7[*f:L2S{Ǧ>Mnߎu'Q5\ b^D(@#[Ee LV|BRPy]T;Hm|F!j^ݞk!4q}\t1+X`ǑhX"-2˄]t.շ+INGd0x[nVk+UԑsrXYfQku{eL#5cM^XM[< y iRza0<:P6͑5(.ae4xEy%Y\̻Hp`SY7dx6&]f2\Q =}L]! RRiy 76ND\܎ 1{'*mB^V*% %C%d=cB4{D2ٰFEt\ M̎;Gv11骲"WP0/&#nK¼y0~a y832BjAxEBB% (ѽ#ZfEk _I>tEaZP,T%ESd%Q%<+2D0ulGpl ̧d4xݜ铔"}5 F==}Pw&FfS'E.uhQB{N| H9" ҍ}_u_v1$ -/*W~۴h49${p*$ IDAT,ʩAOB#kR[`fmlޔNc -EGZ 0srb"G*FL`/@GKdkJ,TL+`Wr{iלQ]Ť V4gJ^Hkm'JiLhd 7/D`E#EA>W̡`;.PS:qfX, cTsf4gs^vTr.09N}H0<>Y®ZAcDb>x#Wq Ҟ/ߍ ښKyvdM>4atKⷳ1:O˽ET K*KG T^*>vVks ;TtAag,?`@ /2#\u_y^Fnzm$(jnn$:;Z< MKXG<+v7D'W|g-t.s_H9J@IeJŠQw2/@ ISaH^E!E4|hk0ޑ5kY@$G@ؙ-cQY&eԔAw·3N%=>6Gv>G,'ص5P%ۦqn|˯冂w#4q ,5VN D] t*5{Lv#!"2w(x Y IgN禘,v|2en,a+:8Fi䢚g(+m6noF;7dK!=iۍԭ% B{Ǔp ܬLeǿ@vF+pb&9`1}{͈-p$ |ѧ9aJA19́]!M I԰:QʹfйT=\Ȃ+/8[ (Դ Y/QZY`7amEOGJ[Ng`;dUp`Kݥ͈q\1 k%%6]j)`mXςId)•DGDٺMgO-1]Z$Tϳ3T'<6QA: ] ]W}f\u;_.*-Yz9^s$jѦ.Sh_$#>)q§kl\qk0.TǕHL.8]!evA`J= ♘JdZxa6[ c)aMGpt)֥dMW:"+N^%n[s!w AܧgRjK3s,DÁ;&S)ʆںH` {kb] u$/Kަ4<b2ueK,O/qgT lx VW>L 5rPULr3d9"׋/n;ywMHqիς350~WjLftc0Q*dBM=Yv&tOarќ1]8̅\A- <_=k "|-;L]2`wgu(+K䴯!."<`ta)=Q쳏\JYOwtzm۶x+COטּqw}q2s,A,+ɿx!N TRE$@Ϸ㽔iNPq6E&sEGB\Ahd; [wFEN;uD_J F]`Dw@6v}Tp퀒C2t\xWS^rz4`;:{;.Em=  D49#Jll6pv RxAq~p n?B?u;RX *5:kA@4):_7JaY(수KNFa٫W/긁R  KxIW ʬ:ón8k; :|G!M~ tLqj=Orx!'7x"q;V{kd~\\jvpcxpUw$}*  ˩c&NM\iEEg'»pa TJTH0>ï!{DE{02h![O.`G6-etNP=2\=h\MD'#1CR!F:4$r܎"0t7u4geÎwayΒ$caf6#2$}ji`X:>RG4eAS74UW!zISr'ϠP*-T`4(V O]nKRWH04XH)Y=Თ8 R;{!m$rav\!j/:={uhO =@;V}ճgWЏEBy%tzӋhS;aO;ULe Rɱb@Ί7f.'%WB@$wV2;%9).vCJwZ`ޞPwdgn'8[ FHt:,qctaDʦ#T}Džow ;:n;V }^oop`e c D(O^7~_-m< wZt)=mET;Z>b ;;>Zj ]λX#bI1qYw-- v:ēO,:9-D)Q:l.lWۿ2m@ apX8JQ< ֏;d{ p*4wm0|>uO!VcvQXwn6 3B48oE%c^MM5EJ=ɔ8g.c19o.GbaoѰ ;[#[Z;*_5tVoo z_$9"U=nX+.E] B ;Q{/wY!.Hhc@e[-lbA)2aG&̆y'_oȟlɬ"nqIZS9U+0 T(? vS;7b%xs1J{yl5K4/=pۉhAf%dZ;ú'qe׬p&Qո@άmrwm>]UVWpeyim(S ̱!'KM`R(fooK$D1g!}8',؁n;a4z3ȉ }'7ꋃ3};'QfQ3 }Bn9]^f/ 1sFaHC\m8j` *D0V4ɂY8#>Kν]m)L-|.n:)Kb_DC!@a*o]+0 q 8 ˭Ic,A}M,H:Jb_8va("-!?FD?Vl<}ᷰ7ŚTv'J˺ϰ)ein6h)pjsSbQ^676q_>mk{t#6 .H7_=fC-cC%DCgƌ_6]sVwwP:])~୆ 5΍me(|^6nvl5Iѕm=t U ._t$V,:c G&% Nw<$ɼ-u$p+MԌ.isAwNIkMȦ;\pZ`wLk-F?`;x{T5@yFŌ˜6v$F;EEc#8='Ԙ@t Mao/~{$W~%2YboaLkW9Mb`nnm ::bq o/V)`&cǟ;~s>ƿ೷#~(kpހP KEyk/]ko8aw;3-i/ݳnvޠu~n zK%ս  5H%w>Cආ17W,N4)s8𥒩21dͨ盉#u;wcP̍s3k37Q㟊gm37޻v5 @ (ߛ!(޽SGU$KK4t݃^l.Af}`3Xpjvėv$8&1#%>YEr5lID@0$r&yD{#ZC}:ڹ{ ݍ{̬u0 ܘ@k .cRc##${U|L'z&{z:@Xd' y]NO0|su==kT0ti V^jء߃׿SY-݃p:T|k ׆ a񀚌~NY-O w~H L&vm~P8e+,Œ T8)]n zvg($psH.]0}w]tJs/˨ <~΅ת$1\ CH)ff>} `n5f. aA7C>˙{zwa [`X0".1'KFepݎ$5[wo=xQ+^z;1 Cא"<>]8-r/=& 1JƬa^XvuI1Y⫿{~~}+PYxIلi.+L,zB:f1Gb50w3||޽ F&X98?cg渖Ubl#Qiq4Q]qtW҃[쭻wu}@g] ϗd\|Sy]9]bya79)V[HJM6 EJ>2r\R4<o}ܑ(w!V_!=giv ^.82EgM_e=s.g's4RX ١.<(0 +Qt,"ySvwU/z- ]%pɿt\-\RF%5>sg^@K/%cfw@JU'`gɃMUt],n ŶR3FZ)y &jNDۡ +M4GswoK2SI;ݥr^o 15ߜϛ% q$z|Lb:Ikj+}꫻߮Ao|J""Q`I{y mɀK t&֡VZb^_(JzPޢR$֙/b؋d>h`7axgV5)/s$Vc`s| ya:jY,qI43:ZkEY;҃H -!]gܫOصp>(ʑ([MGE3Gw ƕdQU2z{|yʙ^}I_xgM"3tѰFax fx^k'Ɖhzg9.lpmQӍYR^g⍤B2Ic{gDwdZS@ J-i8UUXS,[zyx>N!/Wխ"7qEM^;vUL-:w_IUJB0pϖtPZbC /'qgӠ[FgM|M؁&-j(AJ!'%m8Qǃ;YRB"(`M30wږ*%FPv ᝝3JWk ܱWpj&r[\gٌTwrnѮ|l2r4վ{a`Nvn+Z1z-OJ!dFm!'Q{]32I'>Kt JaCR1RV|_xWTfޙF؍w_;CiJQckiO.^iB8º_҉Fgk͛ hw>)6ǩlvI;~F<u3`qj̨3f<9 .ėL(SэŔ(ؾ BF>ܕ;Ro||.>⊪3 &s;/%L*n\s/,1EQPW4$ᄆ=FQpΗ pUeNm)k98p؁C%!cp2|AP<_FJvr8sD'z*R6+>MK>v͂T7ey1қu7E߇tƅHVԁ40v0U+x yaaj7KZ%L.=-9F6[<vVXe>|}uS,Ւ Upx ͇a٪M6لnfϿuτ=D QcҎdN]ۡy;Jшo%@Op,G>L% @LI69pO[Öj^>` i*~9i~L1 +-:!PFev_6!n.7\]kۮe<)VHQ+2XVQN v:ۈdI;=}wh$֊%5XcJbeEYd[]@cHrюʸL!'G҈XDYH}xw)Ch ?6؍|h"9ڹmzsh q *Mʧ{+L6 '>/^ߜ]l4ɁaVW |pu6],ڏ1YY7! Ĕ,ȃRYc83H5VO^k#7XN]P4ͲSIΩR1~0 SZ{#ki7rkG#ƦrzG=B(]bRWuVXn"Q),>RvNhyN>pk:}@6$q[v'Mi$-j2 {(!ÎMwDSO]1+u@euz&>vv2<:jq?ce\ɈZb鶷doK^0s!# ]\pa\9o= /gj*d `4{8s$5"=;%nR݌Q#쏿d)'-ua /4(2ySG'p-ߌ3Xj^U;M5B/zZ^LlHjIpǒHl|R#Tz|6|2=l>tcoowXTۻ+O0/J70d{ed!ƒ|CrCtȗ,Kl6`&O0wvCH:A(']vAaW+y' wvZZc;tvqDaqr`$p),R^_3Gv/$pX5{wџ弫O|(;RCPT+gj1y\ J+7M)6Ee=#g{g|T֌ Tv-#@wG{| ugHi9\wٓ($a 9+/f}1ΪtQ + n>Zcgvf~z(]/=D }?]oEgQ#.fTVi,bL7L! 2%RIFqZ!G6opt'jĠp"-X8I: eȂG zs1*-@Ƚ%`YWt{Qn`o>1_=7/쬌FqڊPCg330NWCŋHVnE.oc0Ex5QLk3-ćk*ڵ<ۤGf'-vCK]t*C_P;;;G ^XNuc;n ϟ$}dѲ]xao,ijnDqqþVPgG4A@ 4-yb_8QL\8H>7NVȎ=H-ڒl,_sq~#pbSa&$aIDATEI\8M xy-Ŧv}UcnQ=UQI,Z b52"Nc58uE7ȿ!0T/=P&XM!>ܚC;n7Mr_z#gڰ v Ov1^<` uUwqFpO:DSY` \ῒ&6+.oQTZ%&Mlb.A ,P rOM*/Bp^׿BrqcCI \ű!WcX:4$G ]}dÝb$&Tc+d3Nގ Ѱp/^tz"qsaGw:H9e Jə\j% ?| eIm ; >Fs>!Nh|&fsYh7 P޷bQ]zGR*DNcheQ,KCkZbi@jјPlաDɫP^%q3KlVgHODq m,_5찟_vb7QX#9UwGkQO=i_RV\g4ي hlWr~`P)Gqቖ\pdX@U~aE M ;X>Fuߍ c;҅D- 8\rhQ{`gUt IZ d.[58//n=2 78L4:8a)N鵾{҉B DEXS(_ܽ!]|3yW 3wv3.8ʼiFSIN!'_ؙ2 =i1wL-ѵ舱tHb:R)7P. raYx-#^L]6dup-l4I8 3H 5&Yб4]Hѵ;\l2GppvaQ84FRvu !+iJ}z,g#rEJ!w2l*M~/yn}Gxw_UgEiv$cBQ,Vcri(;rM(K?%۵]l2 qSlnb>j?è\b]xbb5hUxz^ՆM193F?A59ʲ/­S],F\ءۡWvzZKyq^XU'Y{\ˮJ,V*HnDž M TK0M0yNjkx(8+؁5bIxd[{@wvgO6RTZ jY^ ax1&$b## X93^g>A \$`nش~5n':™vRHybwW1mcgI  Vq-ui[-J,L.qT}U`_T:JQQ!: b3#ku yxLlj颩186p\>kupajȓD¡gP3Ly^߸epiltIc}eꤰLlnS ʭE^߁pRr+_g^}dQ |a^L^ }.#;ʬU?n36~bA1a.K OVwbAV߲"ϱ wCQfE&0탅b{/*q,7PwzdL)標Q)EJ N[hm%M ۲ b5>670+c`ERDb7wl?>fԩ8$Аm;.xn++F1԰tlՑuxY"_ iXpȲmlܳ(ULabـN ႝnsPn»~??g_ }k_4_?x_p4OWv_ҟޞ__ }_?C3%Gz`z<p]Ex%`g޵?{؅#BIENDB`htp-1.19/tests/files.htp0000664000175000017500000000157012525674213015370 0ustar hoenickehoenicke
  • Sorted fruits:
    Include Test: Title: Reading Title: Value: Reading Value: htp-1.19/tests/tags.htp0000664000175000017500000000021112525674213015213 0ustar hoenickehoenicke blub htp-1.19/tests/expand.htp0000664000175000017500000000110412525674213015536 0ustar hoenickehoenicke a is expanded at time . b is expanded at time . contents of a: contents of b: c is expanded at time ; d is expanded at time ; e is expanded at time ; a is defined for the 2nd time . htp-1.19/tests/files.html.exp0000664000175000017500000000034712525674213016335 0ustar hoenickehoenickeSorted fruits:
    • apple
    • banana
    • mango
    • pineapple
    • strawberry
    Include Test: Title: Reading Title: bags Value: Reading Value: 5 36 0 0 0 0.035156250 0.000034332 0.000000034 htp-1.19/tests/ifelse.html.exp0000664000175000017500000000012612525674213016475 0ustar hoenickehoenickeApple Banana Cherry Durian Elderberry wstestthen-part afterif wstestelse-part afterif htp-1.19/tests/png.html.exp0000664000175000017500000000073312525674213016016 0ustar hoenickehoenicke Weser-Ems Weser-Ems Weser-Ems Weser-Ems Weser-Ems htp-1.19/tests/comments.html.exp0000664000175000017500000020031612525674213017056 0ustar hoenickehoenicke htp-1.19/tests/Makefile.sub0000664000175000017500000000145212525674213016000 0ustar hoenickehoenicke# # makefile - htp # # HTML pre-processor # Copyright (c) 2011 Jochen Hoenicke # p$(dir) := $(d) d := $(dir) ################# DEF$(d) = $(d)/htp.def $(d)/files.hti TESTS := macro files wildcard comments options png expand tags ifelse phptest SRC$(d) := $(TESTS:%=$(d)/%.htp) HTML$(d) := $(TESTS:%=$(d)/%.html) DISTDIRS += $(d) DISTFILES += $(d)/Makefile.sub $(SRC$(d)) $(DEF$(d)) DISTFILES += $(TESTS:%=$(d)/%.html.exp) DISTFILES += $(d)/weser-ems.png CLEAN += $(d)/*~ $(d)/*.html $(d)/htp.rsp CLEAN += $(d)/fruits $(d)/htpdeb.out HTML += $(HTML$(d)) .PHONY: check all: check $(HTML$(d)): $(d)/htp.def $(d)/files.html: $(d)/files.hti $(d)/png.html: $(d)/weser-ems.png check: $(HTML$(d)) @for i in $^; do \ $(DIFF) -bw $$i $$i.exp || echo "TEST FAILED: $$i"; done # restore parent dir d := $(p$(d)) htp-1.19/tests/expand.html.exp0000664000175000017500000000050612525674213016507 0ustar hoenickehoenicke a is expanded at time 1. contents of a: a is expanded at time . b is expanded at time 0. contents of b: b is expanded at time 0. c is expanded at time 1; a is expanded at time 1. d is expanded at time 1; a is expanded at time 2. e is expanded at time 2; a is defined for the 2nd time . htp-1.19/tests/files.hti0000664000175000017500000000004412525674213015354 0ustar hoenickehoenickebags 5htp-1.19/tests/macro.htp0000664000175000017500000000144512525674213015370 0ustar hoenickehoenicke val2 macro1 is set macro1 is empty string macro5 is empty string macro1:: macro2:: macro3:: macro4:: macro5:: macro6:: macro7:: macro7 raw:: macro8:: macro8 raw:: macro9 raw:: htp-1.19/tests/phptest.html.exp0000664000175000017500000000021012525674213016707 0ustar hoenickehoenicke $y) echo "The > sign does not close the php code!" ?> Now the php code is closed and $$ are not replaced. $$ htp-1.19/tests/ifelse.htp0000664000175000017500000000055212525674213015534 0ustar hoenickehoenicke Apple Banana Cherry Durian Elderberry wstest then-part else-part afterif htp-1.19/tests/wildcard.htp0000664000175000017500000000113712525674213016056 0ustar hoenickehoenicke
    See the blockdef section for more information about blockdefs. See the blockdef section for more information about blockdefs. See the blockdef section for more information about blockdefs. See the blockdef section for more information about blockdefs. htp-1.19/tests/htp.def0000664000175000017500000000001412525674213015014 0ustar hoenickehoenicke htp-1.19/tests/wildcard.html.exp0000664000175000017500000000112012525674213017012 0ustar hoenickehoenickeSee the blockdef section for more information about blockdefs. See the blockdef section for more information about blockdefs. See the blockdef section for more information about blockdefs. See the blockdef section for more information about blockdefs. htp-1.19/tests/comments.htp0000664000175000017500000020036012525674213016111 0ustar hoenickehoenicke htp-1.19/tests/options.html.exp0000664000175000017500000000053312525674213016723 0ustar hoenickehoenicke htp logo This text needs to be condensed. htp logo This text needs to be condensed. This text needs to be condensed. Generator Tag OK XML Generator Tag OK htp-1.19/tests/tags.html.exp0000664000175000017500000000016312525674213016165 0ustar hoenickehoenicke blub htp-1.19/tests/options.htp0000664000175000017500000000174612525674213015766 0ustar hoenickehoenicke This text needs to be condensed. htp logo htp logo {opt DELIM=SQUARE} [opt DELIM=HTML] Generator Tag OKNotOK XML Generator Tag OKNotOK htp-1.19/tests/macro.html.exp0000664000175000017500000000055012525674213016330 0ustar hoenickehoenickemacro1 is set macro1 is empty string macro5 is empty string macro1:: macro2:val1: macro3:val2: macro4:: macro5:: macro6:val2: macro7:: macro7 raw:: macro8:: macro8 raw:: macro9 raw:fooabcval2: : htp-1.19/tests/phptest.htp0000664000175000017500000000021512525674213015750 0ustar hoenickehoenicke $$y) echo "The > sign does not close the php code!" ?> Now the php code is closed and $$ are not replaced. $$ htp-1.19/tests/png.htp0000664000175000017500000000166212525674213015054 0ustar hoenickehoenicke htp-1.19/homepage/0000775000175000017500000000000012543301704014161 5ustar hoenickehoenickehtp-1.19/homepage/source/0000775000175000017500000000000012543301704015461 5ustar hoenickehoenickehtp-1.19/homepage/source/source.htp0000664000175000017500000000012212525674213017501 0ustar hoenickehoenicke ___SOURCECODE___ htp-1.19/homepage/source/Makefile.sub0000664000175000017500000000146712525674213017731 0ustar hoenickehoenicke# # makefile - htp # # HTML pre-processor # Copyright (c) 2002 Jochen Hoenicke # p$(dir) := $(d) d := $(dir) ################# DEF$(d) := $(d)/htp.def SRC$(d) := $(d)/source.htp HTML$(d) := $(SRC$(d):%.htp=%.html) HTML += $(HTML$(d)) DISTDIRS += $(d) DISTFILES += $(d)/Makefile.sub DISTFILES += $(SRC$(d)) $(DEF$(d)) DISTFILES += $(d)/source.cgi.in CLEAN += $(d)/*~ $(d)/htp.rsp $(d)/*.html $(d)/source.cgi CLEAN += $(d)/htpdeb.out all: $(HTML$(d)) $(d)/source.cgi $(HTML$(d)): $(DEF$(d)) $(d)/source.cgi: $(d)/source.cgi.in perl -pe 's#___REF_URL___#$(REF_URL)#g;s#___HTP_DIR___#$(HTP_DIR)#g' \ < $< > $@ chmod a+x $@ rsync:: $(HTML$(d)) $(SRC$(d)) $(DEF$(d)) chmod a+r $^ $(RSYNC) $^ $(RSYNCDIR)/source/ rsync:: $(d)/source.cgi chmod a+rx $^ $(RSYNC) $^ $(RSYNCCGI)/ # restore parent dir d := $(p$(d)) htp-1.19/homepage/source/htp.def0000664000175000017500000000054012525674213016743 0ustar hoenickehoenicke htp-1.19/homepage/source/source.cgi.in0000664000175000017500000000167412525674213020072 0ustar hoenickehoenicke#!/usr/bin/perl -T -I. -w my $refdir = "___REF_URL___"; my $dir = "___HTP_DIR___"; my $picdir = "$refdir/pic"; my $sourcehtml = "$dir/source/source.html"; my $uri = $ENV{REQUEST_URI}; if ($uri =~ m!/source.cgi/([A-Za-z./-]+)$!) { $filename = $1; if ($filename =~ m!\.\./!) { $filename ="index.htp"; } } else { $filename ="index.htp"; } require "./hlhtp.pl"; $manlink = qq(TEXT); $includelink = qq(FILE); $optn = 0; $opts = 1; sub print_source { if (open FILE, "<$dir/$filename") { highlight_htp(FILE); close FILE; } else { print "File $filename not found.\n"; } } print "Content-Type: text/html\n\n"; open SOURCE, "<$sourcehtml"; while () { s/___FILENAME___/$filename/g; s!\.\./ref!$refdir!g; if ($_ =~ /___SOURCECODE___/) { print_source; } else { print $_; } } htp-1.19/homepage/Makefile.sub0000664000175000017500000000117312525674213016423 0ustar hoenickehoenicke# # makefile - htp # # HTML pre-processor # Copyright (c) 2011 Jochen Hoenicke # p$(dir) := $(d) d := $(dir) # subdirectories dir:=$(d)/source include $(dir)/Makefile.sub dir:=$(d)/ref include $(dir)/Makefile.sub ################# DEF$(d) := $(d)/htp.def SRC$(d) := $(d)/index.htp HTML$(d) := $(SRC$(d):%.htp=%.html) HTML += $(HTML$(d)) DISTDIRS += $(d) DISTFILES += $(d)/Makefile.sub $(SRC$(d)) $(DEF$(d)) CLEAN += $(d)/*~ $(d)/htp.rsp $(d)/*.html $(d)/htpdeb.out $(HTML$(d)): $(HP_DEF) all: $(HTML$(d)) rsync:: $(HTML$(d)) $(SRC$(d)) $(DEF$(d)) chmod a+r $^ $(RSYNC) $^ $(RSYNCDIR)/ # restore parent dir d := $(p$(d)) htp-1.19/homepage/htp.def0000664000175000017500000000021512525674213015442 0ustar hoenickehoenicke htp-1.19/homepage/ref/0000775000175000017500000000000012543301704014735 5ustar hoenickehoenickehtp-1.19/homepage/ref/file.htp0000664000175000017500000001317612525674213016411 0ustar hoenickehoenicke FILE has several optional parameters of differing purpose. The output file's name, the current date and time, and the contents of another file may be included. Another file's time, date, or size may be added to the output file as well.

    As with all HTML, these tags do not have to be on their own line, so the following is perfectly acceptable: File "" last updated ,

    NAME, TIME, SIZE

    To include information about another file, such as an archive file or graphic image, specify its name with the NAME attribute followed by the type of information to be displayed: File image.gif kilobytes Last modified ,

    For file size information, the value BYTE, KBYTE, etc. dictates how the information is displayed. In anything other than byte format, the information is displayed in floating-point notation. The amount of precision (the number of digits to the right of the decimal point) can be set with the optional PRECISION attribute. The default precision is zero (0), which means no fractional portion is displayed.

    At the request of many people, the TIME and DATE attributes will now accept formatting characters that are passed directly into the ANSI C library function. This allows for the time and date to be displayed in virtually any format. Users not wishing to mess around with this should stick to the default format, which is used if no formatting value is specified (i.e., just using ).

    Consult any C programmer's guide discussing the standard C library function strftime() for information on how to build a format string. If unsure, ask an experienced C programmer for help, or consider just sticking to the default formatting.

    INCLUDE

    INCLUDE files are pre-processed as any other file. The resulting text is incorporated into the HTML output as if the file had been copied into the source at the same location as the FILE markup tag.

    htp will automatically convert slashes and backslashes to match the operating system's directory separator.

    Additional parameters can be set in the FILE INCLUDE tag, which are interpreted as macros that are "passed" to the included file. The macros are available only to the include file (and any macros or included files it holds). After the file is completely included, the macros are no longer available. So: This tag will fail:

    Macros named "name" and "email" are set, and available inside the included file. They are not available, however, past the tag (which is why the second statement will fail.)

    TEMPLATE

    A template file is nothing more than a default include file, one that is included once the input text has been completely processed. So, an input file can define many "standard" macros, which are then expanded by a template file to form a consistent page layout.

    The template file can be set many times, but only the last filename specified will be processed by htp. If multiple template files need to be included, specify one template file, and from that file use FILE INCLUDE to branch off.

    Template files are most useful when placed inside an htp default file.

    SEARCH

    A search path can be specified, which is searched if an include file cannot be found. This is handy to keep a set of "common" include files that many documents in many directories may need to access. More than one directory can be specified in the search path, if they are separated by a semi-colon. Spaces should not precede or trail the search path string.

    When htp starts, the search path is clear. FILE SEARCH would be a handy command to use in an htp defaults file.

    EXECUTE

    When FILE EXECUTE is used, htp will launch a program (as specified by the EXECUTE attribute) and include its output as if a FILE INCLUDE was performed on the file. Either the OUTPUT or REDIRECT attribute must also be included.

    OUTPUT specifies the file the command will produce. This is used if the program is either hard-coded to produce output to a particular file, or relies on one of its command-line arguments to determine where to place the output. The output file is deleted after its results have been imported into the output file.

    If the program produces output straight to standard output (as most UNIX and some DOS programs do), then the REDIRECT attribute can be used. In this case htp will take care of the redirection. Depending on the OS features it will either append a '>' and the name of a temporary file or it will use pipe mechanism to directly redirect without temporary files.

    htp will halt processing with an error if the executable exits with an error code of anything but zero (0). Some programs, however, do not specify an error code when exiting, so the exit code is undetermined. If htp should ignore the error code, specify the NOERROR attribute. htp-1.19/homepage/ref/tutorial.htp0000664000175000017500000000650112525674213017327 0ustar hoenickehoenicke

    The Tutorial

    This tutorial should help you with the first steps in htp. This tutorial assumes that you are already somewhat familiar with HTML. You can find good HTML tutorials on the web, e.g. at the W3Schools. If you speak german, spanish, french or japanese, you should take a look at SELFHTML.

    On this and the following pages we want to give you an idea of how htp is used. If you read this the first time you should not follow the links to the reference manual.

    Writing simple htp files

    In their simplest form htp files are just ordinary html files. In that case the htp process just copies the file. However, there are some features of htp makes live easier. Let's have a look at a simple example:

    My first htp page This page was produced by htp.
    Copyright by , , last updated

    You can download the file tut1.htp and put it into an empty directory. Then you can invoke htp from the command line (e.g. from the DOS box) like this:

    htp tut1.htp tut1.html
    
    This creates a file tut1.html, your first html file produced by htp.

    In line 1 we use a special tag named set. Even though this looks like an html tag it is really an htp tag. When htp reads the set tag, it doesn't copy it over to the html file. Instead it defines the macro author and bind the value Joe Doe to it. This macro is later expanded in line 6 and line 12, to retrieve the author name again.

    The advantage of using macros is obvious if you consider the email macro in line 2 and 13. Normally, you need to type the email twice, once in the href attribute and once to show up on the page. If you have a typo in the href tag you probably won't notice it. With the use of macros you only have to type the email once. Also you have to update only one place when your email address changes.

    As you can see there are two ways to get the value, which is bound to a macro: One is the use tag in line 12. This tag is replaced by htp with the contents of the macro, Joe Doe in this case. However, if the macro needs to be expanded inside an html or htp tag, you can't nest a use tag. Instead the "$" character followed by the macro name can be used as shown in lines 6 and 13.

    In line 14 you can see another special htp tag, the file tag. This tag has many functions, however, in this case it is just used to get the modification date of the current htp file.

    In the next section of this tutorial we show you how to use htp in big projects where you have many web pages that should get a similar layout.

    Go to the next section

    htp-1.19/homepage/ref/toc.def0000664000175000017500000000357212525674213016221 0ustar hoenickehoenicke
    htp-1.19/homepage/ref/if.htp0000664000175000017500000000164412525674213016065 0ustar hoenickehoenicke block #1 [ block #2 ... ] [ block #3 ] IF, NOT, ELSEIF, ELSE, and /IF are the building blocks for conditional processing. The basic form is shown above.

    "Conditional" is either a "compare" or "is defined" operation. A compare operator is a test of the value of a macro against a literal string: ...

    and a defined operator is a test of a macro's existance:

    ...

    If the NOT tag is present in the IF markup, the evaluation of the conditional is reversed. The first IF or ELSEIF condition that evaluates to true is chosen. If none of the conditions is true the ELSE block is taken if it is present. A conditional block must be closed with the /IF tag. IF tags can be nested. htp-1.19/homepage/ref/history.htp0000664000175000017500000002346312543265764017202 0ustar hoenickehoenicke

  • Version ()
    • Bug fix: Support longer lines in response files.
    • Interpret command line arguments starting with ‘/’ as absolute paths. Options now always have to start with the ‘-’ character.
    • Fixed JPEG analysis to skip EXIF headers correctly.
    • Fixed wildcard macro ($*) matching attributes without values
    • Support for 64 bit linux.
    • <use name> works again
    • New snprintf file, so file size works under windows again
    • Fixed a bug that broke the EXPAND option for block metatags.
    • Fixed segfault in <WHILE macro="xyz"> for undefined macro.
    • Fixed segfault when processing empty lines in response files.
    • Fixed build process for BSD like systems
    • ELSEIF tag added to IF conditional processing.
    • New IMAGEURL tag to map URLs to paths within the local file system (used for image size detection).
    • Eat newlines after IF, ELSE, ELSEIF and /IF tags.
    • New option XML
    • New variable _htp_version
    • New Tutorial section in the reference manual.
    • New "*" parameter to support tags with variable arguments
    • Fixed parsing of html comments and embedded PHP code.
    • The ‘$’-operator now works in comments and PHP code.
    • When ‘$’ is used without curly braces, the scope is now more intuitive.
    • Removed crash when htp is invoked with an illegal option.
    • Made error messages more understandable.
    • Fixed parsing of jpeg files to support extended formats.
    • Preserve white-spaces in HTML-tags as much as possible.
    • Don't allow white-spaces between attribute name and value any more.
    • htp becomes SourceForge project
    • New location for on-line documentation,
    • The ‘$’-operator can be nested.
    • New tags: BLOCKDEF, INC, OUTPUT, QUOTE, WHILE
    • New attributes EXPAND and GLOBAL
    • Environment variables are now accessible as macros
    • New predefined macros: _htpfile_out, _htpfile_in
    • New "semi-condensed" mode
    • IMG tag supports png images.
    • New location for on-line documentation,
    • New location for on-line documentation,
    • First release by new maintainer, Robert King.
    • No change to behaviour of program from 1.10 at all.
    • Fixed a bug in the memory suballocator. Some CPUs will fault on non-DWORD aligned accesses, which suballoc does continuously. Essentially, htp will coredump almost immediately. Fixed.
    • Allan Todds pointed out a rather severe limitation regarding how htp handles HTML comments. If the comments are too long, htp would puke. This is a particular problem because JavaScript and VBScript are embedded inside a single comment. This has been fixed.
    • The memory suballocator has a new feature to release memory back to the system heap if it grows past a preset bound.
    • Richard Crane pointed out a real bugger: response files would not work with tabs or multiple spaces between file names. Fixed on both counts.
    • From Mark Roedel's suggestion, I've added comments to response files.
    • Metatags added!
    • Broke down and gave in ... time for a real release.
    • Added parameter support for FILE INCLUDE and BLOCK macros expanded with the USE tag.
    • $ macro expansion can now occur anywhere in a markup: the tag name, an attribute name, or an attribute value.
    • New memory allocator (suballoc.c) added, and several memory leaks found and squashed. Increased performance as well.
    • Finally! Added support for default ALT text for image files.
    • Support for project default files added.
    • New CONDENSE option added.
    • FILE TIME and DATE now report the source file's time and date, and not the current.
    • Options can now be placed in response files.
    • Options are processed in a single module rather than haphazardly throughout the code.
    • Support for using different delimiters around htp markups added. htp markups can now be surrounded by curly braces or square brackets. See Creating htp files for more information.
    • File templates now formally supported.
    • Macro store revised with hash table for faster lookups.
    • JPEG support finally added.
    • htp will now delete incomplete output files unless the PRECIOUS option is used.
    • Automatically places quotation marks around a macro expanded inside a markup provided it is not surrounded by other text. See USE for more detailed information.
    • Previously, the macro parser did not escape dual '$' characters. Fixed.
    • Added support for a defaults file. See Default files for more information.
    • Added support for an include file search path. See FILE for more information.
    • FILE TIME and FILE DATE now accept values, which are interpreted as formatting characters to display the time or the date. See FILE for more information and warnings.
    • FILE EXECUTE implemented.
    • Ported old linear-style readme.txt file to friendly, clean HTML on-line reference you are now using. 8-)
    • Block macros can now be embedded inside another block macro.
    • Hell's bells ... was not checking that macro existed before dereferencing.
    • Added dependency checking. htp will now only build the output file if any of the input files have changed (according to file timestamps). Can be disabled with the NODEPEND option.
    • Added some additional code to prevent numerous (but harmless) compiler warnings.
    • Added FILE SIZE, FILE DATE, and FILE TIME that works in conjunction with a NAME attribute to report respective information for an external file.
    • Switched to large model for DOS version, to avoid memory constraints of small model.
    • Added the UNSET tag.
    • Fixed bug related to re-defining macros and defining null-length macros.
    • Can now declare multiple SET macros in the same tag.
    • Various code issues brought to my attention by Joseph Dandrea of AT&T Bell Laboratories (joseph.dandrea@att.com). Joseph provided many helpful insights and pointed out many potential problems in a massive (and desparately needed) code review. htp is a much stronger program thanks to his excellent support.
    • In both response files and FILE INCLUDE's, the directory delimiter (forward slash in UNIX, backwards slash in MS-DOS) is parsed to match the native filesystem ... in other words, no need to change sources when moving from UNIX to DOS or vice-versa. Suggested by Chris Jobling (C.P.Jobling@swansea.ac.uk).
    • IFNOT tag removed, replaced with IF NOT, which is more compliant with HTML.
    • Braces around macros implemented.
    • htp was leaving linefeeds for lines that contained stripped-out tags. The resulting HTML was somewhat sloppy. Fixed.
    • Error and warning reporting made more consistent
    • Ported source code to Linux. Code should also be portable to other UNIX-type operating systems as well.
    • Cleaned up the code for portability and maintainability.
    • Added conditionals (IF, NOT, ELSE, /IF).
    • Added block macros (BLOCK, /BLOCK).
    • Added response files.
    • Initial release. Many features unimplemented.
    htp-1.19/homepage/ref/macros.htp0000664000175000017500000000060412525674213016746 0ustar hoenickehoenicke

    Predefined macros

    There are only a few predefined macros:
    _htpfile_in
    The main htp file that is being processed.
    _htpfile_out
    The name of the html file that is created.
    _htp_version
    The version number of htp (e.g. "1.15").

    Also every environment variable is implicitly defined as macro. htp-1.19/homepage/ref/img.htp0000664000175000017500000000222012525674213016232 0ustar hoenickehoenicke

    img is a standard HTML tag. htp can add the specified image's width and height to the tag automatically. This has the advantage of not having to determine each image's size manually, which is especially useful if the image may change frequently.

    htp adds this information with the WIDTH and HEIGHT markup attributes. If htp detects these attributes are already present in the tag, it will not modify the values. If htp cannot find the image file, it will issue a warning but not halt processing.

    At this time, GIF (Graphic Interchange Format), PNG (Portable Network Graphics), and JFIF (JPEG File Interchange Format) are supported.

    The IMGXY and NOIMGXY options control whether or not htp actually adds this information as it executes.

    Since htp is able to lookup files only in the local filesystem, the IMAGEURL tag may be used to map URLs to local files.

    htp can also add default ALT text to IMG tags using ALTTEXT.

    htp-1.19/homepage/ref/expand.htp0000664000175000017500000000716612525674213016753 0ustar hoenickehoenicke

    The global attribute

    Normally when you define a macro it is only defined in the current scope. A scope is for example the definition of a metatag. Once the definition is expanded and the metatag has finished the macro is automatically removed. In some cases you want to define a macro inside a metatag and use it later. You can do this with the global attribute that you can add to set, inc, block, def, and blockdef tags.

    The expand attribute

    The expand attribute is not a tag of its own but is an attribute of all block tags even metatags defined with the blockdef macro. Normally htp uses a lazy evaluation strategy, i.e. it expands htp tags, metatags and macros when the HTML document is written not when they're stored into block macros. When you use a macro defined with the blockdef tag the html code between the tags is just copied literally into the macro named block, without any expansion going on.

    However, if the block tag is marked with the expand modifier it is expanded immediately. This is useful if you want to store something in a block macro, that depends on the current value of another macro. This other macro may no longer have the correct value when the macro is expanded. Here is some code that demonstrate when the htp tags are expanded:

    a is expanded at time . b is expanded at time . contents of a: contents of b: c is expanded at time ; d is expanded at time ; e is expanded at time ; a is defined for the 2nd time . This produces the following: a is expanded at time 1. b is expanded at time 0. contents of a: a is expanded at time . contents of b: b is expanded at time 0. c is expanded at time 1; a is expanded at time 1. d is expanded at time 1; a is expanded at time 2. e is expanded at time 2; a is defined for the 2nd time .

    When block a and block b are defined in lines 2-7 the contents of a are taken literally, however, the contents for b are already expanded so the macro time is evaluated. So a is expanded when it is used, while the contents of b are already expanded.

    In line 10 and 12 the use tag is used with the noexpand attribute which prevents the expansion of the macro value. Here it is used to show you what the value of the block macros really is.

    A more important reason to use the noexpand attribute is to prevent double expansion and to restore the original lazy expansion policy when you have to use the expand attribute as for block d in the example above. See the section example in the metatag tutorial. Rule of thumb: The use tags in an expanded block should be tagged with noexpand.

    htp-1.19/homepage/ref/hlhtp.pl0000664000175000017500000000750712525674213016432 0ustar hoenickehoenicke# # functions for pretty printing of htp code. # # options: # $optn include line numbers # $opts include EBNF like syntax $tagstart = qq(); $macrorefstart = qq(); $attribstart = qq(); $valuestart = qq(); $stringstart = qq(); $synstart = qq(); $commentstart = qq(); $manlink = qq(TEXT); $includelink = ""; $endtag = qq(); $syntax="[](|)[]"; $replacetags = "alttext|block|blockdef|def|file|if|inc|img|imageurl|opt|output|quote|set|undef|unset|use|while"; my $incomment = 0; my $infiletag = 0; my $ininclude = 0; my $intag = 0; my $inhtptag = 0; my $instring = 0; $optn = 0; $opts = 0; sub colormacro($) { $_ = $_[0]; s!(^|[^\$])(\$([A-Za-z0-9_-]+|[^\$\{A-Za-z0-9_-]|\{[^\}]*\})) !$1$macrorefstart$2$endtag!xg; if ($opts) { s/[](|)[]/$synstart$&$endtag/g; } return $_; } sub parsehtml($) { my ($in) = @_; my $out = ""; $in =~ s/&/&/g; while ($in) { if ($instring) { $in =~ s/^((\\.|[^\\\"])*)//s; $file = $1; if ($ininclude && $includelink && $file !~ /\$/ && $in =~ /^\"/) { $include = $includelink; $include =~ s/FILE/$file/g; $out .= $valuestart . $include . $endtag; } else { $out .= colormacro($file); } if ($in =~ s/^(\")//) { $out .= $1; $instring = 0; $out .= $endtag; } } elsif ($incomment) { $in =~ s/^(([^-]|-*[^>-])*)//s; $out .= $1; if ($in =~ s/^(--+)>//) { $out .= $1.">"; $incomment = 0; $out .= $endtag; } } elsif ($intag) { # colorize attrib value pairs $in =~ s/^(\s*)//s; $out .= $1; if ($opts) { if ($in =~ s/^($syntax)//s) { $out .= $synstart.$1.$endtag; } } if ($in =~ s/^>//s) { $intag = $inhtptag = 0; $out .= ">$endtag"; } else { $ininclude = 0; $excl = $opts ? '](|)[>\s=' : '>\s='; if ($in =~ s/^([^$excl]+)//s) { $attrib = $1; $out .= $attribstart . colormacro($attrib) . $endtag; $ininclude = ($attrib =~ /(include|template)/i); } if ($opts) { if ($in =~ s/^($syntax)//s) { $out .= $synstart.$1.$endtag; } } if ($in =~ s/^(=)//s) { $out .= "="; if ($opts) { if ($in =~ s/^($syntax)//s) { $out .= $synstart.$1.$endtag; } } if ($in =~ s/^\"//s) { $out .= $stringstart.'"'; $instring = 1; } elsif ($in =~ s/^([^\s>]*)//s) { $file = $1; if ($ininclude && $includelink && $file !~ /\$/) { $include = $includelink; $include =~ s/FILE/$file/g; $out .= $valuestart . $include . $endtag; } else { $out .= $valuestart . colormacro($file) . $endtag; } } } } } else { $in =~ s/^([^<]*)//s; $_ = $1; # replace some spaces with nbsp s/^ / /g; s/\t/        /g; s/(\s) /$1 /g; $out .= $_; if ($in =~ s/^<(\/?)($replacetags)\b//si) { $tag = "\L$2\E"; $text = "$1$2"; $ml = $manlink; $ml =~ s/TAG/$tag/; $ml =~ s/TEXT/$text/; $out .= "$tagstart\<$ml"; $infiletag = 1 if $tag =~ /file/i; $intag = $inhtptag = 1; } elsif ($in =~ s/^<(!--)//s) { $out .= $commentstart . "<" . $1; $incomment = 1; } elsif ($in =~ s/^<([^\s>]*)//s) { $out .= $tagstart . "<" . colormacro($1); $intag = 1; } } } return $out; } sub highlight_htp { my ($FILE) = @_; my $linenr = 0; print "

    \n"; while (<$FILE>) { $_ = parsehtml($_); if ($optn) { # add line header $head = sprintf '%2d. ', ++$linenr; $head =~ s/> /> /g; $_ = "$head$_"; } chomp $_; print "$_
    \n"; } print "

    \n"; } 1; htp-1.19/homepage/ref/unset.htp0000664000175000017500000000122212525674213016615 0ustar hoenickehoenicke UNSET removes (or deletes) a macro and it's definition. The macro is subsequently not available for use in the pre-processed files. (Note that simply redefining the macro with another SET or BLOCK definition with the same name is acceptable. The old macro definition will be removed automatically.)

    For example:

    More than one macro may be removed in the same tag: htp-1.19/homepage/ref/set.htp0000664000175000017500000000226012525674213016255 0ustar hoenickehoenicke SET creates a macro definition that can later be expanded anywhere in the HTML document. To create a macro:

    The macro "emailaddr" can then be expanded later. The USE tag is used to expand the macro outside a tag (i.e., into the regular text). If the macro needs to be expanded inside a markup tag, use the '$' operator.

    Multiple macros can be declared in a single markup tag, as the second syntax line shows.

    SET should only be used for a single line's worth of text. Multi-line macros can be defined with the BLOCK tag. The BLOCK tag is also useful if the macro contains a quotation character and you don't want to fool around with special escape characters.

    Macros can be redefined by using another SET command with the same macro name. The prior definition will be destroyed, however. Also, the macro can be removed (destroyed) with the UNSET tag. htp-1.19/homepage/ref/include.htp0000664000175000017500000000354612525674213017115 0ustar hoenickehoenicke

    How to put common parts in different files

    When you have a web site consisting of several pages, you may notice that you often need to add the same html code to all pages. With htp you can put common code in extra files and include them in all pages. Here is an example.

    Here is the content

    As you can see the file contains almost only the contents.

    In line 2 the file
    tag is used to include a different file. When this tag is processed, htp will read and process the file header.hti (see below) and after it is finished it continues after the tag. The included file contains the usual html header and the navigation bar. All macros defined before the file include tag are also visible in the included file. So the macro title defined in the first line is used in the header to produce the title of the page: <use title>
    Navigation bar
    Main
    Example
    Similarly, in the last line of our example the file footer.hti is included, which contains the common copyright information and the necessary closing tags:

    Copyright by Joe Doe.
    last updated
    In the next section, we will show you a similar mechanism, the template. htp-1.19/homepage/ref/template.htp0000664000175000017500000001267012525674213017303 0ustar hoenickehoenicke

    How to use templates

    Instead of having the header and footer in separate files as in the previous section, it is often more convenient to have them in a single file, which is a template from which the web pages are produced.

    A simple example

    Such a template would look as follows. Click here to download tut3.htt.

    <use title>
    Navigation bar
    Main
    Example

    Copyright by Joe Doe.
    last updated

    The contents have to be stored into the macro body and are inserted in line 11. To define a macro whose contents span multiple lines you can use the block tag. Here is the file tut3.htp that makes use of the template:

    Here are the contents

    As you can see the file contains almost only the contents.

    In line 1 you can see yet another syntax of the file tag. The template attribute is similar to include attribute, but the inclusion is deferred until the file is completely processed and the macros are defined. You can have at most one template per file but this is no serious limitation. Of course, the template and the main file can include other files with the <file include> syntax.

    You can see the strength of this template mechanism if you compare this reference manual with the previous at . As you can see the layout changed drastically, however, this was achieved by changing only a single file, the template file.

    Including more than one piece of information

    Of course, you can have more than one place in your template where macros are expanded. Here is an example that displays informations about employees in a common layout. For each employee you have a htp file, which just defines the personal informations in several macros, and a single template file, that lays out the informations:

    The template employees.htt looks like this:

    Photo
    Room:
    Phone:
    Fax:
    Email:

    This example shows, that you can mix includes and templates. In this case the template includes a common header and footer, which may be shared with several templates. In line 6 and several other you can see the if tag. This tag can be used to check if a variable is defined or if it has a certain value. In this case the tag is used to omit information that wasn't defined for this person.

    How to include numbered sections

    One feature of htp is a loop construct that enables you to create numbered sections. Here is the example for the contents file. This page explains how to use sections. The htp file should define macros for each section. The htt file uses these macro in a while loop. This file defines several macros numbered from one to three. Here is the corresponding template tut4.htt.

    On This Page

    • .

    In lines 5-9 the table of contents is generated. The macro i is used as counter variable. In line 5 it is initialized to one. The while loop in lines 6-9 is repeatly executed until the macro para$i is no longer defined. It creates a list item, prints out the section number, then a link to #sec$i on the current page, and writes out the title of the section. In line 8 the macro i is incremented. An analogous mechanism is used to include the sections in lines 14-19.

    This closes our introduction to templates. In the next section you will find some hints how you can organize your htp projects

    htp-1.19/homepage/ref/block.htp0000664000175000017500000000141512525674213016555 0ustar hoenickehoenicke text block

    BLOCK and /BLOCK are used to create block macros, which are similar in use to SET macros, but can be multi-line definitions.

    Any text and formatting may be set inside the block. You can use any htp or user defined metatag including FILE INCLUDE. The metatags won't be expanded before the block is USEd except if you give the EXPAND parameter.

    The block macro is dereferenced (expanded) with the USE tag or the '$' operator. See the notes on the USE tag on how to pass parameters to a block macro.

    htp-1.19/homepage/ref/output.htp0000664000175000017500000000126712525674213017030 0ustar hoenickehoenicke text block

    The OUTPUT tag can be used to create auxillary files besides the main HTML file. The text between this tag and the corresponding </OUTPUT> tag is written to output file.

    Normally the outputfile is cleared before writing to it, but you can use the APPEND attribute to extend an existing file. The text written to the file is normally not expanded, i.e. all tags inside this block are not executed but written unmodified to the file. However, you can use the EXPAND attribute to override this behaviour.

    htp-1.19/homepage/ref/intro.htp0000664000175000017500000000664112525674213016624 0ustar hoenickehoenicke

    An HTML pre-processor

    htp is an HTML pre-processor. It is designed to be a flexible authoring tool that can easily be integrated into the design process.

    htp works by processing special HTML files and producing as output regular HTML files ready to be served up. The original HTML files are "special" because they (possibly) contain certain markup tags only recognizable to htp. These tags are formed very similarly to standard HTML tags. This allows for an easy learning curve and the ability to use visual HTML editors to build htp files.

    This on-line reference was entirely designed with htp. The htp Home Page has a hyperlink to the latest copy of htp, which includes an executable file, a client-readable copy of this reference, the original files used to build the reference, and a full copy of the original 'C' language source code (either for perusal or porting to other platforms).

    A WWW page was produced by the author, was then maintained by Robert King () at and is now available at .

    Background

    In building my own Web pages, I felt it important to maintain a consistent layout across all documents produced. This was easy enough at first, but after building 20+ pages, it was more and more difficult to change or update the style or information across all pages. I can only imagine the problems a site with 100 or more pages would have.

    htp is a simple response to this problem. Although there are a number of interactive HTML editors available, none of them had all of the features I've placed into htp. I'm also uncomfortable using windows based HTML editors, for a variety of reasons. htp allows me to produce HTML files with any text editor. Once finished, htp is executed from the command-line to "build" the final HTML code that goes on the HTTP server.

    Build is an appropriate term. The HTML source files can ultimately be used to import various files, letting the author create a sort of template for the various headers and footers that are part of the HTML document.

    Distribution

    htp is licensed under the terms of the Clarified Artistic License.

    Porting to other platforms

    htp was written in as much standard ANSI C as possible. Jim was anticipating porting it to platforms other than DOS and Linux. Indeed, we have ported it to SPARCstation running Solaris, to x86 running BSD and to a Digital AlphaStation running Ultrix.

    If you run into problems porting htp, please email us as thorough a description of the error(s) as possible, We'll be more than happy to try and help you through the process. You can use the bug forum at the SourceForge project page.

    It should normally be enough to edit Makefile.config in the source distribution, especially look for HAVE_xxx macros and remove those that you don't have (htp will then use it's own methods). The next file to look for is os.h, which already contains a lot OS specific code. If you are successful in porting htp to another platform, we would appreciate an email. Thanks in advance.

    htp-1.19/homepage/ref/comment.htp0000664000175000017500000000124412525674213017125 0ustar hoenickehoenicke

    This is a simple comment that is not included in the output. This is useful when commenting metatags, since the metatags do not appear the output either. Example:

    Note that these comments should not include < or >, that is you should not use it to comment out htp code. For that purpose use something like this:

    ...

    Make sure that the variable is never defined and xyz should be the reason why you don't want to include this block

    htp-1.19/homepage/ref/Makefile.sub0000664000175000017500000000407712525674213017205 0ustar hoenickehoenicke# # makefile - htp # # HTML pre-processor # Copyright (c) 2011 Jochen Hoenicke # p$(dir) := $(d) d := $(dir) # subdirectories dir:=$(d)/pic include $(dir)/Makefile.sub ################# DEF$(d) := htp.def macros.def toc.def htp.htt SRC$(d) := alttext.htp block.htp blockdef.htp bugs.htp comment.htp \ def.htp default.htp expand.htp file.htp history.htp \ if.htp img.htp imageurl.htp inc.htp index.htp intro.htp macros.htp \ metatag.htp opt.htp options.htp output.htp quote.htp set.htp template.htp \ undef.htp unset.htp usage.htp use.htp while.htp wishlist.htp \ tutorial.htp include.htp license.htp DEF$(d) := $(DEF$(d):%=$(d)/%) SRC$(d) := $(SRC$(d):%=$(d)/%) HTML$(d) := $(SRC$(d):%.htp=%.html) MISC$(d) := $(d)/hlhtp.pl $(d)/pphtp.pl $(d)/styles.css HPTUTDIR := $(d)/tut HPTUTSTAMP := $(d)/tut/.stamp HPTUT_SRC := $(HPTUTDIR)/tut1.htp $(HPTUTDIR)/tut2.htp HPTUT_SRC += $(HPTUTDIR)/tut3.htp $(HPTUTDIR)/jh.htp HPTUT_DEF += $(HPTUTDIR)/footer.hti $(HPTUTDIR)/header.hti HPTUT_DEF += $(HPTUTDIR)/tut3.htt $(HPTUTDIR)/tut4.htt HPTUT_HTML := $(HPTUT_SRC:%.htp=%.html) HTML += $(HTML$(d)) $(HPTUT_HTML) DISTDIRS += $(d) $(d)/pic DISTFILES += $(d)/Makefile.sub $(SRC$(d)) $(DEF$(d)) $(MISC$(d)) CLEAN += $(d)/*~ $(d)/htp.rsp $(d)/*.html $(d)/htpdeb.out $(d)/ref.tmp $(HTML$(d)): $(DEF$(d)) $(HPTUTSTAMP) $(HPTUT_DEF): $(HTML$(d)) touch $@ $(HPTUT_SRC): $(HTML$(d)) touch $@ $(HPTUT_HTML): $(HPTUT_DEF) all: $(HPREF_HTML) $(HPTUT_HTML) clean:: rm -rf $(HPTUTDIR) $(HPTUTSTAMP): mkdir -p $(HPTUTDIR) touch $@ .PHONY: clean-ref install-doc rsync-ref rsync-tut install: install-doc install-doc:: $(HTML$(d)) $(SRC$(d)) $(DEF$(d)) $(MISC$(d)) mkdir -p $(pkgdocdir) for i in $^; do \ $(INSTALL) $$i $(pkgdocdir); done install-doc:: $(HPTUT_HTML) $(HPTUT_SRC) $(HPTUT_DEF) mkdir -p $(pkgdocdir)/tut for i in $^; do \ $(INSTALL) $$i $(pkgdocdir)/tut; done rsync:: $(HTML$(d)) $(SRC$(d)) $(DEF$(d)) $(MISC$(d)) chmod a+r $^ $(RSYNC) $^ $(RSYNCDIR)/ref rsync:: $(HPTUT_HTML) $(HPTUT_SRC) $(HPTUT_DEF) chmod a+r $^ $(RSYNC) $^ $(RSYNCDIR)/ref/tut # restore parent dir d := $(p$(d)) htp-1.19/homepage/ref/opt.htp0000664000175000017500000000114012525674213016260 0ustar hoenickehoenicke OPT is an htp tag that can be used to specify processing options inside the actual document being processed. The options are used exactly as they would be on the command-line, although they are not preceded by a ‘-’ character.

    Click here for more information on using customization options with htp. htp-1.19/homepage/ref/bugs.htp0000664000175000017500000000134112525674213016421 0ustar hoenickehoenicke

    You can use the bug forum at the SourceForge project page to browse for other known bugs or report one yourself.

    • Dependency checking is not completely functional. Right now, the dependency check function is not expanding macros as part of its search. Again, this is something I will attack in a future release.
    • The GIF processing is not correct. Andrew Ward has pointed out that the location htp assumes to be the picture dimensions is actually the recommended screen display dimensions. I will investigate and fix in the future. Note that in most cases, this is acceptable since they are one and the same, but no guarantees.
    htp-1.19/homepage/ref/pphtp.pl0000664000175000017500000000101312525674213016430 0ustar hoenickehoenicke#!/usr/bin/perl # # pretty print htp code. # # options: # -n include line numbers # -s include EBNF like syntax require "hlhtp.pl"; while ($ARGV[0] =~ /^-(.*)/) { $_ = $1; $optn = 1 if (/^n$/i); $opts = 1 if (/^s$/i); shift @ARGV; } print "

    \n"; while (<>) { $_ = parsehtml($_); if ($optn) { # add line header $head = sprintf '%2d. ', ++$linenr; $head =~ s/> /> /g; $_ = "$head$_"; } chomp $_; print "$_
    \n"; } print "

    \n"; htp-1.19/homepage/ref/htp.def0000664000175000017500000000024512525674213016221 0ustar hoenickehoenicke htp-1.19/homepage/ref/inc.htp0000664000175000017500000000210412525674213016230 0ustar hoenickehoenicke The INC can be used for incrementing/decrementing a variable or for variable addition. The basic form is shown above.

    The "increment" is anything that evaluates to a integer. It can be a literal string or a macro preceeded by the '$'-operator. The macroname must be the name of a defined macro that contains an integer. If the increment is ommitted it defaults to 1. The effect of this operation is that the macro is redefined to contain the sum of its previous value and its increment.

    To increment or decrement a variable you can use this form:

    Note that INC doesn't check if the strings really denote integers. It may give weired results when used on arbitrary strings. The integer values are limited to the range -2^31..2^31.

    Note further that htp wasn't designed to do extensive calculations. The INC tag is useful in conjunction with WHILE to iterate over the defined blocks. htp-1.19/homepage/ref/imageurl.htp0000664000175000017500000000471312525674213017274 0ustar hoenickehoenicke

    IMAGEURL tells htp, where to find images on the local file system. declares an URL replacement that is used for size lookups in any IMG tag. This definitions takes effect only if the IMGXY option is enabled. Beacause htp can't lookup files in the world wide web you have to map absolute image URLs to a directory in the local file system.

    When an IMG tag is encountered where htp has to insert width and height the defined URL replacements will be taken into account (later definitions take precedence to earlier): For each defined imageurl it checks (case-insensitive) if it is a prefix of the image's SRC attribute. If it matches this prefix is replaced by the given PATH. If no IMAGEURL matches the SRC is considered as relative link and looked up in the current directory.

    For example:

    For this line: the local filename "logo.gif" will be used to determine image dimensions (no URL replacement). For this line: the local filename "/var/www/my.domain/logo.gif" will be used. But for this line: the local file cannot be found (no prefix match), so the image dimensions will not be added. Order is important; last IMAGEURL tag takes precedence: and are mapped to /var/www/htdocs/image.gif and /var/www/test/image.gif, resp. If the order of the imageurl lines would be swapped, the second image would be mapped to /var/www/htdocs/test/image.gif.

    If IMAGEURL is specified with a URL but no PATH attribute, it is treated as an undefine, and is removed.

    Since you usually need the url mapping for a number of images used throughout a set of documents, IMAGEURL is most appropriately put into an include file or the htp.def file.

    In addition to WIDTH and HEIGHT, htp can also (semi-)automatically add an ALT text attribute to IMG tags.

    htp-1.19/homepage/ref/styles.css0000664000175000017500000000076412525674213017011 0ustar hoenickehoenicke.quote { margin-left:5mm; font-size:10pt; font-style:italic; } .tocf { vertical-align:baseline; text-align:right; } .toc { padding-left:7px; padding-bottom:3pt; text-indent:-7px; } .noline { text-decoration:none; } .htp-tag { color:#000080; } .htp-macro { color:#c00000; } .htp-attrib { color:#800000; } .htp-value { color:#c08000; } .htp-string { color:#c08000; } .ebnf { color:#000000; } .comment { color:#800000; } htp-1.19/homepage/ref/usage.htp0000664000175000017500000000561712525674213016577 0ustar hoenickehoenicke htp is designed to be run from the command-line. Basic usage is as so:

        htp [options] <source filename> <final HTML filename>
    

    Command-line options are discussed in the options and customization section. Most options can also be embedded in the htp source files themselves.

    The source file contains standard and htp-specific markup tags. htp processes the source file and writes the resulting output to the final HTML file.

    To handle larger sets of files, htp also accepts a response file, which lists input/output filename pairs and additional response files. A response file is specified as so:

        htp [options] @<response filename>
    

    A response file is a text file, with input and output filenames specified on each line, or alternatively, another response file. Also, options can be included provided they are preceded by a minus sign (‘-’), as if they were typed on the command-line. Since the response file is processed once and in order, options should be placed before specifying any files or response files. Finally, a comment can be placed in the response file by adding a semi-colon. All text on the line beyond the semi-colon will be ignored.

        ; sample response file
        -CONDENSE -IMGXY
        index.htp index.htm
        page1.htp page1.htm
        feature/feature.rsp
    

    A hierarchy of response files can be created using this format.

    htp will automatically search for a default response file named "htp.rsp" if no response file is specified. Therefore, to execute htp with a default response file, type

        htp [options] @
    

    And, in a response file, only a new directory needs to be specified to use a default response file:

        feature/
    

    Note that the trailing slash (or backslash) must be included for htp to properly discover the response file.

    Additionally, htp will automatically convert slashes and backslashes for file names in all response files and htp special tags only. This means that response files and file names specified by a FILE INCLUDE do not need to be changed if the files are taken back and forth between a DOS and UNIX platform. It will not convert slashes in standard HTML tags. It will convert them internally if the file must be accessed, as in the case of IMG, but the pathname will not be changed in the final output.

    While processing, htp will display informational, warning, and error messages. Informational messages are preceded with a "[-]" string. Warning messages are preceded with a "[*]" string. Error messages are preceded with a "[!]" string. Error messages will halt processing of the file, and htp will exit with an error level of 1 (one). htp-1.19/homepage/ref/pic/0000775000175000017500000000000012543301704015510 5ustar hoenickehoenickehtp-1.19/homepage/ref/pic/logo.png0000664000175000017500000006173312525674213017200 0ustar hoenickehoenickePNG  IHDRitg pHYsod tEXtComment* IDATxTUY.L꾯L(J9t9 Dr9  P1!fE({#VXuja9V,+saY$'уW+zz[]n\1e8V!ec/^J%v^[FHpΝKO}ų gOY^\kv;rh?w E <7dF}p?U[}}x%.xeRo5Gy5@-(A 2k9Hk޴:N7_wPFx+]kLO~+Kw.y8x``JϞ2Cb]>cشb_/^8zŶ/j1(O< |@K řzq"}sĂ Uˋˋs,f~E )ܝAXo%}&Z-@_De3_,cD/~>^ T( #1JCW+z =uI:ɜ7}>g "BLe4T -"Ȱ=݌&dRBlFuea $9o}KK-zz qjID"ޞfF6f8uO"[6QڶJMIxl$bEr777ڷ#tϟq\8ш5Zg7~uhh,uXIVƞၔeCpSʢ D%oMoˋˋ=s#BfS"C.\Y{ucrb i<\bԱzXp Xf\wo=L[,G0S枎P UԕqR!ҒHDp,!,("G /QÝ_/^\/ӯO~&nvNhqNVH Z^OLJLLMIڅ}+DH_OO[+3-^-!*$&, σ Nle֐t*ϚZ_?~whA?7; ٧Z@^\D-@pkgc%#)..þEFkCdmت ,tܿ @S*".,g(*@Q th.F G1jʊ/&XGS£Tinq~6G|50-(k\x/E11^\UY4Uиt=n:0uMv);YD8$v!Ns(=״v mO\h 7{l8M]ښeue\Bdx(7h[֎D< ,4ڗXg[+Ӄ}!l5߽ɆhA%:*33҃zJ"dǍ,mχƩEyZF9ev% o3E~uP^AbgIF;^Xf]Iё7zϸ^pv<(peWeP#됣fuBu[ n _0O v<1rC}sI-}*smvf:iyCcݷtS{uUv&y jaWNB e <' K~=0 ~LC~ZGCHNjgc/Ɨwv $ݪz*)) !HW*Q\ \_.)"_kc9ҹ)CCݡ+t5/0}}hᙩu9w3Bx}_nUp)}}^ [7o"F22< ={@ujKJGk^ε-/./6./Z^QOZ ]A]!rY8_-zSnttyiyo]^,[^Xk'+5dBxDp ̗qlTYy<`|$Et糝SM!_O!1Lp F3HS;\],*l["PUVSRL ?7-*ȏ`ڵI<;S#}7'(W_daA~n}YmɁ&.,闖h2فk.m:\㪦PY^vx" _H{4TTQ'1aAd*ښ FV Y) e%Ĕdx# rwIu9\;2Xy'98s Hv =ɵU'/jde"?+Z!:ȃQٷnf\G"TW`غa~^y-mE+9wgfطl4Q ?PylgO+hi5MIdz~?ge!.;~:K ×gAd4T4$/KP   qܑ4{tVsspR Yc;MUTdvj/a4aPQkM<{2,'.,m{7'%C=A@5F $ة(6֍۶l߲}f} Yt7H,<\3uwn?PhaLcb_#=UԌ _H#%9)2<,,4$$8]::ZF֖vvVi` 삺M)#).%&.JJ0ɶAv֍lĕ`VnmDmlXixUH{jblb뭩3O --c0mݸ>&*2)1!9))O vxiYgcǞV005171&~M:8A*5@"x  qq`7%lG a^=ulOqarၶ{}sOG>i,X7,w0%)ι@LzZZVfFRB./ϝNw7 lmmHFQ,0140{*cfdi:F H L ̈́y Z<)Bą} |}ZjJ rrҒB"|<|"`tDxXHP/M]MMY1Nrd?+,o̜??kjIk۫Zj:Fy5+ >bdYsO6 jA΅}}%Dń:3y#8vҒKPE: XB!/# vHyzGGEEGF:ژ#{G7'EYey ~.Rw㟥i.; MBJcbO؄Yi4ֵ/ii"s/` }:<4tsxw*b,}& KXO[EF0~JQUU5gAWKSK0 Ɔ>DF ,qS\e>^7XGC]U;0Ejv!*64$ӔZV6Ii'{I;kJiOx6, DUn_~ՔFZB\X|?Q|ldxps ';on_ngҤ9kNݙ<6Fn$$*vNߕeVcV} Sv'RzU:5LTk w,,S;ܙF|X8sr84+(HX&4 NhVu46ӂa\`qA,e Z ["&G Svk.{*W2ا o`aI? *`l]Gu TRKR)2 U6/6ǥH3:KM֟27m+b-)sW47?ۛڙAe}y#}5Քw;Qw\ˑx]g;zidPq}-5t?؞)y6 4TSe ӓCs2j+է7C~ 7`Ņ%Lu7f*~cG[[:cϵElGTS ;99O/D0?ʌ1R<7kq$((,.hlKzN#BasE6 -sm&'=zx.T\!$KQEaN]ĉ:7s'VrU1Պ1%/*brcgv}X3qd5rD|׋( #Qk=U ˋ%ˋ Ifo3,YLyv1@G>;3E;3Y @th뷭Po߂Qܔ[꧁h跭O6__okU?,n)pAfb1]Is43F9`f`n T/AHk+dcFD8 IDAT%c"roߊTgv֍gNf)lSSר!v?n/ʊB/]E!AȋDΟ3|k* ?iy(;Gn%,M, x,RnZOI#lQPUiM||1N 1_7+`}Sݮswnd.85O ԯ1|mxvl򓌥 Kc km! ?jM9ćwN|rRʊ rt|lghH 3ts!8)b|rܓR&x3hnc5)A.hXc@ Cǚ ?;}dQo8fۼMJ27eC &$)+4R p JHzyRUijʦ veBJv>vwCxS42M`D~ý;} ,k{[9D!k;68p "Ņ(σ?Tpm#HiIK2& p KJ 33mBDh I}~{i"rv|fT#Mh/%9N#tھ8WVܶ:{A\XPJLLP/`V!^nq!c<`L 3Pjkm_RLDz/ffCl|\2R,z; ⼎4d6?lwE3|gvz8c8Lv1:P臬f0>R*Jק#‚bu@d̾6B#4Ul-tƒܲCIm"sW10@!3CMy)U?݀+sc%T;;:#©B* rZ0E6s;B\D6V!r SFx;B8 HAFZ$-&PQR\^j*㌎š/=J]#u@XY1uX>XCUH_o#u2<4slecem^.8M뾗ef'ssoLYJ~.vJG)DeTDxP`@? Clafl̇:6\~$ՔdM4<8#(+ Cb߁rr4}++ر}+1eHp+y ?oG NV=^6b?&‡A5ehhؽ龯7;,$$$(;:;5_ \?"B,O̚SU# n uHr2,bbж-Ģ9T6VQjom62tWVZ`z3 c'NBmWިȈPfw612ZZ;;i4!ECSWӦ sq$Ķ)~Ass@ F!&lqƟ tMv{9Fzw>;A+G0~ϝ.Nv֐)~mm@5xalu tM &|Rdeedij*[# RB ^Gm\8o72Ч]qn2vs6Ɍ=U @^>)c_CE 652HLONJ#(o/bݡ 5_y=paminijBM371&&4 (* }EəR\ Dpqsl"nKs3%9i0b.glg ] `<|b_EI|J/m8ٶ89$B@? k.ϝ`7Who`gXY71206uA 烶;Ӥ !qX>N/7,ecuXv Q,wTtέgG&_p}˜,ML HߛE,Y1g/!|vyz:;IKस@5=kMbbmTUQ=yӇ?K3F;נ?RA_N]S {~@{&sLN1j"B,S -h? eS"ݵGf2y}gL=ڔtwԄ1qTH_޾܂Ԕ_CMEUQAAV.2{E(1PÔ!VW?F %fEy!g 0RS6R0ީfdShXgjSﰧ=O\Ǎ~G L^7hڍFJ\ܬp¿i Qd [\=2<&kN=mRkS==?-Fka9]E=)m[U -]&VaM6ǩize'<myE:!(gb8VR|K#TSU#|$y2}Dfnj]˸57Ռ?h-vljKjXJjY+Zj7o9 zT_9dѵY]>?FjLZDXȭsVfYX' h? @:BeHH2Ӳ2Jܸ?Ut>1Py d6 =?w{Lw+oTeTk]ehiA4pԱ>[DmG|rڵQ0ЬKF]PS Uh1OUUemMu/?.&pL;9b*\_M#:C]=bR],YnCI6jaaVǬr[4ۥ9_xߩw$޻{,'K2 }['PK1ʼnV Cl``x#*%`)_ MXmDj}y]vi'N3_۪H(bU$+yn\-qthk eP=JU/S]A?2}#MM--0kkk؃P .l#ˇb4Ͷ8;ۙtN Ps2ؽ*io7Cz}rC)fe_0''+ԡG~Pϟ_~pתu(sDFjmf&.M=^DmdWSS}#ƆA{BB}Sb X雩^312{8Y,=ej$&11>6m Sc5UtcݾqK<&ΌW">5ucӖnmi>S5\S:Rhm$] 7>518352>U~|SgOٞCaGm#IÎYx csP4_U/[A55#o怚E/K.(b#,>XT0 !;\}v*\-Ms40wwuALf9G;[5%+15|{VnA7%cG-pm]sGaQsˑ˃Ԝ\ٳgZOmoN="@JqQBCUim-淾bLnnoC?sB:k#P/&H+8\8͛ORjSd3ŗO^>yUΖ/uVvr{|ų >\0>_yQ. Ȁ:ܝB&* øw1&`ˇ?+"sY̚ MgjeU ;5‰?xyj"(Ik^V1&Ԛo3,YLz?9ꛙ Ӌ hᷤ.~Xg?,GSb^޵MVmZ|T͙52-@^UI FQ&7_sݶJZKqͱW|m_X.mgf)G`) oh(z߰ |x_Q!f7_G D fC:K8Br1A";;Y=byiIhP.;ᖁVHP@aA"`bidΝi w%#dӺeĘ Nrl/+9x!iƤoޞP(3F nz=nj0T@Qkoe ֭&8mc(BB ݼqoG\p?7J/^[߳4444DХȥKqKK KdMZO^OYO]O[O_`T:Q3ɺ9>̚>q%i?6,>3CU:N"CDڑɓ@'U7A]R|@EAnd)Q pﷵ)(_ZZ|mzG{^m7n\DҰ+Ԫok5D "3\IQ&)ƒ3ŊQ|",}6ƚ>jgzЭ\v-\X^bY#!\<2T/*?Ӎlo q}jU nN6VG6W]!A) j)3+d DN|fqvTUoٰH9Q7%1D;jWg3r"UHɟg$)a KoUΚ7f^̎x؍Xv9xl _ZJ֖{N]( ?qy *lo꤫M]%"486*"7; yxjٕBmCMmFC%۷\o # _ G=:2<Ą9=/A?J֟j~/$M.v#;6_H,p=`KmKQw8촷Ldѽ|Z _OG,B(n),8(2,4-9Zw%>&ZO[S!dWgձWׯ33cc q_TyXx8b"b7g}]ksS+sS'{=c"⃨{33CJueM~CΞ9ˉZQVJ,t`ߺ032R221vs"枤-~J؟ҏK[ՏGmgOW G8 t-݌'hUC! kD0p{P~o Rb.2R&F0 q1{2M `0.*J7n"h071ҡimg݈{?j B?# xz=?u{c]]'.2}k*ټׯ>g$Z I ^şOj+ 3-SÃ!:Kx-hH{qħpkT~}\JEy!rԷ>.L-f cEtՖ}l.ǹ]SU@fif,#.e+8p@|lǚ  rWʹ-xȧx W{9Wz!JzZ~ ƻw|S-Ã!n{e.? vN$pp#>AO"㠳$p0,[zY$HzZ3-YKgϜ81<ؒK3%,%49(9(90)B?)T7)XD?D?lpp*B@}o`zګN"򇐠JĊr+K}9W]lɶXH(* (ʑPS$vT8DG.$?#B.ch &^D8zy2 p"XuqFZ~DYvK])Wߩ|?#j^H\=JL#K߻wm{x/MhjJϣ"*@~ґ@Z2"-.*/-@ĄTC ڌd/#!Q4C:*MߗPQ4ղ0迍u#lê8Z+ {&n992xWO,IzZb#goz됶 #PSV` nߺ wh[q IDATpc^FoOȠ(Aqbh tR aUuiooϝ±'v$'Z7/0]mvmL|la),2gUxTwuٽ4>9o_]UL졁{-/w1 3^_įCzjȍ3ӑ#i:67 d۴BRp< qɵm+ăJ5TibV}$9' H rg2cs& {2- ":4C=.MnjVj;w9d>ڜwd듇=/zqޝ#s%]]YUٕǫʳ>[K # ޾~9dk<ęK}-]G _P8$SpoG*ENIJSRQQSR(n\'RHQDfJLW&쿮bUGN~t|>Qr )Է MMؕ fIEi]&=MlК/IOu `QTka~BJLfn_` gę@nGSnd⌣?\O1 Ys}F0ErL_ޡ R'칚6v֘ F('/-@cw"F9ގT/-I8؛֯bhnj!{Rl?; zڲaL%6y)mTu4-Lh&vVrR~ dɶѬ:g ~Oz1Nܹu~u "qQ_nCA]I7Acy|MVy$PYQN1ą\ 8ؽhBP @(X9{Xrw HIܛQPS|V=~0aW_[=)͍ x{'_$2147v%.N. aTJt е ƆĺszZ4** @ " YI TDrR"0*؊3fFf&8 r4hwPTPQG ߯N??/< /   @`Fl@nA3~`]FFLPW1 -|wHOEp0qs0o!f:I(nݺa3@:>6&9)19))5%9%9"0B C@|$ݷw&DuwswdpE%!\P0'0anFT3w4!?F@m3Ձyـ@ AUoj< Ow?{bĦ=‚pɇRhP\*@̼5.8ط"suUıڛ hhkk+#Yw!I lmmsl 5Ӂ%VHzҜ S;?7O"BG=D$ ˄mx@ ^|?c, 0׾`~;~ ˜c_e)dbfig J Cc`tf__9!`vcڙ-ߔ|c>v.*)Jo,NƑ3meDyMypٻ77''o_n~޾L )T]qr B\HQ'B6¯@p4/``eehJ^b00w/; *P@KAUKT@f+glG&T>J9I=Ыxw!ˀ&ˀ#~mKj Ʃ/XG!Pc p6g3#````lj׺H 8JUi)I  ">[xw[ ^HI.Ss -!EEFG!.Q-L\mU@ ;ZHmsE˳KcKiˡz 23U7K~6U}S5N=Y+xAӀJːV&@^u5&nZo^xؚH|,zv36|0qH=;Lhߝ6XNKXNBv 1CfNE()>@*()o&jAF )&LQ*"N*<442, NTdڻkGKw6WnP6@MI,/kծO ?"le+l$b$f"e-gC_-F']7S'KwQ@YhEDMtmLm 2CF~Hz啇&vݝ{z3;jz?_yQ38=N|XtwW ~^"ӣs˃?q%H+KPB `ҼҒҊ2&%Ļ|HPC,RDbQ%jFcr w`DHs uw ToϝUUUUUp{v!@P8sRS`~dgev.$߄uLV?: #=6z6ԣ): 3@~ _N&;ۛ8ۙ8ۛzX6fLQSWVWw 2N(n=fq""*&>!!>6:䨥OΟ@3/0s=ZvBͩOSSԾyoߚ2:zv ;G7-+)ߗs66< GÃ-L xEX-iI9 @HHjkkkkMIJr-$(~p?b=~BΉAAn-q jY3m /tԕü^tUija㝩|K"{vz:xy7h[0ѓ$"5B5weE7ڻLgwffgvҝζL4Il0 改/s#@o!H$\67 vf{PdqvIIр{?~')R6'ImZm6CrSaGSw4cTߗw-/1[kWq~ߏ3%7./4=%,ÓɾdmakrL`9b&9I6mtMr5_f͓ZZn=\?93Fig rxQ^_wLğȠUp5V#Y(+;'mm]| pA?KV}cﭟ o;k@hң3 sdfdŢD'ij-\\FSx{>Rg'WgX/b$S,yݐ u<>9|f%G=\gFcBϊJN)S1,dCW[S`s<"Fl×%+R;Rm}+nU 7L8n7*$U\:2Np\Ϙπ ^}L.Vߟ-E4Y¸ /h_uibq0/?[7WNZFf&FMMRiL&hkU'|F.<44M]P`P ز!i߁7Λ҆ql7Á7._41rdn1nDKUGpz{y9"kc87]2,A[׹ŲM2t6v7,03_ [pŷYǶZf˰fK\-U jJ#!xZwg{ 7ꝝ{w@Ӫ>l$K7K9PǦ;o0H?p6ӅЂB&((ry PW(ڔJ &EE/"Wz}'yq/W :0F\mK)ÆmamyVÅo.n0P~\PTWd(lYSban}M6 ,ֵHз9皸zrJͼ}*/ -B"e2v2" ԵR *uX\L&?'>zvU bhoooOaa~^FZjkKk߳42.s},A AAC%% <^<Źvinp#Iߧ8"|cloUa|6u:9nP&=\}8w#ғÁ}fzTIA" ool:91WocoThRl^jQnv꒯QN Өi5dYG-dPu͙oJ+'$9!Sj?.u?ښ=믿&$:=A(4$O}|oɎtѣ#7`mWpViE s;tbn0p'YLm=(^/Z5ӑ[uǶGsguxg_91*^0n:Vz_Txho7nk ׾>Ă}}][YZ\XYK^;~K:3DOVMǟ+}+.~%,<}BEF%Υ&.enfU@Zeը@zoTF|":-/fB|\ӼߟDg#Aj$JOsX]<xGD 6$p澽\sbiS" "vpUFuҒ1Mt񓕁k7< לɉTߒ٤ߙ$'t7\kdr׿.'"T骝=b]==\ 2("YQV*=QF!6u Ǖ]Z_7zwo!!lOI DVi^!+8j-s_AF&8C08bSC`o!$ǝџ,:&0@_9=5<<48!rҒLe<|сͼ+JIxsΌ1طho{BT ʽ9NU=Օ%E]muE֮T>11"=sGqwmMShnM6B".<&y&"O~:|4أ@%B @_lۆ{?7FN9͙aVWiyũ2;8j݁-0J{D&'{xAxɤ$S ē7*2mq\-򂰐`~Ǫ5pwSy\5%_F_&L=e5uvEȭ1}Sn\tG{;Ͼ|z[ P#:Bw7Nϙq:'@ #?N7= $'*-j\Z4AX`$G[D/sbQ  Io uuvt6.Y@sU7qx̽]\_RT0%81i&Ci˨,/kE9*@^?լ`n3/RhWHc߆o^S>K؊~ok8 *D#=zD޷|FaTIDATWR7u׵Uț %7)QDP.736YV2wpb|anuE.}PN}ҌY?^B@%^95lp?>bƐ+ݙu`6Ql1ow~Lv 4 }áDE3y)Ye;x~^F[[=*-7/-H>څeƚǏ/4>H3dRf"fM  rOvw*ß<~ x߻tr&sHP|0*ٸ=귵4 G4ؑ:E2`/M/ fe֐f0*MM0`i8QQ)!$Bχ4DqTƋRc> ઁZ Z-5_qB ]?Ni8 |Z L)Z[ˬSSx@$z`H` SSwah|0aL)'S{}2`uikloN6a0YG /z7zIENDB`htp-1.19/homepage/ref/pic/poweredbyhtp.png0000664000175000017500000000244112525674213020743 0ustar hoenickehoenickePNG  IHDRXTPLTE+('0)!G1864*/EB?2`0uȇ1/t v l#Lyjt_/bsW~Sb*'!cmb|@oo`\Ewi`'w}:a, !mPֺ5jβ.T~&>GĬDC I 頖v6~oU~SL H^`f!sWp% Cp)? Pc򲋎})dl"Lh7m/9v9&yJYyLzKptblqi2O0pL U}3%M\w:,˯p,s57׃<(,CfozN!1WYH2LWi<[&=dL^ {q^/7rΑ g&_!#Na$wIܭ?"/  A (Q?R)) ds7l &Shܼ,Eǥ:*qwזO?\ bJxM<%Z?IZq,qnAуN]:G_׸?˱iϲ{ûzű)*^DjHYcҲ z(&vD~_jfs Tǂ &I^~_|(e&Q* "a1JiӺ6B4mZen( ZH=VQ8A&ZJ;h3޹z[Xa#Z[ZB>@*&r%dZA۵`t&rq|| 5B$m:XN$*+<ƝׯeY K,-!+ )EAedY&LPR⢩Q*wxp3@{P|! }$47QU;K{-}L':kZEVz"s&"ֳX7(!-A2@əIS0b,>F;6wf{߈ qZDQd ٝ2ʉ/8[гd]O/cs`]ۺx\j7ŎeHuWTO}ܸ*k{i_x! &g#xI5.Aj* 64Az>"B+nȞ #j \^@QBCX` bʂԚ|sh/ 6?N9Hhz3W\}[HUNZA"QRq:E'4Yv&tҧ^*KN:@$I QA<ZU`v] eR "8vM%4Y/8/`y[Zάo˫m>-pTIgδMcANzIENDB`htp-1.19/homepage/ref/pic/manbig.png0000664000175000017500000000070712525674213017467 0ustar hoenickehoenickePNG  IHDRabKGD pHYs  tIME  $ԅTIDATxһJAwl &v`%$W(Xy*E F4*D: BI֕쎍rبaȖZRzY<>Bݶw8;%iXsCޅ^(Xy$qtӤXIENDB`htp-1.19/homepage/ref/pic/source.png0000664000175000017500000000075412525674213017534 0ustar hoenickehoenickePNG  IHDR ͣ9bKGD pHYs ?@"tIME  YyIDATxJ+Aup!i., bI!wAMVC6D4"ugEM@3 ΁c8^ eVU0_P$cPVs\.f=Y0fvsp0^R( C* NvM,?a~?<8 k+_\˒v+Xg L"<˓sTaYE#ɰ0201ZCqV#V㬦w ٙ$U5vH($4IV+ڧg.&fঐIحocoQX1I c>i0`b1 yh8;~}RUUDIENDB`htp-1.19/homepage/ref/pic/arrow.png0000664000175000017500000000025312525674213017360 0ustar hoenickehoenickePNG  IHDR 2ϽbKGD pHYs  ~tIME ";>$,8IDATxc`qc*O hBw000pcu 1nīXE xݐFIENDB`htp-1.19/homepage/ref/pic/manual.png0000664000175000017500000000075312525674213017510 0ustar hoenickehoenickePNG  IHDR 2ϽbKGD pHYs  @AtIME &xxIDATx]]+dq^3d/4c34b $q|E.B+moVkP(˘30sq|.OV{mW? KtYe‘?g/*iɤUK*r0nWAd;U,jrSՑ-;]O.w~y !{u䬶.u7JrnIyR5=9ig17G~oDU54UȤV2P%_ -biPf3r6VrbfѶc3_ӑ|񤹋uʼn!Ι_.2oH|xc"rEwI%ohp \ {VIENDB`htp-1.19/homepage/ref/pic/download.png0000664000175000017500000000040612525674213020035 0ustar hoenickehoenickePNG  IHDRRPLTEܨ|XtRNS@fbKGDH pHYs  ~tIME -::dIDATxU D 80LcGpZ+Dm&?^̅ݥ\*S9 OC#,|c 6k* i[܆5y$IENDB`htp-1.19/homepage/ref/options.htp0000664000175000017500000000603412525674213017160 0ustar hoenickehoenicke All htp options can be specified on the command-line; many can be set in the actual source files. Options set inside source files override command-line options.

    These options can be used on the command-line by preceding their name with a ‘-’ character. Inside source files, the OPT tag is used.

    Options include:

    • IMGXY: Width & height will be added to all image tags. This is the default setting.
    • NOIMGXY: Width & height will not be added to image tags (but not removed if already found).
    • QUIET: Pre-processor only displays warnings and error messages.
    • VERBOSE: Pre-processor displays all informational, warnings, and error messages. This is the default setting.
    • DEPEND: Check target file's dependencies before processing. If the input file, or any of the file it may INCLUDE have changed, it will continue and build the output file. Otherwise, a simple informational message will be printed and no action will occur. This is the default setting.
    • NODEPEND: Dependency checking will not occur during processing.
    • PRECIOUS: Normally, if htp cannot finish processing a file, it will delete the incomplete output file to prevent using it accidentally. However, if this is not desirable, the PRECIOUS option will turn off this behavior.
    • CONDENSE: All HTML will be condensed, which is merely stripping it of all linefeeds. HTML does not require any carriage returns or linefeeds, so the format of the output will not be changed. However, file sizes will be somewhat smaller, and should load a little faster, especially over a slow link.
    • SEMICONDENSE: This option will strip empty lines from the produced HTML file. Normally this makes the output more readable than when using CONDENSE or NOCONDENSE. This is the default setting.
    • NOCONDENSE: This disables condensing the output.
    • DELIM: This can be set to either HTML, CURLY or SQUARE. Each setting determines how htp markups should be surrounded in the text. HTML indicates using arrow brackets (‘<’ and ‘>’) just like standard HTML tags. CURLY means tags should be surrounded by curly braces (‘{’ and ‘}’). SQUARE uses square brackets (‘[’ and ‘]’) to surround htp tags. Note that this only applies to the special htp tags and not to the standard HTML tags, including IMG (which htp can process.) The default setting is HTML.
    • XML: This options tells htp to produce a XML-style generator tag. Since HTML forbids the generator tag to end with /> but XHTML and XML require it, this flag indicates what to use.
    htp-1.19/homepage/ref/htp.htt0000664000175000017500000001011112525674213016253 0ustar hoenickehoenicke htp on-line referencehtp - a HTML pre-processor : <USE title>
    HTP

    syntax

    synopsis

      page source
      htp project
      htp homepage
      download
      htp on-line reference
    hosted by
    SourceForge.net
    HTML coding Powered by htp
    htp on-line reference /
    htp homepage /
    Authors: Jim Nelson, , .
    Maintainers: Robert King / , .

    Copyright © 1995–96 Jim Nelson.
    Copyright © 2000 Robert King.
    Copyright © 2001–2014 .
    Permission to reproduce and distribute this hypertext document granted according to terms described in the License section.

    last updated

    htp-1.19/homepage/ref/license.htp0000664000175000017500000000070612525674213017107 0ustar hoenickehoenicke

    Clarified Artistic License

    htp is released under the clarified artistic license. The license change took place when we took over maintanance of htp and started the sourceforge project.

    If you actively use htp and find it useful and worthwhile, I would appreciate placing a hyperlink on one of your pages pointing to the htp home page.

    
    
    htp-1.19/homepage/ref/default.htp0000664000175000017500000000611512525674213017111 0ustar hoenickehoenicke

    Using default files

    Often you want to use the same templates, the same options, and the same macros in all htp files in a certain project. To support this htp parses a default file that can contain the necessary template, macro definitions. It can also include other htp files.

    At program start, htp will look for an environment variable called HTPDEF. This variable can be set to a specific file. htp will load in this file and process it like any other, except that htp will not generate any output from it. In other words, it will only cull macros, options, and other settings. Plain text and other HTML markups will be ignored and shouldn't be present in this file.

    htp will then search the current directory for a file named "htp.def". This file, called the project default file, is also processed like the HTPDEF file.

    The file "htp.def" should contain all macros, metatags (see next section), options and templates common to all files in the directory. That is, if you organize your HTML file groups in separate directories, each directory has it's own project default file with settings and macros particular to that project.

    The use of a global HTPDEF file instead of project default files makes it difficult to share projects with other people, as they would need the same global configuration. Using it is therefore deprecated by now.

    Organizing your files

    htp has been designed to break apart two components required to HTML files: design and content. This is good as it allows you to change your design without having to touch the content and to add new content without having to think about the design.

    The design of your pages is best kept in a template file as seen in the last section. As mentioned earlier this reference manual is also created from a template file.

    Page content should be held in separate files, each using file include or template to point to a template file. By using global and project default files and keeping logical groupings of subject matter in separate directories, this dissection of design and content becomes quite natural.

    Although htp does not enforce any file naming conventions, I've adopted the following file extensions for my own sanity:

    .htp:
    Content file defining macros containing the textual content. The macros are expanded by the template file.
    .htt:
    Template file describing page layout.
    .def:
    Include file holding common macros and setting options.
    .hti:
    Include file holding common content (when included from htp files) or common layout parts (when included from templates).

    So much about files. In the next section you can learn how to customize htp to your own needs by defining your own tags.

    htp-1.19/homepage/ref/quote.htp0000664000175000017500000000060612525674213016621 0ustar hoenickehoenicke QUOTE is used to quote a macro that would otherwise be interpreted by HTP. It may be useful in conjunction with a surrounding EXPANDed block to prevent early expansion of some contained blocks. Note that '$' evaluation is still done inside a quote block. htp-1.19/homepage/ref/use.htp0000664000175000017500000000634412525674213016265 0ustar hoenickehoenicke <... $macroname ...> <... ${macroname} ...> USE will expand macros that have been previously declared with either SET or BLOCK. USE can only be used outside of other markup tags.

    If you USE a block macro the value of expanded block macros will be further parsed by htp. This is maybe not what you want, for example, if the use is inside a block which expands itself. You can use the noexpand attribute to prevent further expansion.

    USE will accept additional parameters, which are "local" macros for the expanded macro. This is only valid for BLOCK macros. Macros created using SET cannot have parameters passed. For example:

    send email This works: But this fails: And this fails:

    (See below for a description of the '$' operator.) The example on line 7 works because "stuff" has been declared as a block macro, and the tag is passing the "email" macro to the "stuff" macro. Line 8 fails because the "email" macro is unavailable once the block macro is completely expanded, and cannot be passed to a SET macro.

    Note that the "email" macro is available to other macros or included files called within the "stuff" block.

    Inside a markup tag, like IMG, A (anchor), or any other standard HTML or htp tag, the '$' operator must be used. The '$' should be immediately followed by the macro name, which may or may not be surrounded by curly braces. When htp encounters this it replaces the macro name by the contents of the macro without further processing the contents. mailto hyperlink another hyperlink

    The use of curly braces is encouraged, since it is more robust and should never cause confusion with surrounding text. If no curly braces are used the macro name consists either of a single punctuation character or the maximum sequence of letters, digits, "-" and "_" that follows it.

    If a '$' character needs to be kept in the final output, and not interpreted as a macro name, it must be escaped by another '$' character. This is especially true for PHP code.

    If the '$' macro is the only text in the attribute's value, htp will automatically surround it with quotation marks to prevent spaces from delimiting the text as if it were additional markup attributes. If the '$' macro is surrounded by other text (as in the two examples above), quotation marks are not automatically supplied.

    Note that a '$' macro can be placed anywhere in a markup tag and can be nested. This is valid: <${tagName} ${attrName}=${value$ctr}>

    The tagName macro can contain any tag name, even a self-defined metatag. Note that $ctr is expanded before the valueX macro is expanded, so assuming that ctr was set to 1 it will expand value1. htp-1.19/homepage/ref/while.htp0000664000175000017500000000165212525674213016576 0ustar hoenickehoenicke block WHILE is the building block for repeated processing. The basic form is shown above.

    "Conditional" is either a "compare" or "is defined" operation. A compare operator is a test of the value of a macro against a literal string. If the NOT tag is present in the WHILE markup, the evaluation of the conditional is reversed: ...

    Just as with IF you can also check for a macro's existance: ...

    If the condition is true, the block is evaluated and afterwards the WHILE tag is evaluated again. If the '$'-operator is used in the WHILE tag it is also reevaluated on each iteration.

    A loop block must be closed with the /WHILE tag. htp-1.19/homepage/ref/metatag.htp0000664000175000017500000001354712525674213017116 0ustar hoenickehoenicke

    Programming your own tags

    Metatags allow for defining your own HTML-like tags. When you define a metatag you have to provide the HTML code which it abbreviates. In fact metatags are just like block macros, but they have a nicer syntax. With metatags you can expand htp's functionality.

    Metatags are defined with the def and blockdef tags and undefined with the undef tag.

    As an example we show how to define a tag that builds a fancy horizontal rule out of several images.

     
    paragraph paragraph

    In line 1 of the above example a new tag named imghr is defined. The html code which implements this rule is following in lines 2-8. between the def and /def tags. You don't have to understand this html code, but you should understand that this is just pure html to draw the fancy rule. Every time you write <imghr> as in line 12 htp will replace this tag with the corresponding html code. To make metatags available to all htp documents in your project, place them in a common include file.

    Often you want to define tags that have an opening and a closing variant. For this purpose you should use the blockdef tag. When htp encounters a blockdef tag it will automatically search for the matching closing tag and put everything between these tags in a block macro named block. Here is an example for this.

    This is bold and italic

    Using parameters

    More sophisticated tags accept parameters. The option parameter lets multiple metatag parameters be named and expanded inside the def or blockdef block:

    ${alt};

    Saving blocks for later

    When you are using templates, the html should only be written by the template file. The normal htp files should just define macros that are used later in the template. So you may want to write block tags that just save the block in a macro for later use. Although this is possible with htp it is quite tricky, so here we present the way to do this:

    This defines a block macro named section. This macro uses a counter sect-ctr that enumerates the sections. It is increased for every section (line 3) and then the block macro name is build from this counter. So the first section is stored in block sect-1, the second in sect-2 and so on. The global flag in line 4 tells htp that these macros should be defined globally for the remaining run. Otherwise they would be forgotten at the end of the section macro.

    The tricky part is the expand and noexpand flags in line 4 and 5. Normally when you define a block macro the code between the start and end tag is literally copied into the macro value. The expansion takes place when the macro is used. In this case that doesn't make sense; all macros sect-1, sect-2 and so on would just contain the same value, namely <use block> and block wouldn't be defined anymore when the macros are finally expanded. Therefore we use expand to expand the use tag already when sect-1 is defined.

    The noexpand attribute of the use tag is just the opposite and prevents the contents of block to be expanded twice. If you omit it, it would be expanded when defining the sect-1 macro and when using it later in the template. Generally it is a good idea to use noexpand whenever you use expand in a block around it.

    To close this example we show how to expand the sect-${sect-ctr} blocks in the template:

    The while tag in line 3 checks whether the macro sect-${sect-ctr} is defined. If it is defined the body is evaluated, which expands the macro and increases sect-ctr. Afterwards the while condition is checked again to check for sect-2 macro. This repeats until sect-${sect-ctr} is not defined.

    Conclusions

    This closes our short htp tutorial. I hope you did enjoy it and see the advantages of using htp for your own projects. Please give us some feedback about this tutorial. What can be improved?

    There is more documentation in this manual, see the Usage chapter or browse the documentations for the htp tags. If you're looking for examples, in case you haven't already noticed yourself, there is a link to the source code on the left, where you can get the source code for every page on this site.

    htp-1.19/homepage/ref/index.htp0000664000175000017500000000011612525674213016567 0ustar hoenickehoenicke

    Table Of Contents

    htp-1.19/homepage/ref/wishlist.htp0000664000175000017500000000243712525674213017336 0ustar hoenickehoenicke
    • Add more powerful conditions for if and while macro. The main problem is the syntax. I think of something like
      <if test="${i} lt 5 or ${i} lt ${max}">.
    • Add regular expressions, to make htp more powerful.
    • An <OUTPUT EXECUTE="..." REDIRECT> tag would be nice that filters a block through an external program and inserts the result. This would be useful in the online documentation to produce the pretty HTML code. The problem is that it needs to handle concurrency correctly: for large blocks it is not good to just write the input and afterwards read the output as this may deadlock (htp and the other process are both waiting for their output to be consumed).
    • Add a section to this manual containing useful code snippets.
    • The ability to define macros on the command-line or in response files.
    • It would be nice to have a fully functional dependency mechanism. When the html file is produced, htp could also output the names of all read files to an extra file. On the next run this file could be read to quickly determine the dependencies.

      One could also handle file execute tags by allowing the user to give the dependencies in an attribute.

    htp-1.19/homepage/ref/alttext.htp0000664000175000017500000000261212525674213017150 0ustar hoenickehoenicke ALTTEXT declares an ALT attribute for any IMG tag with a SRC matching the ALTTEXT NAME. Since relative paths can be used to point to the same image, only the filename is considered in all comparisons.

    When an IMG tag with a matching source is encountered, htp will add an ALT attribute only if one is not already present. This allows for ALT text to be overridden on specific images and default text on all others.

    For example: this line: becomes this after processing: Company logo this line: will also have an ALT attribute appended to it this line: Click here for more information! remains unchanged.

    An ALTTEXT tag with a name but no text attribute removes any ALT mapping for this image. Successing IMG tags with a matching SRC name are not changed.

    Since this is useful for an image used throughout a set of documents, ALTTEXT is most appropriate in an include file or a default file.

    In addition to ALTTEXT, htp can also automatically add WIDTH and HEIGHT attributes to IMG tags. htp-1.19/homepage/ref/blockdef.htp0000664000175000017500000000206312525674213017234 0ustar hoenickehoenicke ... ... BLOCKDEF creates block metatags, which is a fancy way of saying it creates new block tags. A block tag is a tag that takes a whole block as additional parameter. This block is surrounded by <tagname> and </tagname>. The contents of this block are automatically stored in the block macro named BLOCK.

    For example:

    This is a fancy section.

    All block metatags have the implicit option EXPAND, which tells htp to expand the contents of the block before the definition is expanded.

    A more thorough discussion and more elaborate examples are discussed in the metatag section.

    htp-1.19/homepage/ref/macros.def0000664000175000017500000000730612525674213016717 0ustar hoenickehoenicke [ref]
    >     >   htp-1.19/homepage/ref/def.htp0000664000175000017500000000702112525674213016220 0ustar hoenickehoenicke

    DEF creates metatags, which is a fancy way of saying it creates new tags. The mechanism is very similar to BLOCK macros, except that the USE tag is not used to expand them. Instead, they are expanded by their own name. For example:

    This text is centered.

    Some metatags will require an opening and closing tag (comparable to and ). In this case, you should use the BLOCKDEF macro. Another slightly faster alternative is to use two metatags, the opening tag and the closing tag with a preceding slash. For example:

    Some large text

    You should really use BLOCKDEF, though, as it will check for matching end tag. It is not that slower.

    Options can be passed to a metatag, which can then expand as if it were a SET macro. Option names are parameterized with the OPTION attribute. Multiple options can be listed by separating their name with a space (which therefore requires they be surrounded by quotes.)

    This will fail: Instead, use * like this:

    htp will do very specific checking of parameters when a metatag is invoked. htp assumes that all parameter options to the metatag are optional. This is why the HEADERIMG definition uses IF to verify the SIZE option is defined before expanding it in the block. If a parameter is required, simply expand it without first checking. When htp expands the metatag and the macro is not defined, it will halt processing and complain with an error message and the required macro name. Normally htp will not allow parameters not listed in the OPTION attribute to be added to the tag. This is why the third invocation of HEADERIMG will fail. There is no ALT parameter specified in the OPTION attribute. However, there is the special option *, which matches every other parameter. It should be used to pass all other options to another tag.

    Metatags can be removed by using the UNDEF tag. Note that both open and close tags must be removed with UNDEF. Removing one will not remove both.

    Warning: Although possible, def should not be used to override standard HTML and htp tag names, as this can cause much confusion and unexpected results. The def tag can even be used to override its own tag name. Because of the problems this can cause, its highly recommended to not override known tag names.

    You can find some other examples in the metatag section of the tutorial.

    htp-1.19/homepage/ref/undef.htp0000664000175000017500000000071412525674213016565 0ustar hoenickehoenicke

    UNDEF removes a metatag definition. Metatags created by DEF and BLOCKDEF can be removed with the UNDEF command. Once removed, the metatag will no longer be recognized by htp until it is reassigned.

    Multiple metatags can be removed by placing each name as an attribute.

    htp-1.19/homepage/index.htp0000664000175000017500000000272112525674213016017 0ustar hoenickehoenicke

    Htp was intended as a HTML pre-processor. It is able to preprocess HTML, XHTML, XML and CSS files (htp could process any text based files). Its purpose is to assist you to maintain a consistent "look" over an entire set of web pages. This is done by allowing you to define your own tags as abbreviations for sets of standard HTML tags.

    This site provides an on-line version of the reference manual, together with the option to download the program. In addition it includes the htp SourceForge project link and information about the original author and previous maintainers.

    How to get htp release

    Now htp is a SourceForge project. See the history for more information about new features. You can download it from the sourceforge file server.

    The htp reference manual is available online. The entire htp source used to produce the reference manual is also present in the source distribution and provides a good series of examples. You can also download a the prebuild manual from the sourceforge file server.

    Authors and Maintainers

    htp was originally written by Jim Nelson. It was extended and is currently maintained by .

    htp-1.19/Makefile0000664000175000017500000000311412543300625014034 0ustar hoenickehoenicke# # makefile - htp # # HTML pre-processor # Copyright (c) 2002 Jochen Hoenicke # include Makefile.config d:=. DISTDIRS := DISTFILES := Makefile Makefile.config CLARIFIED_ARTISTIC INSTALL CLEAN := *~ SCRUB := $(MAIN)-*.zip $(MAIN)-*.tar.gz HTML := # sub directories dir:=src include $(dir)/Makefile.sub dir:=tests include $(dir)/Makefile.sub dir:=homepage include $(dir)/Makefile.sub dir:=examples include $(dir)/Makefile.sub all: .PHONY: all install dist scrub clean force scrub:: clean rm -f $(SCRUB) clean:: rm -rf $(RELDIR) rm -f $(CLEAN) dist: rm -rf $(RELDIR) for i in $(DISTDIRS); do mkdir -p $(RELDIR)/$$i; done for i in $(DISTFILES); do cp -p $$i $(RELDIR)/$$i; done release: all release-src release-doc release-bin ls -l $(MAIN)-$(VERSION)* @test "$(RELEASE)" = 1 || \ echo "****** ADD RELEASE=1 TO Makefile.config *******" release-src: dist tar -czf $(MAIN)-$(VERSION).tar.gz $(RELDIR) rm -rf $(RELDIR) @test "$(RELEASE)" = 1 || \ echo "****** ADD RELEASE=1 TO Makefile.config *******" release-doc: $(HTP) rm -rf $(RELDIR) $(MAKE) install-doc pkgdocdir=`pwd`/$(RELDIR) zip -r $(MAIN)-$(VERSION)-doc.zip $(RELDIR) rm -rf $(RELDIR) release-bin: $(HTP) $(STRIP) $(HTP) zip -j $(MAIN)-$(VERSION)-$(OS).zip $(HTP) CLARIFIED_ARTISTIC $(HTML): %.html: %.htp $(HTP) cd $(dir $<); $(PWD)/$(HTP) -quiet -nodepend $(notdir $<) $(notdir $@) vars: @echo HTML=$(HTML) @echo HTMLhomepage=$(HTMLhomepage) @echo HTMLhomepage/ref=$(HTMLhomepage/ref) @echo HTMLtests=$(HTMLtests) @echo HTMLexamples=$(HTMLexamples) @echo SRC=$(SRC) @echo HTP=$(HTP) htp-1.19/src/0000775000175000017500000000000012543301704013163 5ustar hoenickehoenickehtp-1.19/src/htp-files.c0000664000175000017500000003473012543265561015243 0ustar hoenickehoenicke/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* // // htp-files.c // // htp specific file access // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #include "defs.h" #include "option.h" #include "streams.h" #include "bool-proc.h" #include "snprintf.h" /* // returns the full, qualified pathname of the default htp include file // // Returns FALSE if unable to find the file. */ BOOL HtpDefaultFilename(char *filename, uint size) { char *defFile; /* get the name of the default file from the HTPDEF environement */ /* variable */ if((defFile = getenv("HTPDEF")) == NULL) { return FALSE; } /* verify that the file exists */ if(FileExists(defFile) == FALSE) { return FALSE; } /* copy the filename into the buffer and skeedaddle */ StringCopy(filename, defFile, size); return TRUE; } /* // compare files modified time/date stamp, as a dependency check ... returns // TRUE if the dependency does not require an update, FALSE otherwise (which // could either be a timestamp discrepency, or simply that the resulting file // does not exist) ... if dependency checking is turned off, this function // will always return FALSE. // // Returns ERROR if dependency file does not exist. */ BOOL IsTargetUpdated(const char *dependency, const char *target) { struct stat dependStat; struct stat targetStat; char *dependName; char *targetName; assert(dependency != NULL); assert(target != NULL); /* always update targets? */ if(DEPEND == FALSE) { return FALSE; } /* convert the dependency and target filenames for this filesystem */ if((dependName = ConvertDirDelimiter(dependency)) == NULL) { return ERROR; } if((targetName = ConvertDirDelimiter(target)) == NULL) { FreeMemory(dependName); return ERROR; } /* get information on the dependency file */ if(stat(dependName, &dependStat) != 0) { /* dependency file needs to exist */ FreeMemory(dependName); FreeMemory(targetName); return ERROR; } /* get information on the target file */ if(stat(targetName, &targetStat) != 0) { /* target file does not exist, dependency needs to be updated */ FreeMemory(dependName); FreeMemory(targetName); return FALSE; } FreeMemory(dependName); FreeMemory(targetName); /* compare modification times to determine if up-to-date */ return (dependStat.st_mtime <= targetStat.st_mtime) ? TRUE : FALSE; } /* // searches for the specified file in the search path ... this function is // very stupid, it simply gets the first directory in the search string, // appends the file directly to the end, and tests for existance. Repeat. */ BOOL SearchForFile(const char *filename, char *fullPathname, uint size) { char *searchPathCopy; char *ptr; char *convertedName; FIND_TOKEN findToken; /* quick check for search path even being defined */ if(searchPath[0] == NUL) { return FALSE; } /* need to make a copy of the search path for String...Token() to butcher up */ if((searchPathCopy = DuplicateString(searchPath)) == NULL) { printf("%s: unable to allocate temporary buffer for include path (out of memory?)\n", PROGRAM_NAME); return FALSE; } /* look for ';' delimiter */ ptr = StringFirstToken(&findToken, searchPathCopy, ";"); while(ptr != NULL) { StringCopy(fullPathname, ptr, size); /* if the last character is not a directory delimiter, add it */ if(strchr(ALL_FILESYSTEM_DELIMITERS, fullPathname[strlen(fullPathname) - 1]) == NULL) { strncat(fullPathname, DIR_DELIMITER_STRING, size); } /* append the file name */ strncat(fullPathname, filename, size); /* need to do a complete conversion of delimiters in the filename, but */ /* ConvertDirDelimiter() returns a AllocMemory()'d copy of the string ... */ convertedName = ConvertDirDelimiter(fullPathname); /* check for existance */ if(FileExists(convertedName) == TRUE) { /* clean up and get outta here */ StringCopy(fullPathname, convertedName, size); FreeMemory(searchPathCopy); FreeMemory(convertedName); return TRUE; } FreeMemory(convertedName); convertedName = NULL; ptr = StringNextToken(&findToken); } /* clean up */ FreeMemory(searchPathCopy); return FALSE; } static char *markupBuffer = NULL; static uint markupSize = 0; static void FreeMarkupBuffer(void) { FreeMemory(markupBuffer); markupBuffer = NULL; } /* // TRUE = plaintext is filled with new plain text markup, FALSE if end of file, // ERROR if a problem // !! Don't like using ERROR in any BOOL return values */ BOOL ReadHtmlMarkup(STREAM *infile, STREAM *outfile, uint *markupType, HTML_MARKUP *htmlMarkup) { char ch; uint ctr; char inQuotes; uint startLine; uint numread; char open_markup[3]; char tag_specials[3]; open_markup[0] = HTML_OPEN_MARKUP; open_markup[1] = htpOpenMarkup; open_markup[2] = htpOpenMarkup; tag_specials[1] = '\"'; tag_specials[2] = '\''; #if 0 memset(open_markup, 0, sizeof(open_markup)); BITMAP_SET(open_markup, HTML_OPEN_MARKUP); BITMAP_SET(open_markup, htpOpenMarkup); memset(tag_specials, 0, sizeof(tag_specials)); BITMAP_SET(tag_specials, HTML_CLOSE_MARKUP); BITMAP_SET(tag_specials, htpCloseMarkup); BITMAP_SET(tag_specials, '\"'); BITMAP_SET(tag_specials, '\''); #endif assert(infile != NULL); /* if outfile is NULL, then the input stream is just being walked and */ /* not parsed for output ... i.e., don't assert outfile != NULL */ /* allocate some space for markup plaintext ... this will dynamically */ /* expand if necessary, and has to be freed by the caller */ if(markupBuffer == NULL) { if ((markupBuffer = AllocMemory(MIN_PLAINTEXT_SIZE)) == NULL) { HtpMsg(MSG_ERROR, NULL, "unable to allocate memory to read HTML file"); return ERROR; } /* track the markupBuffer size */ markupSize = MIN_PLAINTEXT_SIZE; atexit(FreeMarkupBuffer); } for (;;) { numread = GetStreamBlock(infile, markupBuffer, markupSize, open_markup); if (numread == 0) { /*EOF*/ /* no markup found, end of file */ return FALSE; } if (IS_OPEN_MARKUP(markupBuffer[numread-1])) { /* get the type of markup for caller */ *markupType = MarkupType(markupBuffer[numread-1]); if (numread > 1 && outfile != NULL) { /* there is normal text, just copy it to the output file */ markupBuffer[numread-1] = NUL; StreamPrintF(outfile, "%s", markupBuffer); } break; } /* no open markup found in 2KB. Print the full block and * continue. */ if (outfile != NULL) StreamPrintF(outfile, "%s", markupBuffer); } /* copy the markup into the markupBuffer */ ctr = 0; inQuotes = NUL; startLine = infile->lineNumber; tag_specials[0] = MARKUP_CLOSE_DELIM(*markupType); for(;;) { numread = GetStreamBlock(infile, markupBuffer + ctr, markupSize - ctr, tag_specials); if (numread == 0) { /* EOF ... this is not acceptable before the markup is */ /* terminated */ infile->lineNumber = startLine; HtpMsg(MSG_ERROR, infile, "markup tag is never closed", startLine); return ERROR; } ctr += numread; ch = markupBuffer[ctr - 1]; if ((IS_CLOSE_MARKUP(ch)) && (MarkupType(ch) == *markupType)) { /* Check whether this end tag closes the tag. We need * special checks for PHP-tags and comment tags */ if (strncmp(markupBuffer, "!--", 3) == 0 /* comment tag: check for -- */ ? strncmp(markupBuffer+ctr-3, "--", 2) == 0 /* PHP tag: check for ? */ : markupBuffer[0] == '?' ? markupBuffer[ctr-2] == '?' /* normal tag: check for matching quotes */ : inQuotes == NUL) { /* end of markup, terminate string and exit */ markupBuffer[ctr - 1] = NUL; break; } } /* track quotation marks ... can only close markup when */ /* all quotes have been closed */ if(inQuotes) { if (ch == inQuotes) inQuotes = NUL; } else if (ch == '\'' || ch == '\"') { inQuotes = ch; } /* check for overflow ... resize markupBuffer if necessary */ if(ctr >= markupSize - 1) { char *newmarkupBuffer = ResizeMemory(markupBuffer, markupSize + PLAINTEXT_GROW_SIZE); if(newmarkupBuffer == NULL) { /* unable to enlarge markupBuffer area */ HtpMsg(MSG_ERROR, NULL, "unable to reallocate memory for reading HTML file"); return ERROR; } markupBuffer = newmarkupBuffer; markupSize += PLAINTEXT_GROW_SIZE; } } if(PlaintextToMarkup(markupBuffer, htmlMarkup) == FALSE) { HtpMsg(MSG_ERROR, infile, "could not parse markup tag (out of memory?)"); return ERROR; } return TRUE; } BOOL FullyCheckDependencies(const char *in, const char *out) { BOOL result; STREAM infile; char title[MAX_PATHNAME_LEN]; HTML_MARKUP markup; const char *includeFile; const char *imageFile; BOOL readResult; BOOL checkResult; uint markupType; assert(in != NULL); assert(out != NULL); if(DEPEND == FALSE) { /* outta here */ return FALSE; } /* check if target file is completely up to date compared to input file */ result = IsTargetUpdated(in, out); if(result == ERROR) { printf("%s: unable to get file information for file \"%s\"\n", PROGRAM_NAME, in); return ERROR; } else if(result == FALSE) { /* target is not updated */ return FALSE; } /* because target is up to date, need to search dependency file for */ /* FILE INCLUDE tags and check those files likewise */ /* open file */ snprintf(title, sizeof(title), "Dependency check for %s", in); if (CreateFileReader(&infile, in) == FALSE) { printf("%s: unable to open file \"%s\" for reading while checking dependencies\n", PROGRAM_NAME, in); return ERROR; } infile.name = title; /* assume everything is hunky-dory unless otherwise discovered */ checkResult = TRUE; /* get the next markup tag from the input file */ while((readResult = ReadHtmlMarkup(&infile, NULL, &markupType, &markup)) != FALSE) { if(readResult == ERROR) { /* error occurred processing the HTML file */ checkResult = ERROR; break; } /* check markup type ... only interested in htp markups currently */ if((markupType & MARKUP_TYPE_HTP) == 0) { DestroyMarkupStruct(&markup); continue; } /* if FILE INCLUDE markup, get the filename specified */ includeFile = NULL; imageFile = NULL; if(IsMarkupTag(&markup, "FILE")) { if(MarkupAttributeValue(&markup, "EXECUTE") != NULL) { /* If we find an execute tag, we can't be sure that it * is up to date */ result = FALSE; DestroyMarkupStruct(&markup); break; } includeFile = MarkupAttributeValue(&markup, "INCLUDE"); if (includeFile == NULL) { includeFile = MarkupAttributeValue(&markup, "TEMPLATE"); } } else if(IsMarkupTag(&markup, "IMG")) { imageFile = MarkupAttributeValue(&markup, "SRC"); } else if(IsMarkupTag(&markup, "OPT")) { if(UnlinkBoolAttributeInMarkup(&markup, "NODEPEND")) { /* !! dependency checking disabled in source file ... since this */ /* can swing back and forth throughout the files, and its just */ /* a pain to track what is technically the last one set, */ /* if one is found, dependency checking is disabled and the */ /* targets are not considered updated */ /* this could be fixed with some work */ checkResult = FALSE; DestroyMarkupStruct(&markup); break; } } /* by default assume everything is up to date unless more information */ /* is available through other files */ result = TRUE; /* check include or image file timestamps */ if(includeFile != NULL) { /* !! the accursed recursion strikes again */ /* check the dependencies based on this new file */ result = FullyCheckDependencies(includeFile, out); } else if(imageFile != NULL) { /* check the image files timestamp as part of dependency checking */ if(FileExists(imageFile)) { result = IsTargetUpdated(imageFile, out); } } /* unneeded now */ DestroyMarkupStruct(&markup); if(result != TRUE) { /* if FALSE, not up to date, no need to go further */ /* if ERROR, need to stop and report to caller */ checkResult = result; break; } /* otherwise, TRUE indicates that everything is okay, */ /* so keep searching */ } /* EOF encountered in the HTML input file ... target is updated */ CloseStream(&infile); return checkResult; } htp-1.19/src/jpeg.c0000664000175000017500000001435112525674213014270 0ustar hoenickehoenicke/* // // jpeg.c // // JPEG FIF (File Interchange Format) support functions // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #include "htp.h" /* // a great deal of this code was ripped off wholesale from the Independent // JPEG Group's sample source code, obtainable from any SimTel mirror under // msdos/graphics/jpegsrc6.zip */ /* // JPEG markers */ #define M_SOF0 0xC0 /* Start Of Frame N */ #define M_SOF1 0xC1 /* N indicates which compression process */ #define M_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use */ #define M_SOF3 0xC3 #define M_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers */ #define M_SOF6 0xC6 #define M_SOF7 0xC7 #define M_SOF9 0xC9 #define M_SOF10 0xCA #define M_SOF11 0xCB #define M_SOF13 0xCD #define M_SOF14 0xCE #define M_SOF15 0xCF #define M_SOI 0xD8 /* Start Of Image (beginning of datastream) */ #define M_EOI 0xD9 /* End Of Image (end of datastream) */ #define M_SOS 0xDA /* Start Of Scan (begins compressed data) */ #define M_APP0 0xE0 #define M_COM 0xFE /* COMment */ BOOL JpegReadByte(FILE *file, BYTE *b) { int i; if((i = fgetc(file)) == EOF) return FALSE; *b = (BYTE) i; return TRUE; } BOOL JpegFirstMarker(FILE *file) { BYTE flag; BYTE marker; /* move to the beginning of the file */ if(fseek(file, 0, SEEK_SET) != 0) { HtpMsg(MSG_WARNING, NULL, "unable to seek to start of JFIF file"); return FALSE; } /* look for the start of image marker */ if(JpegReadByte(file, &flag) == FALSE) { return FALSE; } if(JpegReadByte(file, &marker) == FALSE) { return FALSE; } /* start of image? */ if((flag != 0xFF) || (marker != M_SOI)) { return FALSE; } return TRUE; } BOOL JpegNextMarker(FILE *file, BYTE *marker, WORD *size) { BYTE flag; BYTE buff[2]; int bytesread = 0; /* move file pointer to next 0xFF flag */ do { if (JpegReadByte(file, &flag) == FALSE) return FALSE; bytesread++; } while (flag != 0xFF); /* extra 0xFF flags are legal as padding, so move past them */ while (flag == 0xFF) { if (JpegReadByte(file, &flag) == FALSE) return FALSE; bytesread++; } *marker = flag; if (bytesread > 2) { HtpMsg(MSG_WARNING, NULL, "Skipped %d bytes of garbage in JFIF file", bytesread - 2); } if(fread(buff, 1, 2, file) != 2) { return FALSE; } *size = MAKE_WORD(buff[0], buff[1]); /* exit condition really depends if a good marker was found */ return TRUE; } BOOL JpegFormatFound(FILE *file) { BYTE marker; WORD size; char signature[8]; if(JpegFirstMarker(file) == FALSE) { return FALSE; } while(JpegNextMarker(file, &marker, &size) == TRUE) { /* should see an APP0 marker */ if(marker == M_APP0) { /* file format is now pointing to JFIF header */ /* look for the signature */ if(fread(signature, 1, 5, file) != 5) { HtpMsg(MSG_WARNING, NULL, "unable to read JFIF signature from file"); return FALSE; } /* it all comes down to the signature being present */ return (strcmp(signature, "JFIF") == 0) ? TRUE : FALSE; } else if(marker == 0xe1) { /* file format is now pointing to JFIF header */ /* look for the signature */ if(fread(signature, 1, 5, file) != 5) { HtpMsg(MSG_WARNING, NULL, "unable to read JFIF signature from file"); return FALSE; } /* it all comes down to the signature being present */ return (strcmp(signature, "Exif") == 0) ? TRUE : FALSE; } else { if (fseek (file, size-2, SEEK_CUR) != 0) { HtpMsg(MSG_WARNING, NULL, "unable to seek past JFIF block"); return FALSE; } } } return FALSE; } BOOL JpegReadDimensions(FILE *file, DWORD *height, DWORD *width) { BYTE marker, buff[5]; WORD size; /* make sure we can find the first marker */ if(JpegFirstMarker(file) == FALSE) { return FALSE; } /* read file looking for SOF (start of frame) ... when it or */ /* or SOS (start of scan, the compressed data) is reached, stop */ while(JpegNextMarker(file, &marker, &size) == TRUE) { /* if SOS, stop */ if(marker == M_SOS) { HtpMsg(MSG_WARNING, NULL, "JFIF SOS marker found before SOF marker"); break; } /* if not SOF, continue */ switch (marker) { case M_SOF0: /* Baseline */ case M_SOF1: /* Extended sequential, Huffman */ case M_SOF2: /* Progressive, Huffman */ case M_SOF3: /* Lossless, Huffman */ case M_SOF5: /* Differential sequential, Huffman */ case M_SOF6: /* Differential progressive, Huffman */ case M_SOF7: /* Differential lossless, Huffman */ case M_SOF9: /* Extended sequential, arithmetic */ case M_SOF10: /* Progressive, arithmetic */ case M_SOF11: /* Lossless, arithmetic */ case M_SOF13: /* Differential sequential, arithmetic */ case M_SOF14: /* Differential progressive, arithmetic */ case M_SOF15: /* Differential lossless, arithmetic */ /* start of frame found ... process the dimension information */ /* read the height and width and get outta here */ if(fread(buff, 1, 5, file) != 5) { HtpMsg(MSG_WARNING, NULL, "unable to read dimensions from JFIF file"); return FALSE; } /* words are kept in MSB format */ *height = MAKE_WORD(buff[1], buff[2]); *width = MAKE_WORD(buff[3], buff[4]); return TRUE; default: if (fseek (file, size-2, SEEK_CUR) != 0) { HtpMsg(MSG_WARNING, NULL, "unable to seek past JFIF block"); return FALSE; } } } HtpMsg(MSG_WARNING, NULL, ("JFIF SOF marker not found")); /* didn't find the SOF or found the SOS */ return FALSE; } htp-1.19/src/ver.c0000664000175000017500000000206412525674213014135 0ustar hoenickehoenicke/* // // ver.c // // version and program information // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #include "htp.h" /* // program usage & syntax */ void DisplayHeader(void) { printf("\n%s %s - HTML pre-processor\n", PROGRAM_NAME, VER_STRING); printf("Copyright (c) 1995-96 Jim Nelson\n"); printf("Copyright (c) 2002-14 Jochen Hoenicke under Artistic License\n"); printf("[%s]\n\n", PROGRAM_OS); } void usage(void) { printf("Original author, Jim Nelson.\n"); printf("email:\thtp-discuss@lists.sourceforge.net\n"); printf("WWW:\thttp://htp.sourceforge.net/\n\n"); printf("usage: %s [options] \n", PROGRAM_NAME); printf(" %s [options] @\n", PROGRAM_NAME); printf(" %s [options] @\n", PROGRAM_NAME); printf("\nSee on-line reference for full details.\n"); printf("\nThis is software is released under the Artistic License.\n"); } htp-1.19/src/varstore.h0000664000175000017500000000717112525674213015217 0ustar hoenickehoenicke/* // // varstore.h // // Variable store functions (implemented with a splay tree) // // Copyright (c) 1995-96 Jim Nelson. // Copyright (c) 2002 Jochen Hoenicke. // Released under Artistic License. // */ #ifndef VARSTORE_H #define VARSTORE_H /* // maximum length for the variable name and the variables value */ #define MAX_VARNAME_LEN (256) #define MAX_VARVALUE_LEN (1024) /* // variable destructor callback ... set to NULL if no callback required when // destroyed */ typedef void (*VAR_DESTRUCTOR)(const char *name, void *value, uint type, uint flag, void *param); /* // a variable held in the store */ typedef struct tagVARIABLE { struct tagVARIABLE *left; struct tagVARIABLE *right; char *name; void *value; uint type; uint flag; void *param; VAR_DESTRUCTOR destructor; } VARIABLE; /* // variable store structure // // parent and child refers to scope ... when traversing the chain for a // particular macro, always look to parent scope if not found in current */ typedef struct tagVARSTORE { struct tagVARSTORE *parent; struct tagVARSTORE *child; VARIABLE *root; BOOL isGlobal; } VARSTORE; /* // statistics for performance measurement */ #if DEBUG extern uint variableLookups; extern uint variableStringCompares; extern uint variableRotations; #endif /* // GetVariableType() will return this value if the variable is not found */ #define VAR_TYPE_UNKNOWN ((uint) -1) /* // GetVariableFlag() will return this value if the variable is not found */ #define VAR_FLAG_UNKNOWN ((uint) -1) /* // initialize a VARSTORE */ BOOL InitializeVariableStore(VARSTORE *varstore); /* // destroys a variable store and ALL child scope stores */ void DestroyVariableStore(VARSTORE *varstore); /* // Push, pop, and get current varstore context ... note that for pop and // get, simply passing a variable store somewhere in the context will get // or pop the topmost one, and for push it will find the topmost context // before adding the new context */ void PushVariableStoreContext(VARSTORE *parent, VARSTORE *varstore); VARSTORE *PopVariableStoreContext(VARSTORE *varstore); /* // add a variable to a store ... the store will keep its // own copy of the variable kept, no need to maintain name and // value once added // // Set destructor to NULL if no additional processing required before // destroying the variable. Otherwise, pass a pointer to a function. // // Returns FALSE if unable to add variable into the store */ BOOL StoreVariable(VARSTORE *varstore, const char *name, void *value, uint type, uint flag, void *param, VAR_DESTRUCTOR destructor); /* // Returns TRUE if variable found in store (case-insensitive) */ BOOL VariableExists(VARSTORE *varstore, const char *name); /* // A variable's destructor will be called from the context of these // functions */ BOOL RemoveVariable(VARSTORE *varstore, const char *name); /* // Get variable information ... returns NULL for GetVariableValue(), // VAR_TYPE_UNKNOWN for GetVariableType(), and VAR_FLAG_UNKNOWN for // GetVariableFlag() if variable not in list // // GetVariableParam() returns NULL if not found ... since this is a valid // return value, caller should really use VariableExists() first! */ void *GetVariableValue(VARSTORE *varstore, const char *name); BOOL UpdateVariableValue(VARSTORE *varstore, const char *name, void* value); uint GetVariableType(VARSTORE *varstore, const char *name); uint GetVariableFlag(VARSTORE *varstore, const char *name); void *GetVariableParam(VARSTORE *varstore, const char *name); #endif htp-1.19/src/msg.c0000664000175000017500000000566412525674213014140 0ustar hoenickehoenicke/* // // msg.c // // Processing messages (informational, warning, and error) // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #include "htp.h" #include "option.h" #include "snprintf.h" /* symbols used to express severity of message */ const char *severitySymbol[3] = { "[-]", "[*]", "[!]", }; void HtpMsg(uint level, STREAM *textFile, const char *format, ...) { va_list argptr; char *str; /* check severity level */ if(level < GetOptionValue(OPT_I_MESSAGE)) { return; } /* allocate room for string ... 1K should be large enough, but a more */ /* deterministic method would be better */ if((str = AllocMemory(1024)) == NULL) { return; } /* convert variable arguments into single string */ va_start(argptr, format); vsnprintf(str, 1024, format, argptr); va_end(argptr); /* print the standard message header followed by formatted message */ printf("%s ", severitySymbol[level]); if(textFile != NULL) { printf("%s line %d: ", textFile->name, textFile->lineNumber); } printf("%s\n", str); /* free the string and exit */ FreeMemory(str); } #if DEBUG FILE *debugMsgFile = NULL; void DebugInit(const char *debugMsgFilename) { remove(debugMsgFilename); debugMsgFile = fopen(debugMsgFilename, "at"); if(debugMsgFile == NULL) { printf("htp: unable to open debug file \"%s\", aborting\n", debugMsgFilename); exit(1); } } void DebugTerminate(void) { if(debugMsgFile != NULL) { fclose(debugMsgFile); debugMsgFile = NULL; } } /* // DebugMsg // // DebugMsg is a helper function to (a) log a formatted string to disk and // (b) display the same string to the screen. This function is called by // DEBUG_PRINT, which is normally removed from the code in a final release // build. // // Because this debug information is really most useful when the program // is coughing up blood, this function will flush contents every time, // doing whatever it can to get the debug string to disk. Slow, but that's // what a debug build is for. // // Important: this file can't use the abstraction present in textfile.c // because *that* module uses DEBUG_PRINT as well ... (same for suballoc.c // functions) // */ void DebugMsg(const char *format, ...) { va_list argptr; char *str; /* 1K should be enough, but no guarantees */ if((str = malloc(1024)) == NULL) { /* !! gaaak */ return; } /* convert variable arguments into single string */ va_start(argptr, format); vsnprintf(str, 1024, format, argptr); va_end(argptr); /* write the string to disk */ fprintf(debugMsgFile, "%s", str); /* flush it out to disk */ fflush(debugMsgFile); #if 0 /* write it to screen */ printf(str); #endif free(str); } #endif htp-1.19/src/html.c0000664000175000017500000003723612525674213014316 0ustar hoenickehoenicke/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* // // html.c // // HTML markup tag functions // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #include "htp.h" const char *FindWhitespace(const char *str) { assert(str != NULL); while(*str != NUL) { if(isspace(*str)) { break; } str++; } return str; } const char *FindNonWhitespace(const char *str) { assert(str != NULL); while(*str != NUL) { if(!isspace(*str)) { break; } str++; } return str; } /* // HTML_ATTRIBUTE functions */ static BOOL MakeAttribute(HTML_ATTRIBUTE *htmlAttribute, const char *name, const char *value, int quotes) { assert(htmlAttribute != NULL); assert(name != NULL); /* create a duplicate of the string for the attribute structure */ if((htmlAttribute->name = DuplicateString(name)) == NULL) { return FALSE; } /* do the same for the value, if it exists */ if(value != NULL) { if((htmlAttribute->value = DuplicateString(value)) == NULL) { FreeMemory(htmlAttribute->name); htmlAttribute->name = NULL; return FALSE; } } else { htmlAttribute->value = NULL; } /* keep track if this was a quoted value */ htmlAttribute->quotes = quotes; htmlAttribute->whitespace = NULL; return TRUE; } BOOL ChangeAttributeName(HTML_ATTRIBUTE *htmlAttribute, char *name) { assert(htmlAttribute != NULL); /* although name should never be null, let it slide */ if(htmlAttribute->name != NULL) { FreeMemory(htmlAttribute->name); htmlAttribute->name = NULL; } htmlAttribute->name = name; return TRUE; } BOOL ChangeAttributeValue(HTML_ATTRIBUTE *htmlAttribute, char *value, int quotes) { assert(htmlAttribute != NULL); /* free the value's memory, if previously defined */ if(htmlAttribute->value != NULL) { FreeMemory(htmlAttribute->value); htmlAttribute->value = NULL; } htmlAttribute->value = value; htmlAttribute->quotes = quotes; return TRUE; } void DestroyAttribute(HTML_ATTRIBUTE *htmlAttribute) { assert(htmlAttribute != NULL); /* the attribute should always have a name */ assert(htmlAttribute->name != NULL); FreeMemory(htmlAttribute->name); htmlAttribute->name = NULL; if(htmlAttribute->value != NULL) { FreeMemory(htmlAttribute->value); htmlAttribute->value = NULL; } if (htmlAttribute->whitespace != NULL) { FreeMemory(htmlAttribute->whitespace); htmlAttribute->whitespace = NULL; } } /* // HTML_MARKUP functions */ /* this is perhaps the ugliest piece of code in the entire program ... it is also one of the most critical. (Surprise.) Allan Todd provided a very important fix: htp 1.0 and before would crash and burn if it hit a large comment. This was problematic for JavaScript and VBScript, which embed the interpreted code in comments to prevent other browsers from gagging. Allans solution is simply to pack the entire comment into one attribute. */ BOOL PlaintextToMarkup(const char *plaintext, HTML_MARKUP *htmlMarkup) { const char *plainPtr, *start; HTML_ATTRIBUTE **attribLink, *attrib; assert(plaintext != NULL); assert(htmlMarkup != NULL); /* although this isnt a good thing, its not something to halt execution over */ if(plaintext[0] == NUL) { DEBUG_PRINT(("no plaintext to convert")); return FALSE; } plainPtr = plaintext; /* initialize the markup structure */ htmlMarkup->tag = NULL; htmlMarkup->single = FALSE; htmlMarkup->attrib = NULL; attribLink = &htmlMarkup->attrib; /* walk the markup and build tag and attribute list (re-using the markup */ /* argument to walk the copied string) */ /* walk past any initial whitespace */ plainPtr = FindNonWhitespace(plainPtr); if(*plainPtr == NUL) { return TRUE; } /* mark first token as the tag */ start = plainPtr; /* walk to the first whitespace, mark it as NUL, and this is the tag */ plainPtr = FindWhitespace(plainPtr); /* copy the markup tag into the structure */ if((htmlMarkup->tag = DuplicateSubString(start, plainPtr - start)) == NULL) { DEBUG_PRINT(("unable to duplicate markup token")); return FALSE; } /* save and skip whitespace */ start = plainPtr; plainPtr = FindNonWhitespace(plainPtr); htmlMarkup->whitespace = DuplicateSubString(start, plainPtr - start); /* if a comment or php code, throw the whole she-bang into the attribute */ if (!strncmp(htmlMarkup->tag, "!--", 3) || htmlMarkup->tag[0] == '?') { if (*plainPtr == 0) return TRUE; *attribLink = attrib = AllocMemory(sizeof(HTML_ATTRIBUTE)); if(attrib == NULL) { DEBUG_PRINT(("unable to add attribute to markup")); DestroyMarkupStruct(htmlMarkup); return FALSE; } attrib->name = DuplicateString(plainPtr); attrib->value = NULL; attrib->whitespace = NULL; attrib->quotes = QUOTES_NONE; attrib->next = NULL; return TRUE; } /* start walking the rest of markup, looking for attributes and their */ /* values */ while(*plainPtr != NUL) { /* real attribute ore xml-closing? */ if (strcmp(plainPtr, "/") == 0) { htmlMarkup->single = TRUE; break; } *attribLink = attrib = AllocMemory(sizeof(HTML_ATTRIBUTE)); if(attrib == NULL) { DEBUG_PRINT(("unable to add attribute to markup")); DestroyMarkupStruct(htmlMarkup); return FALSE; } /* walk through the attribute, looking for whitespace or an */ /* equal sign */ start = plainPtr; while(*plainPtr != NUL && *plainPtr != '=' && !isspace(*plainPtr)) { plainPtr++; } attrib->name = DuplicateSubString(start, plainPtr - start); attrib->value = NULL; attrib->quotes = QUOTES_NONE; attrib->next = NULL; attrib->whitespace = NULL; attribLink = &attrib->next; if(*plainPtr == '=') { plainPtr++; if(*plainPtr == '\"' || *plainPtr == '\'') { /* quoted value, search for end quote */ char quote = *plainPtr; attrib->quotes = quote == '\"' ? QUOTES_DOUBLE: QUOTES_SINGLE; plainPtr++; start = plainPtr; while(*plainPtr != quote) { /* ReadHtml already checked that there is * a matching quote, but the quotes may * have appeared at a unchecked place before. */ if (*plainPtr == NUL) { DEBUG_PRINT(("can't find matching quote in markup")); DestroyMarkupStruct(htmlMarkup); return FALSE; } plainPtr++; } attrib->value = DuplicateSubString(start, plainPtr - start); plainPtr++; } else { start = plainPtr; plainPtr = FindWhitespace(plainPtr); attrib->value = DuplicateSubString(start, plainPtr - start); } } /* skip past whitespace (looking for next value) */ start = plainPtr; plainPtr = FindNonWhitespace(plainPtr); attrib->whitespace = DuplicateSubString(start, plainPtr - start); } return TRUE; } BOOL AddAttributeToMarkup(HTML_MARKUP *htmlMarkup, const char *name, const char *value, int quotedValue) { HTML_ATTRIBUTE **attribPtr, *attrib; assert(htmlMarkup != NULL); assert(name != NULL); attrib = AllocMemory(sizeof(HTML_ATTRIBUTE)); if(attrib == NULL) { DEBUG_PRINT(("unable to create attribute structure")); return FALSE; } if (!MakeAttribute(attrib, name, value, quotedValue)) { FreeMemory(attrib); DEBUG_PRINT(("unable to make attribute")); return FALSE; } attribPtr = &htmlMarkup->attrib; while (*attribPtr != NULL) { attribPtr = &(*attribPtr)->next; } *attribPtr = attrib; attrib->next = NULL; return TRUE; } void DestroyMarkupStruct(HTML_MARKUP *htmlMarkup) { HTML_ATTRIBUTE *attrib, *next; assert(htmlMarkup != NULL); /* destroy the tag */ /* do not assert against this, as this function might be used to */ /* destroy a partially-built structure */ if(htmlMarkup->tag != NULL) { FreeMemory(htmlMarkup->tag); htmlMarkup->tag = NULL; } attrib = htmlMarkup->attrib; htmlMarkup->attrib = NULL; if (htmlMarkup->whitespace != NULL) { FreeMemory(htmlMarkup->whitespace); htmlMarkup->whitespace = NULL; } /* destroy all markup attributes */ while (attrib != NULL) { next = attrib->next; DestroyAttribute(attrib); FreeMemory(attrib); attrib = next; } } BOOL IsMarkupTag(HTML_MARKUP *htmlMarkup, const char *tag) { assert(htmlMarkup != NULL); assert(tag != NULL); return (stricmp(htmlMarkup->tag, tag) == 0) ? TRUE : FALSE; } BOOL MarkupToPlaintext(HTML_MARKUP *htmlMarkup, char **plaintext) { HTML_ATTRIBUTE *htmlAttribute; uint size; uint attrSize; uint maxAttrSize; uint wslen; char *buffer, *bufferPtr; assert(htmlMarkup != NULL); assert(htmlMarkup->tag != NULL); assert(plaintext != NULL); /* estimate the required size of the plaintext buffer */ maxAttrSize = 0; /* compute length of separating space char */ wslen = htmlMarkup->whitespace != NULL ? strlen(htmlMarkup->whitespace) : 0; /* force whitespace if more attributes follow */ if (wslen == 0 && (htmlMarkup->attrib || htmlMarkup->single)) wslen = 1; /* additional byte is to account for NUL */ size = strlen(htmlMarkup->tag) + wslen + 1; htmlAttribute = htmlMarkup->attrib; while (htmlAttribute != NULL) { char *quotes = ""; assert(htmlAttribute != NULL); assert(htmlAttribute->name != NULL); /* compute length of separating space char */ wslen = htmlAttribute->whitespace != NULL ? strlen(htmlAttribute->whitespace) : 0; /* Force whitespace if more attributes follow */ if (wslen == 0 && (htmlAttribute->next || htmlMarkup->single)) wslen = 1; attrSize = strlen(htmlAttribute->name) + wslen; switch (htmlAttribute->quotes) { case QUOTES_DOUBLE: quotes= "\""; break; case QUOTES_SINGLE: quotes= "\'"; break; } if(htmlAttribute->value != NULL) { /* additional byte added to account for equal sign */ attrSize += strlen(htmlAttribute->value) + 1; /* account for the quote characters */ attrSize += 2 * strlen(quotes); } /* additional byte added for NULL character */ attrSize++; size += attrSize; if(maxAttrSize < attrSize) { maxAttrSize = attrSize; } htmlAttribute = htmlAttribute->next; } if (htmlMarkup->single) { size ++; } if((buffer = AllocMemory(size)) == NULL) { DEBUG_PRINT(("unable to allocate plaintext buffer (%u bytes)", size)); return FALSE; } /* start copying in the markup as plaintext */ bufferPtr = stpcpy(buffer, htmlMarkup->tag); if (htmlMarkup->whitespace == NULL || htmlMarkup->whitespace[0] == 0) { /* Force whitespace if more attributes follow */ if (htmlMarkup->attrib || htmlMarkup->single) bufferPtr = stpcpy(bufferPtr, " "); } else { bufferPtr = stpcpy(bufferPtr, htmlMarkup->whitespace); } htmlAttribute = htmlMarkup->attrib; while (htmlAttribute != NULL) { char *quotes = ""; /* checked previously, but check again */ assert(htmlAttribute != NULL); assert(htmlAttribute->name != NULL); switch (htmlAttribute->quotes) { case QUOTES_DOUBLE: quotes= "\""; break; case QUOTES_SINGLE: quotes= "\'"; break; } bufferPtr = stpcpy(bufferPtr, htmlAttribute->name); if (htmlAttribute->value != NULL) { bufferPtr = stpcpy(bufferPtr, "="); bufferPtr = stpcpy(bufferPtr, quotes); bufferPtr = stpcpy(bufferPtr, htmlAttribute->value); bufferPtr = stpcpy(bufferPtr, quotes); } if (htmlAttribute->whitespace == NULL || htmlAttribute->whitespace[0] == 0) { /* Force whitespace if more attributes follow */ if (htmlAttribute->next || htmlMarkup->single) bufferPtr = stpcpy(bufferPtr, " "); } else { bufferPtr = stpcpy(bufferPtr, htmlAttribute->whitespace); } htmlAttribute = htmlAttribute->next; } if ((htmlMarkup->single) == TRUE) { bufferPtr = stpcpy(bufferPtr,"/"); } /* give the buffer to caller */ *plaintext = buffer; return TRUE; } HTML_ATTRIBUTE **FindMarkupAttribute(HTML_MARKUP *htmlMarkup, const char *name) { HTML_ATTRIBUTE **attribPtr; assert(htmlMarkup != NULL); assert(name != NULL); attribPtr = &htmlMarkup->attrib; while (*attribPtr != NULL) { if (stricmp((*attribPtr)->name, name) == 0) return attribPtr; attribPtr = &(*attribPtr)->next; } return NULL; } const char *MarkupAttributeValue(HTML_MARKUP *htmlMarkup, const char *name) { HTML_ATTRIBUTE **attribPtr; assert(htmlMarkup != NULL); if((attribPtr = FindMarkupAttribute(htmlMarkup, name)) == NULL) { return NULL; } /* check validity of attribute */ assert ((*attribPtr)->name != NULL); return (*attribPtr)->value; } BOOL ChangeMarkupTag(HTML_MARKUP *htmlMarkup, char *tag) { assert(htmlMarkup != NULL); assert(tag != NULL); if(htmlMarkup->tag != NULL) { FreeMemory(htmlMarkup->tag); } htmlMarkup->tag = tag; return TRUE; } HTML_ATTRIBUTE *UnlinkAttributeInMarkup(HTML_MARKUP *htmlMarkup, const char *name) { HTML_ATTRIBUTE **attribPtr, *attrib; assert(htmlMarkup != NULL); if((attribPtr = FindMarkupAttribute(htmlMarkup, name)) == NULL) { return NULL; } attrib = *attribPtr; *attribPtr = attrib->next; attrib->next = NULL; return attrib; } BOOL UnlinkBoolAttributeInMarkup(HTML_MARKUP *htmlMarkup, const char *name) { HTML_ATTRIBUTE **attribPtr, *attrib; assert(htmlMarkup != NULL); if((attribPtr = FindMarkupAttribute(htmlMarkup, name)) == NULL) { return FALSE; } attrib = *attribPtr; /* If it has a value it is not a bool attribute */ if (attrib->value != NULL) return FALSE; *attribPtr = attrib->next; attrib->next = NULL; FreeMemory(attrib->name); if (attrib->whitespace) FreeMemory(attrib->whitespace); FreeMemory(attrib); return TRUE; } htp-1.19/src/image-proc.c0000664000175000017500000001463412525674213015372 0ustar hoenickehoenicke/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* // // image-proc.c // // specialized markup processors // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #include "defs.h" #include "option.h" #include "snprintf.h" /* // specialized markup processors */ uint ImageProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext) { char str[32]; IMAGEFILE imageFile; DWORD width, height; const char *imgSource; const char *imgFilename; const char *imgText; char altFilename[MAX_FILENAME_LEN+8]; UNREF_PARAM(newPlaintext); /* parse down the image source to just the filename */ imgSource = MarkupAttributeValue(htmlMarkup, "SRC"); if(imgSource == NULL) { HtpMsg(MSG_WARNING, task->infile, "image SRC not specified, skipping"); return MARKUP_OKAY; } /* try to find ALT text in store */ /* first: is there already ALT attribute? if so, skip this step */ if(MarkupAttributeValue(htmlMarkup, "ALT") == NULL) { /* parse the image name, just find the filename */ imgFilename = FindFilename(imgSource); strcpy(altFilename, "_htpalt_"); StringCopy(altFilename + 8, imgFilename, MAX_FILENAME_LEN); /* add the specified text to the image */ imgText = GetVariableValue(task->varstore, altFilename); if (imgText != NULL) { AddAttributeToMarkup (htmlMarkup, "alt", imgText, QUOTES_DOUBLE); HtpMsg(MSG_INFO, task->infile, "ALT text \"%s\" added to IMG \"%s\"", imgText, imgSource); } } /* if option is turned off, then just include the markup as-is */ if(IMGXY == FALSE) { return MARKUP_OKAY; } /* if width and/or height are already specified, then include the */ /* markup as-is with no modifications */ if (MarkupAttributeValue(htmlMarkup, "HEIGHT") != NULL || MarkupAttributeValue(htmlMarkup, "WIDTH") != NULL) { return MARKUP_OKAY; } /* open the image file, get its dimensions, and close the file */ if(OpenImageFile(imgSource, &imageFile) == FALSE) { HtpMsg(MSG_WARNING, task->infile, "unable to open image file \"%s\"", imgSource); return MARKUP_OKAY; } if(GetImageDimensions(&imageFile, &width, &height) == FALSE) { HtpMsg(MSG_WARNING, task->infile, "unable to determine image file \"%s\" dimensions", imgSource); } else { /* add the width and height specifier for the image */ snprintf(str, 32, "%lu", width); AddAttributeToMarkup(htmlMarkup, "width", str, QUOTES_DOUBLE); snprintf(str, 32, "%lu", height); AddAttributeToMarkup(htmlMarkup, "height", str, QUOTES_DOUBLE); /* print out an informational message to the user */ HtpMsg(MSG_INFO, task->outfile, "image file \"%s\" dimensions (%u x %u) added", imgSource, width, height); } CloseImageFile(&imageFile); /* include the markup in the final output */ return MARKUP_OKAY; } uint AltTextProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext) { const char *imgName, *imgText; char *altNameCopy, *imgTextCopy; char altName[MAX_FILENAME_LEN+8]; UNREF_PARAM(newPlaintext); /* get the relevant information */ imgName = MarkupAttributeValue(htmlMarkup, "NAME"); /* requires at least a NAME parameter */ if (imgName == NULL) { HtpMsg(MSG_ERROR, task->infile, "ALTTEXT requires a nonempty NAME attribute"); return MARKUP_ERROR; } imgText = MarkupAttributeValue(htmlMarkup, "TEXT"); strcpy(altName, "_htpalt_"); StringCopy(altName + 8, imgName, MAX_FILENAME_LEN); /* if no name specified, delete it from the store */ if(imgText == NULL) { /* try to find the graphic name in the ALTTEXT store */ if (RemoveVariable(task->varstore, altName) == TRUE) { HtpMsg(MSG_INFO, task->infile, "ALT text for image \"%s\" removed", imgName); } else { /* tried to delete an image not already in the store */ /* just post a warning */ HtpMsg(MSG_WARNING, task->infile, "attempted to delete image text not already defined"); } return DISCARD_MARKUP; } if ((altNameCopy = DuplicateString(altName)) == NULL || (imgTextCopy = DuplicateString(imgText)) == NULL) { HtpMsg(MSG_ERROR, task->infile, "Can't duplicate text, out of Memory."); if (altNameCopy != NULL) FreeMemory(altNameCopy); return MARKUP_ERROR; } StoreVariable(task->varstore, altNameCopy, imgTextCopy, VAR_TYPE_ALTTEXT, VAR_FLAG_DEALLOC_NAME | VAR_FLAG_DEALLOC_VALUE, NULL, NULL); HtpMsg(MSG_INFO, task->infile, "ALT text for image \"%s\" set to \"%s\"", imgName, imgText); return DISCARD_MARKUP; } uint ImageUrlProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext) { const char *url, *path; char *pathCopy; UNREF_PARAM(newPlaintext); /* get the relevant information */ url = MarkupAttributeValue(htmlMarkup, "URL"); /* requires at least a NAME parameter */ if (url == NULL) { HtpMsg(MSG_ERROR, task->infile, "IMAGEURL requires a nonempty URL attribute"); return MARKUP_ERROR; } path = MarkupAttributeValue(htmlMarkup, "PATH"); /* if no name specified, delete it from the store */ if (path == NULL) { if (RemoveImageUrl(url)) { HtpMsg(MSG_INFO, task->infile, "path for image URL \"%s\" removed", url); } else { /* tried to delete an image not already in the store */ /* just post a warning */ HtpMsg(MSG_WARNING, task->infile, "attempted to delete URL path not already defined"); } return DISCARD_MARKUP; } if ((pathCopy = ConvertDirDelimiter(path)) == NULL) { HtpMsg(MSG_ERROR, task->infile, "Can't duplicate path, out of Memory."); return MARKUP_ERROR; } StoreImageUrl(url, pathCopy); HtpMsg(MSG_INFO, task->infile, "path for URL \"%s\" set to \"%s\"", url, path); return DISCARD_MARKUP; } htp-1.19/src/macro.h0000664000175000017500000000137712525674213014455 0ustar hoenickehoenicke/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* // // macro.h // // specialized markup processors // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #ifndef MACRO_H #define MACRO_H #include "defs.h" BOOL ExpandMacrosInString(TASK *task, const char *text, char **newText, int *quoted, uint *changeCount); BOOL ExpandMacros(TASK *task, HTML_MARKUP *htmlMarkup); #define METATAG_MAX_OPTIONS (256) uint ExpandMetatag(TASK *task, HTML_MARKUP *htmlMarkup); uint ExpandAll(TASK *task, HTML_MARKUP *htmlMarkup, char** newPlaintextPtr, uint markupType); #endif htp-1.19/src/varstore.c0000664000175000017500000002170412525674213015210 0ustar hoenickehoenicke/* // // varstore.c // // Variable store functions (implemented with a splay tree) // The splay tree algorithm are taken from D. Sleator's examples. // // Copyright (c) 1995-96 Jim Nelson. // Copyright (c) 2002 Jochen Hoenicke. // Released under Artistic License. // */ #include "htp.h" #include "defs.h" /* statistics for performance measurement */ #if DEBUG uint variableLookups = 0; uint variableStringCompares = 0; uint variableRotations = 0; #endif /* // top down splay routine. // // If name is in the tree with root t, it will be moved to the // top of the tree and the element is returned. // // If name is not in the tree a neighbour of name is moved to the // top of the tree and NULL is returned. // // If tree is empty NULL is returned. */ static VARIABLE *VariableSplay (const char *name, VARIABLE ** root) { VARIABLE N, *t, *l, *r, *result; int cmp; t = *root; if (t == NULL) return t; /* Fast path */ cmp = stricmp(name, t->name); if (cmp == 0) return t; /* Slow path: Need to reorder tree */ result = NULL; N.left = N.right = NULL; l = r = &N; for (;;) { #if DEBUG variableStringCompares++; #endif if (cmp < 0) { if (t->left == NULL) break; cmp = stricmp(name, t->left->name); if (cmp < 0) { VARIABLE *y; y = t->left; /* rotate right */ t->left = y->right; y->right = t; t = y; #if DEBUG variableStringCompares++; variableRotations++; #endif if (t->left == NULL) break; cmp = stricmp(name, t->left->name); } r->left = t; /* link right */ r = t; t = t->left; } else if (cmp > 0) { if (t->right == NULL) break; cmp = stricmp(name, t->right->name); if (cmp > 0) { VARIABLE *y; y = t->right; /* rotate left */ t->right = y->left; y->left = t; t = y; #if DEBUG variableStringCompares++; variableRotations++; #endif if (t->right == NULL) break; cmp = stricmp(name, t->right->name); } l->right = t; /* link left */ l = t; t = t->right; } else { /* we found the name */ result = t; break; } } l->right = t->left; /* assemble */ r->left = t->right; t->left = N.right; t->right = N.left; *root = t; return result; } BOOL InitializeVariableStore(VARSTORE *varstore) { assert(varstore != NULL); /* initialize the store */ varstore->parent = NULL; varstore->root = NULL; varstore->child = NULL; varstore->isGlobal = FALSE; return TRUE; } /* // Call destructors for variable and/or free the name/value. */ static void DestroyVariable(VARIABLE *variable) { /* if the variable has a destructor callback, do it */ if(variable->destructor != NULL) { variable->destructor(variable->name, variable->value, variable->type, variable->flag, variable->param); } /* Deallocate name and value if the corresponding flags are set */ if (variable->flag & VAR_FLAG_DEALLOC_NAME) { FreeMemory(variable->name); } if (variable->flag & VAR_FLAG_DEALLOC_VALUE) { FreeMemory(variable->value); } } static void ClearVariableTree(VARIABLE *t) { if (t == NULL) return; ClearVariableTree(t->left); ClearVariableTree(t->right); DestroyVariable(t); FreeMemory(t); } void DestroyVariableStore(VARSTORE *varstore) { /* The children must have been destroyed earlier */ assert(varstore->child == NULL); /* unlink from parent */ if(varstore->parent != NULL) { varstore->parent->child = NULL; varstore->parent = NULL; } /* destroy all variables in this store */ ClearVariableTree(varstore->root); varstore->root = NULL; } static VARIABLE *FindVariable(VARSTORE *varstore, const char *name) { VARIABLE *ptr; assert(varstore != NULL); assert(name != NULL); #if DEBUG variableLookups++; #endif do { ptr = VariableSplay(name, &varstore->root); if(ptr) return ptr; /* check all parent stores as well */ varstore = varstore->parent; } while (varstore != NULL); return NULL; } void *GetVariableValue(VARSTORE *varstore, const char *name) { char *value; VARIABLE *variable; if(name != NULL) { if((variable = FindVariable(varstore, name)) != NULL) { return variable->value; } if((value = getenv(name)) != NULL) { return value; } } return NULL; } BOOL StoreVariable(VARSTORE *varstore, const char *name, void *value, uint type, uint flag, void *param, VAR_DESTRUCTOR destructor) { VARIABLE *variable; assert(varstore != NULL); assert(name != NULL); /* remove any variable with the same name in the store */ variable = VariableSplay(name, &varstore->root); if (variable) { /* Replace an existing variable */ DestroyVariable(variable); } else { /* allocate space for the variable structure */ if((variable = AllocMemory(sizeof(VARIABLE))) == NULL) { DEBUG_PRINT(("unable to allocate memory for new variable")); return FALSE; } if (varstore->root == NULL) { variable->left = variable->right = NULL; } else if (stricmp(name, varstore->root->name) < 0) { variable->left = varstore->root->left; variable->right = varstore->root; varstore->root->left = NULL; } else { variable->right = varstore->root->right; variable->left = varstore->root; varstore->root->right = NULL; } varstore->root = variable; } /* set the variable's name and value */ variable->name = (char *) name; variable->value = value; /* set flags and destructor pointer */ variable->type = type; variable->flag = flag; variable->param = param; variable->destructor = destructor; return TRUE; } /* // TODO: Get rid of the function. IncProcessor is the only one using this. */ BOOL UpdateVariableValue(VARSTORE *varstore, const char *name, void *value) { VARIABLE *variable; assert(name != NULL); assert(value != NULL); do { variable = VariableSplay(name, &varstore->root); if (variable) break; /* check the parent store if this isn't the global store */ if (varstore->isGlobal) break; varstore = varstore->parent; } while (varstore != NULL); if (variable == NULL) return FALSE; /* Replace an existing variable */ if (variable->value != NULL && (variable->flag & VAR_FLAG_DEALLOC_VALUE)) FreeMemory(variable->value); variable->value = value; variable->flag |= VAR_FLAG_DEALLOC_VALUE; variable->flag &= ~VAR_FLAG_UNDEFINED; return TRUE; } uint GetVariableType(VARSTORE *varstore, const char *name) { VARIABLE *variable; if(name != NULL) { if((variable = FindVariable(varstore, name)) != NULL) { return variable->type; } if(getenv(name) != NULL) { return 1; } } return VAR_TYPE_UNKNOWN; } uint GetVariableFlag(VARSTORE *varstore, const char *name) { VARIABLE *variable; if(name != NULL) { if((variable = FindVariable(varstore, name)) != NULL) { return variable->flag; } } return VAR_FLAG_UNKNOWN; } BOOL RemoveVariable(VARSTORE *varstore, const char *name) { VARIABLE *ptr; assert(varstore != NULL); assert(name != NULL); ptr = VariableSplay(name, &varstore->root); if(ptr) { /* found the variable */ if (ptr->left == NULL) { varstore->root = ptr->right; } else { VariableSplay(name, &ptr->left); varstore->root = ptr->left; varstore->root->right = ptr->right; } /* call destructors */ DestroyVariable(ptr); /* free the structure */ FreeMemory(ptr); return TRUE; } /* check all parent stores as well */ if(varstore->parent != NULL) { return RemoveVariable(varstore->parent, name); } return FALSE; } BOOL VariableExists(VARSTORE *varstore, const char *name) { if (FindVariable(varstore, name) != NULL) { return TRUE; } if (getenv(name) != NULL) { return TRUE; } return FALSE; } void *GetVariableParam(VARSTORE *varstore, const char *name) { VARIABLE *var; if(name != NULL) { if((var = FindVariable(varstore, name)) != NULL) { return var->param; } } return NULL; } void PushVariableStoreContext(VARSTORE *parent, VARSTORE *varstore) { assert(parent != NULL); assert(parent->child == NULL); assert(varstore != NULL); assert(varstore->parent == NULL); parent->child = varstore; varstore->parent = parent; varstore->child = NULL; } VARSTORE *PopVariableStoreContext(VARSTORE *varstore) { assert(varstore != NULL); assert(varstore->child == NULL); /* unlink from parent and return current context */ varstore->parent->child = NULL; varstore->parent = NULL; return varstore; } htp-1.19/src/def-proc.c0000664000175000017500000002607212525674213015045 0ustar hoenickehoenicke/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* // // def-proc.c // // specialized markup processors // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #include "def-proc.h" #include "defs.h" #include "htp-files.h" #include "macro.h" #include "option.h" /* // Block macro destructor callback ... used whenever a block macro is // destroyed with a RemoveVariable() or ClearVariableList() */ void BlockDestructor(const char *name, void *value, uint type, uint flags, void *param) { STREAM *stream = (STREAM*) value; UNREF_PARAM(name); UNREF_PARAM(type); UNREF_PARAM(flags); CloseStream(stream); FreeMemory(stream); /* DEF macros use param */ if(param != NULL) { FreeMemory(param); } } BOOL ReadBlockToFile(TASK *task, BOOL expand, const char *tag, STREAM *blockFile) { char *plaintext; char ch; HTML_MARKUP newHtml; BOOL result; static uint blockDepth = 0; uint markupType; STREAM *oldOutFile; uint markupResult; HtpMsg(MSG_INFO, task->infile, "reading %s block to memory", expand ? "expanded" : "raw"); oldOutFile = task->outfile; task->outfile = blockFile; /* Skip EOL, but put it back if it's another character */ if (GetStreamChar(task->infile, &ch) && ch != '\n') { UnreadStreamChar(task->infile, ch); } task->outfile->name = DuplicateString(task->infile->name); task->outfile->lineNumber = task->infile->lineNumber; /* start copying the file into the temporary file, looking for the */ /* BLOCK or /BLOCK tag if block macro, DEF or /DEF otherwise ... */ /* just squirrel away all other tags and text */ for(;;) { result = ReadHtmlMarkup(task->infile, blockFile, &markupType, &newHtml); if(result == ERROR) { task->outfile = oldOutFile; return FALSE; } else if(result == FALSE) { /* end-of-file encountered before end-of-block */ HtpMsg(MSG_ERROR, task->infile, "EOF encountered before %s in line %d was closed", tag, task->outfile->lineNumber); task->outfile = oldOutFile; return FALSE; } if ((markupType & MARKUP_TYPE_HTP) && blockDepth == 0 && newHtml.tag[0] == '/' && stricmp(tag, newHtml.tag+1) == 0) { /* found the end of the macro block */ DestroyMarkupStruct(&newHtml); break; } plaintext = NULL; if (expand) { /* give the default processor a chance to expand macros, etc. */ markupResult = ExpandAll(task, &newHtml, &plaintext, markupType); } else { if(markupType & MARKUP_TYPE_HTP) { /* check for embedded block declarations */ if (stricmp(tag, newHtml.tag) == 0) { /* add to the block macro depth and continue */ blockDepth++; } else if (newHtml.tag[0] == '/' && stricmp(tag, newHtml.tag+1) == 0) { /* depth has decreased one */ blockDepth--; } } /* if continuing, then the plaintext is put into the * output stream as-is ... there is no case where the * processor continues scanning but discards a markup */ if(MarkupToPlaintext(&newHtml, &plaintext) == FALSE) { HtpMsg(MSG_ERROR, task->infile, "unable to build plain text from markup (out of memory?)"); task->outfile = oldOutFile; return MARKUP_ERROR; } markupResult = MARKUP_OKAY; } switch(markupResult) { case MARKUP_OKAY: { /* add the markup to the output file as it should appear */ StreamPrintF(blockFile, "%c%s%c", MARKUP_OPEN_DELIM(markupType), plaintext, MARKUP_CLOSE_DELIM(markupType)); } break; case NEW_MARKUP: case MARKUP_REPLACED: { /* the markup has been replaced by a normal string */ StreamPrintF(blockFile, "%s", plaintext); } break; case DISCARD_MARKUP: { /* markup will not be included in final output */ } break; case MARKUP_ERROR: { /* (need to destroy plaintext buffer before exiting) */ FreeMemory(plaintext); task->outfile = oldOutFile; return FALSE; } default: { FreeMemory(plaintext); printf("%s: serious internal error\n", PROGRAM_NAME); exit(1); } } /* destroy the HTML markup, not needed any longer */ DestroyMarkupStruct(&newHtml); /* destroy the plaintext buffer */ if (plaintext) FreeMemory(plaintext); } task->outfile = oldOutFile; return TRUE; } BOOL ReadinBlock(TASK *task, HTML_MARKUP *htmlMarkup, STREAM *blockStream) { BOOL expand = UnlinkBoolAttributeInMarkup(htmlMarkup, "EXPAND"); if (htmlMarkup->attrib != NULL) { HtpMsg(MSG_WARNING, task->infile, "Unhandled %s attribute in %s markup", htmlMarkup->attrib->name, htmlMarkup->tag); } /* try and create the temporary file */ if(CreateBufferWriter(blockStream, htmlMarkup->tag) == FALSE) { HtpMsg(MSG_ERROR, task->infile, "unable to create stream for %s macro", htmlMarkup->tag); return FALSE; } if (ReadBlockToFile(task, expand, htmlMarkup->tag, blockStream) == FALSE) { CloseStream(blockStream); FreeMemory(blockStream); return FALSE; } FlushBufferWriter(blockStream); return TRUE; } uint BlockProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext) { char *defName, *param; STREAM *stream; BOOL blockMacro; uint macroType; VARSTORE *varstore; HTML_ATTRIBUTE *attrib; UNREF_PARAM(newPlaintext); /* first: is this a BLOCK macro or a DEF macro? This function is */ /* overloaded to handle both types, and must internally change its */ /* functionality for each type */ /* if this is false, this is a DEF macro */ if(stricmp(htmlMarkup->tag, "BLOCK") == 0) { blockMacro = TRUE; macroType = VAR_TYPE_BLOCK_MACRO; /* no extra varstore parameter for a block macro */ param = NULL; } else { blockMacro = FALSE; if (stricmp(htmlMarkup->tag, "BLOCKDEF") == 0) { macroType = VAR_TYPE_BLOCKDEF_MACRO; } else { assert(stricmp(htmlMarkup->tag, "DEF") == 0); macroType = VAR_TYPE_DEF_MACRO; } /* get the OPTION parameter */ attrib = UnlinkAttributeInMarkup(htmlMarkup, "OPTION"); if (attrib != NULL) { FreeMemory(attrib->name); param = attrib->value; if (attrib->whitespace) FreeMemory(attrib->whitespace); FreeMemory(attrib); } else { param = NULL; } } /* check if name is present */ attrib = UnlinkAttributeInMarkup(htmlMarkup, "NAME"); if (attrib != NULL && attrib->value != NULL) { /* new syntax */ FreeMemory(attrib->name); defName = attrib->value; if (attrib->whitespace) FreeMemory(attrib->whitespace); FreeMemory(attrib); } else { /* The only attribute is the macro name without value * (which can be "name" though). */ if (attrib == NULL) { attrib = htmlMarkup->attrib; if(attrib == NULL) { HtpMsg(MSG_ERROR, task->infile, "%s markup without name", htmlMarkup->tag); return MARKUP_ERROR; } htmlMarkup->attrib = attrib->next; } defName = attrib->name; if (attrib->whitespace) FreeMemory(attrib->whitespace); if (attrib->value != NULL || htmlMarkup->attrib != NULL) { HtpMsg(MSG_ERROR, task->infile, "bad %s markup", htmlMarkup->tag); if (attrib->value != NULL) FreeMemory(attrib->value); FreeMemory(attrib); return MARKUP_ERROR; } FreeMemory(attrib); /* old style only allowed for block macros */ if(!blockMacro) { HtpMsg(MSG_ERROR, task->infile, "%s requires NAME attribute", htmlMarkup->tag); return MARKUP_ERROR; } } /* store the block file name and the block macro name as a variable */ varstore = task->varstore; if (UnlinkBoolAttributeInMarkup(htmlMarkup, "GLOBAL")) { while (!varstore->isGlobal) varstore = varstore->parent; } stream = (STREAM*) AllocMemory(sizeof(STREAM)); if (!ReadinBlock(task, htmlMarkup, stream)) { FreeMemory(defName); if (param != NULL) FreeMemory(param); return MARKUP_ERROR; } if(StoreVariable(varstore, defName, stream, macroType, VAR_FLAG_DEALLOC_NAME, param, BlockDestructor) == FALSE) { HtpMsg(MSG_ERROR, task->infile, "unable to store macro information (out of memory?)"); FreeMemory(defName); if (param != NULL) FreeMemory(param); return MARKUP_ERROR; } return DISCARD_MARKUP; } uint UndefProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext) { HTML_ATTRIBUTE *attrib; uint type; UNREF_PARAM(newPlaintext); attrib = htmlMarkup->attrib; /* need at least one attribute to undef */ if(htmlMarkup->attrib == NULL) { HtpMsg(MSG_ERROR, task->infile, "UNDEF requires at least one name"); return MARKUP_ERROR; } /* walk the list of attributes, deleting them as found */ while (attrib != NULL) { /* only remove it if it is a [BLOCK]DEF macro */ type = GetVariableType(task->varstore, attrib->name); if(type == VAR_TYPE_DEF_MACRO || type == VAR_TYPE_BLOCKDEF_MACRO) { RemoveVariable(task->varstore, attrib->name); HtpMsg(MSG_INFO, task->infile, "metatag \"%s\" removed", attrib->name); } else { HtpMsg(MSG_ERROR, task->infile, "metatag \"%s\" never defined", attrib->name); return MARKUP_ERROR; } attrib = attrib->next; } return DISCARD_MARKUP; } htp-1.19/src/image-proc.h0000664000175000017500000000114412525674213015367 0ustar hoenickehoenicke/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* // // image-proc.h // // specialized markup processors // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #ifndef IMAGE_PROC_H #define IMAGE_PROC_H #include "defs.h" uint ImageProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext); uint AltTextProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext); uint ImageUrlProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext); #endif htp-1.19/src/suballoc.h0000664000175000017500000000711312525674213015152 0ustar hoenickehoenicke/* // // suballoc.h // // Memory suballocation ... rather than go out to heap for all the memory, // htp maintains a small cache of recently allocated memory for speedier // requests // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #ifndef SUBALLOC_H #define SUBALLOC_H /* //#undef USE_SUBALLOC */ #ifndef USE_SUBALLOC #define AllocMemory(size) malloc(size) #define FreeMemory(ptr) free(ptr) #define ResizeMemory(ptr, newSize) realloc(ptr, newSize) #else /* // performance counters */ #if DEBUG extern uint totalAllocations; extern uint freePoolHits; #endif /* // suballoc has several features that can be controlled via #defines // most features are turned off for release versions of the software to // speed up execution // // These features are: // // SUBALLOC_WARNING prints warning to stdout when problems are // detected // // SUBALLOC_CLEARMEM all memory is cleared with a special bit // pattern (not all zero or all one) when // allocated and freed // // SUBALLOC_DEBLOG will print all allocs and frees to a debug // log // // SUBALLOC_MINALLOCSIZE size (in bytes) of minimum allocation ... // helps prevent heap thrashing when lots of // small allocations occur ... if set to 0 // then allocation sizes match requested size // // SUBALLOC_FIRSTFIT if set, suballoc pulls the first properly sized // block out of its free pool, rather than the // one with the best fit ... faster, but may lead // to unnecessary allocs from the system heap // // SUBALLOC_MAXFREEPOOLSIZE if set, suballoc will keep the free pool // size equal to or less than this amount // ... too small a size will lead to excessive // heap allocations, too large could cause the // program to keep vital memory from the operating // system // */ #define SUBALLOC_MINALLOCSIZE (64) #define SUBALLOC_FIRSTFIT (1) #if DEBUG #define SUBALLOC_WARNING (1) #define SUBALLOC_CLEARMEM (1) #define SUBALLOC_DEBLOG (0) #else #define SUBALLOC_WARNING (0) #define SUBALLOC_CLEARMEM (0) #define SUBALLOC_DEBLOG (0) #endif #if __MSDOS__ #define SUBALLOC_MAXFREEPOOLSIZE (60 * KBYTE) #else #define SUBALLOC_MAXFREEPOOLSIZE (512 * KBYTE) #endif /* // Initialize and terminate functions ... should be called before and // after using following functions */ void InitializeMemory(void); void TerminateMemory(void); /* // AllocMemory // // malloc() look-alike */ void *_AllocMemory(uint size, const char *file, uint line); #define AllocMemory(size) _AllocMemory(size, __FILE__, __LINE__) /* // FreeMemory // // free() look-alike */ void _FreeMemory(void *ptr, const char *file, uint line); #define FreeMemory(ptr) _FreeMemory(ptr, __FILE__, __LINE__); /* // ResizeMemory // // realloc() look-alike */ void *_ResizeMemory(void *ptr, uint newSize, const char *file, uint line); #define ResizeMemory(ptr, newSize) \ _ResizeMemory(ptr, newSize, __FILE__, __LINE__) /* // MemorySize // // Returns available size of buffer */ uint MemorySize(void *ptr); #endif #endif htp-1.19/src/gif.c0000664000175000017500000000302312525674213014102 0ustar hoenickehoenicke/* // // gif.c // // GIF (Graphic Interchange Format) support functions // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #include "htp.h" BOOL GifFormatFound(FILE *file) { BYTE header[8]; /* move to BOF */ if(fseek(file, 0, SEEK_SET) != 0) { DEBUG_PRINT(("unable to seek to start of GIF file")); return FALSE; } /* read first six bytes, looking for GIF header + version info */ if(fread(header, 1, 6, file) != 6) { DEBUG_PRINT(("could not read GIF image file header")); return FALSE; } /* is this a GIF file? */ if((memcmp(header, "GIF87a", 6) == 0) || (memcmp(header, "GIF89a", 6) == 0)) { return TRUE; } /* not a GIF file */ return FALSE; } BOOL GifReadDimensions(FILE *file, DWORD *height, DWORD *width) { BYTE buff[4]; /* move to the image size position in the file header */ if(fseek(file, 6, SEEK_SET) != 0) { DEBUG_PRINT(("unable to seek to start of GIF file")); return FALSE; } /* read width and height into a byte array */ if(fread(buff, 1, 4, file) != 4) { DEBUG_PRINT(("unable to read word from JFIF file")); return FALSE; } /* this gets around machine endian problems while retaining the */ /* fact that GIF uses little-endian notation */ *width = MAKE_WORD(buff[1], buff[0]); *height = MAKE_WORD(buff[3], buff[2]); return TRUE; } htp-1.19/src/option.c0000664000175000017500000001040312525674213014645 0ustar hoenickehoenicke/* // // option.c // // Program options and setting // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #include "option.h" #include "msg.h" static uint globalOptions[OPT_I_COUNT]; static uint localOptions[OPT_I_COUNT]; uint *currentOptions; /* // */ const char *option_msg_index[] = { "image pre-processing", NULL, "dependency checking", "precious output", "condensed output", NULL, "markup delimiter", "use XML-style generator tag", }; const char *option_msg_value[] = { "turned OFF", "turned ON", "turned to SEMI", "set to \"<\"", "set to \"[\"", "set to \"{\"" }; BOOL SetOption(TASK *task, uint index, uint value) { if(task != NULL && option_msg_index[index] != NULL) { HtpMsg(MSG_INFO, task->infile, "%s %s", option_msg_index[index], option_msg_value[value]); } currentOptions[index] = value; if (index == OPT_I_DELIM) { switch (value) { case OPT_V_DELIM_HTML: htpOpenMarkup = '<'; htpCloseMarkup = '>'; break; case OPT_V_DELIM_CURLY: htpOpenMarkup = '{'; htpCloseMarkup = '}'; break; case OPT_V_DELIM_SQUARE: htpOpenMarkup = '['; htpCloseMarkup = ']'; break; } } return TRUE; } BOOL InitializeGlobalOption() { /* set defaults for all options */ globalOptions[OPT_I_IMGXY] = OPT_V_TRUE; globalOptions[OPT_I_MESSAGE] = MSG_INFO; globalOptions[OPT_I_DEPEND] = OPT_V_TRUE; globalOptions[OPT_I_PRECIOUS] = OPT_V_FALSE; globalOptions[OPT_I_CONDENSE] = OPT_V_SEMI; globalOptions[OPT_I_USAGE] = OPT_V_FALSE; globalOptions[OPT_I_DELIM] = OPT_V_DELIM_HTML; globalOptions[OPT_I_XML] = OPT_V_FALSE; currentOptions = globalOptions; return TRUE; } void DestroyGlobalOption(void) { } BOOL InitializeLocalOption(void) { memcpy(localOptions, globalOptions, sizeof(globalOptions)); currentOptions = localOptions; return TRUE; } void DestroyLocalOption(void) { } BOOL ParseToken(TASK *task, const char *string) { static const struct { char *name; uint index, value; } opt[] = { {"IMGXY", OPT_I_IMGXY, OPT_V_TRUE}, {"NOIMGXY", OPT_I_IMGXY, OPT_V_FALSE}, {"VERBOSE", OPT_I_MESSAGE, MSG_INFO}, {"QUIET", OPT_I_MESSAGE, MSG_WARNING}, {"DEPEND", OPT_I_DEPEND, OPT_V_TRUE}, {"NODEPEND", OPT_I_DEPEND, OPT_V_FALSE}, {"PRECIOUS", OPT_I_PRECIOUS, OPT_V_TRUE}, {"NOPRECIOUS", OPT_I_PRECIOUS, OPT_V_FALSE}, {"CONDENSE", OPT_I_CONDENSE, OPT_V_TRUE}, {"SEMICONDENSE", OPT_I_CONDENSE, OPT_V_SEMI}, {"NOCONDENSE", OPT_I_CONDENSE, OPT_V_FALSE}, {"DELIM=HTML", OPT_I_DELIM, OPT_V_DELIM_HTML}, {"DELIM=SQUARE", OPT_I_DELIM, OPT_V_DELIM_SQUARE}, {"DELIM=CURLY", OPT_I_DELIM, OPT_V_DELIM_CURLY}, {"XML", OPT_I_XML, OPT_V_TRUE}, {"XML=FALSE", OPT_I_XML, OPT_V_FALSE}, {"?", OPT_I_USAGE, OPT_V_TRUE}, {"H", OPT_I_USAGE, OPT_V_TRUE}, {"-HELP", OPT_I_USAGE, OPT_V_TRUE} }; int i; for (i = 0; i < sizeof(opt) / sizeof(opt[0]); i++) { if (stricmp(opt[i].name, string) == 0) return SetOption(task, opt[i].index, opt[i].value); } /* dont like it, but dont stop processing either */ HtpMsg(MSG_WARNING, task != NULL ? task->infile : NULL, "unknown option \"%s\" specified", string); return TRUE; } uint OptionProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext) { char buff[MAX_OPTION_LENGTH]; char *token; HTML_ATTRIBUTE *attrib; UNREF_PARAM(newPlaintext); /* technically, would like to avoid iterating through the HTML_MARKUP */ /* structure for certain (future design) reasons, but really have to */ /* for this to work */ attrib = htmlMarkup->attrib; while (attrib != NULL) { token = attrib->name; if(attrib->value != NULL) { StringCopy(buff, token, sizeof(buff)); strncat(buff, "=", sizeof(buff) - 1); strncat(buff, attrib->value, sizeof(buff) - 1); token = buff; } if(ParseToken(task, token) == FALSE) { return MARKUP_ERROR; } attrib = attrib->next; } return DISCARD_MARKUP; } htp-1.19/src/file-proc.c0000664000175000017500000004644512543266614015236 0ustar hoenickehoenicke/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* // // -proc.c // // specialized markup processors // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #include "defs.h" #include "macro.h" #include "htp-files.h" #include "def-proc.h" #include "file-proc.h" #include "snprintf.h" #ifdef HAVE_PIPE #include #include #include #endif uint ExternalFileProcessor(TASK *task, HTML_MARKUP *htmlMarkup, const char *externalName, char **newPlaintext) { struct stat fileStat; struct tm *fileTime; HTML_ATTRIBUTE *attrib; assert(externalName != NULL); assert(htmlMarkup != NULL); /* get information on the file itself */ if(stat(externalName, &fileStat) != 0) { HtpMsg(MSG_ERROR, task->infile, "unable to retrieve file information on \"%s\"", externalName); return MARKUP_ERROR; } /* allocate room for the replacment plaintext */ if((*newPlaintext = AllocMemory(MAX_TIME_DATE_SIZE)) == NULL) { HtpMsg(MSG_ERROR, task->infile, "unable to allocate memory for expansion"); return MARKUP_ERROR; } /* create new plaintext depending on what extra information is specified */ if((attrib = UnlinkAttributeInMarkup(htmlMarkup, "SIZE")) != NULL) { uint precision; HTML_ATTRIBUTE *pattrib; /* get the precision attribute value, if present */ precision = DEFAULT_PRECISION; if ((pattrib = UnlinkAttributeInMarkup(htmlMarkup, "PRECISION")) != NULL) { if(pattrib->value != NULL) { precision = atoi(pattrib->value); } else { HtpMsg(MSG_WARNING, task->infile, "precision attribute needs a value"); } DestroyAttribute(pattrib); FreeMemory(pattrib); } /* expand markup depending on how SIZE should be represented */ if((attrib->value == NULL) || (stricmp(attrib->value, "BYTE") == 0)) { /* byte representation is default */ snprintf(*newPlaintext, MAX_TIME_DATE_SIZE, "%lu", fileStat.st_size); } else if(stricmp(attrib->value, "KBYTE") == 0) { snprintf(*newPlaintext, MAX_TIME_DATE_SIZE, "%.*f", (int) precision, (double) ((double) fileStat.st_size / (double) KBYTE)); } else if(stricmp(attrib->value, "MBYTE") == 0) { snprintf(*newPlaintext, MAX_TIME_DATE_SIZE, "%.*f", (int) precision, (double) ((double) fileStat.st_size / (double) MBYTE)); } else if(stricmp(attrib->value, "GBYTE") == 0) { snprintf(*newPlaintext, MAX_TIME_DATE_SIZE, "%.*f", (int) precision, (double) ((double) fileStat.st_size / (double) GBYTE)); } else { /* free the plaintext memory before returning */ HtpMsg(MSG_ERROR, task->infile, "unknown SIZE specifier"); DestroyAttribute(attrib); FreeMemory(attrib); FreeMemory(*newPlaintext); *newPlaintext = NULL; return MARKUP_ERROR; } DestroyAttribute(attrib); FreeMemory(attrib); } else if((attrib = UnlinkAttributeInMarkup(htmlMarkup, "TIME")) != NULL) { const char *value; /* convert into an ANSI time structure */ fileTime = localtime(&fileStat.st_mtime); /* see if the attribute has a value ... if so, let it be the */ /* strftime() formatter */ if((value = MarkupAttributeValue(htmlMarkup, "TIME")) != NULL) { strftime(*newPlaintext, MAX_TIME_DATE_SIZE, value, fileTime); } else { strftime(*newPlaintext, MAX_TIME_DATE_SIZE, "%I:%M:%S %p", fileTime); } DestroyAttribute(attrib); FreeMemory(attrib); } else if((attrib = UnlinkAttributeInMarkup(htmlMarkup, "DATE")) != NULL) { /* convert into an ANSI time structure */ fileTime = localtime(&fileStat.st_mtime); /* see if the attribute has a value ... if so, let it be the */ /* strftime() formatter */ if (attrib->value != NULL) { strftime(*newPlaintext, MAX_TIME_DATE_SIZE, attrib->value, fileTime); } else { strftime(*newPlaintext, MAX_TIME_DATE_SIZE, "%a %b %d, %Y", fileTime); } DestroyAttribute(attrib); FreeMemory(attrib); } else { /* free the plaintext, unused */ FreeMemory(*newPlaintext); *newPlaintext = NULL; HtpMsg(MSG_ERROR, task->infile, "invalid FILE tag"); return MARKUP_ERROR; } /* the new plaintext was created successfully */ return NEW_MARKUP; } uint FileExecuteProcessor(TASK *task, HTML_ATTRIBUTE *attrib, HTML_MARKUP *htmlMarkup) { const char *cmdline; const char *output; HTML_ATTRIBUTE *outputAttrib; #ifndef HAVE_PIPE char newCmdline[MAX_CMDLINE_LEN]; char tempFilename[MAX_PATHNAME_LEN]; #endif BOOL redirect, ignoreError; STREAM infile; TASK newTask; BOOL result = TRUE; int exitCode; assert(task != NULL); assert(htmlMarkup != NULL); cmdline = attrib->value; redirect = UnlinkBoolAttributeInMarkup(htmlMarkup, "REDIRECT"); ignoreError = UnlinkBoolAttributeInMarkup(htmlMarkup, "NOERROR"); outputAttrib = UnlinkAttributeInMarkup(htmlMarkup, "OUTPUT"); if (outputAttrib != NULL) output = outputAttrib->value; else output = NULL; /* either output or redirect, but not both, must be specified */ if((output == NULL) && (redirect == FALSE)) { HtpMsg(MSG_ERROR, task->infile, "Either REDIRECT or OUTPUT must be specified for FILE EXECUTE"); return MARKUP_ERROR; } if((output != NULL) && (redirect == TRUE)) { HtpMsg(MSG_ERROR, task->infile, "REDIRECT and OUTPUT cannot both be specified for FILE EXECUTE"); DestroyAttribute(outputAttrib); FreeMemory(outputAttrib); return MARKUP_ERROR; } HtpMsg(MSG_INFO, task->infile, "Executing command \"%s\" ...", cmdline); #ifndef HAVE_PIPE /* if redirection required, append to the command-line a redirector to */ /* a temporary file */ if(redirect) { if(CreateTempFilename(tempFilename, MAX_PATHNAME_LEN) == FALSE) { HtpMsg(MSG_ERROR, task->infile, "unable to create a temporary file for redirection"); return MARKUP_ERROR; } strncpy(newCmdline, cmdline, MAX_PATHNAME_LEN); strncat(newCmdline, " > ", MAX_PATHNAME_LEN); strncat(newCmdline, tempFilename, MAX_PATHNAME_LEN); cmdline = newCmdline; output = tempFilename; } /* execute the command */ exitCode = system(cmdline); #else /* if redirection required, create a pipe for our child process */ if (redirect) { pid_t pid; int pipefds[2]; extern char **environ; if (pipe(pipefds) != 0) { HtpMsg(MSG_ERROR, task->infile, "unable to create pipe for redirection"); return MARKUP_ERROR; } pid = fork(); if (pid == 0) { char *argv[4]; dup2(pipefds[1], 1); close(pipefds[0]); close(pipefds[1]); argv[0] = "sh"; argv[1] = "-c"; argv[2] = (char*)cmdline; argv[3] = NULL; execve("/bin/sh", argv, environ); exit(127); } close(pipefds[1]); if (pid == -1) exitCode = -1; else { if (CreateFDReader(&infile, "stdout", pipefds[0]) == FALSE) { HtpMsg(MSG_ERROR, task->infile, "unable to open execute result file"); return MARKUP_ERROR; } /* build a new task */ newTask.infile = &infile; newTask.outfile = task->outfile; newTask.varstore = task->varstore; newTask.sourceFilename = task->sourceFilename; /* process the file */ result = ProcessTask(&newTask); if (!result) { /* Error message was already spitted out. However, we * should give a hint where the meta-tag was called. */ HtpMsg(MSG_ERROR, task->infile, "... in output from '%s'", cmdline); } CloseStream(&infile); /* wait for termination of the command */ while (waitpid(pid, &exitCode, 0) == -1) { if (errno != EINTR) { exitCode = -1; break; } } } } else { /* execute the command */ exitCode = system(cmdline); } #endif if(exitCode != 0 && ignoreError == FALSE) { /* the program has exited with an error condition */ HtpMsg(MSG_ERROR, task->infile, "Command \"%s\" exited with an error code of %u", cmdline, exitCode); /* remove the temporary file, in case it was partially created */ if (output != NULL) remove(output); if (outputAttrib != NULL) { DestroyAttribute(outputAttrib); FreeMemory(outputAttrib); } return MARKUP_ERROR; } if (output != NULL) { /* include the output file like it was anything else */ /* first, open it */ if(CreateFileReader(&infile, output) == FALSE) { HtpMsg(MSG_ERROR, task->infile, "unable to open execute result file"); return MARKUP_ERROR; } /* build a new task */ newTask.infile = &infile; newTask.outfile = task->outfile; newTask.varstore = task->varstore; newTask.sourceFilename = task->sourceFilename; /* process the file */ result = ProcessTask(&newTask); if (!result) { /* Error message was already spitted out. However, we * should give a hint where the meta-tag was called. */ HtpMsg(MSG_ERROR, task->infile, "... in output from '%s'", cmdline); } /* close and destroy the output file */ CloseStream(&infile); remove(output); if (outputAttrib != NULL) { DestroyAttribute(outputAttrib); FreeMemory(outputAttrib); } } return (result == TRUE) ? DISCARD_MARKUP : MARKUP_ERROR; } uint FileTemplateProcessor(TASK *task, HTML_ATTRIBUTE *attrib) { assert(task != NULL); assert(attrib != NULL); /* the template file is not actually processed now, but rather * when the rest of the file is completed ... to postpone * processing, the template name is kept in the variable store * under a special name and retrieved later */ if(StoreVariable(task->varstore, VAR_TEMPLATE_NAME, attrib->value, VAR_TYPE_INTERNAL, VAR_FLAG_DEALLOC_VALUE, NULL, NULL) == FALSE) { HtpMsg(MSG_ERROR, task->infile, "unable to store template filename for post-processing (out of memory?)"); return MARKUP_ERROR; } /* attrib->value was moved into VARSTORE */ attrib->value = NULL; return DISCARD_MARKUP; } uint FileIncludeProcessor(TASK *task, const char *filename, HTML_MARKUP *htmlMarkup) { STREAM incfile; BOOL result; TASK newTask; char fullPathname[MAX_PATHNAME_LEN]; VARSTORE varstore; VARSTORE *topVarstore; uint flag; /* open the include file as input */ if(CreateFileReader(&incfile, filename) == FALSE) { /* use the search path to find the file */ if(SearchForFile(filename, fullPathname, MAX_PATHNAME_LEN) == FALSE) { /* could not find the file in the search path either */ HtpMsg(MSG_ERROR, task->infile, "unable to open include file \"%s\"", filename); return MARKUP_ERROR; } if(CreateFileReader(&incfile, fullPathname) == FALSE) { HtpMsg(MSG_ERROR, task->infile, "unable to open include file \"%s\"", fullPathname); return MARKUP_ERROR; } } else { StringCopy(fullPathname, filename, MAX_PATHNAME_LEN); } /* if additional parameters exist in the tag, build a local varstore */ /* and push it onto the context */ if (htmlMarkup->attrib != NULL) { HTML_ATTRIBUTE *attrib; if(InitializeVariableStore(&varstore) == FALSE) { HtpMsg(MSG_ERROR, task->infile, "unable to initialize context for include file"); CloseStream(&incfile); return MARKUP_ERROR; } /* start including the parameters as local macros */ while (htmlMarkup->attrib != NULL) { attrib = htmlMarkup->attrib; /* varstore inherits the name and value from attribute. */ flag = VAR_FLAG_DEALLOC_NAME | VAR_FLAG_DEALLOC_VALUE; if (!attrib->value) { attrib->value = ""; flag &= ~VAR_FLAG_DEALLOC_VALUE; } if (StoreVariable(&varstore, attrib->name, attrib->value, VAR_TYPE_SET_MACRO, flag | VAR_FLAG_DEALLOC_NAME | VAR_FLAG_DEALLOC_VALUE, NULL, NULL) == FALSE) { HtpMsg(MSG_ERROR, task->infile, "unable to add variable to context for include file"); CloseStream(&incfile); DestroyVariableStore(&varstore); return MARKUP_ERROR; } if (attrib->whitespace) FreeMemory(attrib->whitespace); /* unlink attrib */ htmlMarkup->attrib = attrib->next; FreeMemory(attrib); } /* push this onto the context and use it for the include file */ PushVariableStoreContext(task->varstore, &varstore); topVarstore = &varstore; } else { topVarstore = task->varstore; } /* build a new task structure */ newTask.infile = &incfile; newTask.outfile = task->outfile; newTask.varstore = topVarstore; newTask.sourceFilename = task->sourceFilename; /* informational message for the user */ HtpMsg(MSG_INFO, task->infile, "including file \"%s\"", fullPathname); /* process the new input file */ result = ProcessTask(&newTask); if (!result) { /* Error message was already spitted out. However, we * should give a hint where the meta-tag was called. */ HtpMsg(MSG_ERROR, task->infile, "... in file included here"); } /* pop the local context */ if(topVarstore == &varstore) { assert(topVarstore->child == NULL); PopVariableStoreContext(topVarstore); DestroyVariableStore(&varstore); } CloseStream(&incfile); /* if the new file did not process, return an error, otherwise discard */ /* the markup */ return (result == TRUE) ? DISCARD_MARKUP : MARKUP_ERROR; } uint FileProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext) { HTML_ATTRIBUTE *attrib; BOOL result; if ((attrib = UnlinkAttributeInMarkup(htmlMarkup, "EXECUTE")) != NULL) { result = FileExecuteProcessor(task, attrib, htmlMarkup); DestroyAttribute(attrib); FreeMemory(attrib); } else if ((attrib = UnlinkAttributeInMarkup(htmlMarkup, "TEMPLATE")) != NULL) { result = FileTemplateProcessor(task, attrib); DestroyAttribute(attrib); FreeMemory(attrib); } else if ((attrib = UnlinkAttributeInMarkup(htmlMarkup, "INCLUDE")) != NULL) { result = FileIncludeProcessor(task, attrib->value, htmlMarkup); DestroyAttribute(attrib); FreeMemory(attrib); } else if ((attrib = UnlinkAttributeInMarkup(htmlMarkup, "SEARCH")) != NULL) { /* set the include search path to what was specified */ if(attrib->value != NULL) { StringCopy(searchPath, attrib->value, SEARCH_PATH_SIZE); } else { /* search path is cleared */ searchPath[0] = NUL; } result = DISCARD_MARKUP; DestroyAttribute(attrib); FreeMemory(attrib); } else if ((attrib = UnlinkAttributeInMarkup(htmlMarkup, "NAME")) != NULL) { /* if a NAME attribute is found, and it contains a value, use * the ExternalFileProcessor to create the plaintext (this * function only reports output file's time, date, name) */ if (attrib->value != NULL) { result = ExternalFileProcessor(task, htmlMarkup, attrib->value, newPlaintext); } else { /* should be repleaced by output file name */ *newPlaintext = DuplicateString(task->outfile->name); HtpMsg(MSG_INFO, task->outfile, "adding output filename"); result = NEW_MARKUP; } DestroyAttribute(attrib); FreeMemory(attrib); } else { /* Invoke ExternalFileProcessor on current input file, to * handle TIME, DATE attributes */ result = ExternalFileProcessor(task, htmlMarkup, task->sourceFilename, newPlaintext); } if (result != MARKUP_ERROR && htmlMarkup->attrib != NULL) { HtpMsg(MSG_WARNING, task->infile, "Unhandled %s attribute in %s markup", htmlMarkup->attrib->name, htmlMarkup->tag); } /* the new plaintext has been created */ return result; } uint OutputProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext) { STREAM outputfile; HTML_ATTRIBUTE *attrib; BOOL append, expand, result; UNREF_PARAM(newPlaintext); /* get the filename to include */ if ((attrib = UnlinkAttributeInMarkup(htmlMarkup, "FILE")) == NULL) { HtpMsg(MSG_ERROR, task->infile, "output filename not specified"); return MARKUP_ERROR; } append = UnlinkBoolAttributeInMarkup(htmlMarkup, "APPEND"); expand = UnlinkBoolAttributeInMarkup(htmlMarkup, "EXPAND"); if (htmlMarkup->attrib != NULL) { HtpMsg(MSG_WARNING, task->infile, "Unhandled %s attribute in %s markup", htmlMarkup->attrib->name, htmlMarkup->tag); } /* open the output file */ if(CreateFileWriter(&outputfile, attrib->value, append) == FALSE) { HtpMsg(MSG_ERROR, task->infile, "unable to open output file \"%s\"", attrib->value); return MARKUP_ERROR; } DestroyAttribute(attrib); FreeMemory(attrib); result = ReadBlockToFile(task, expand, htmlMarkup->tag, &outputfile); FreeMemory((char *) outputfile.name); CloseStream(&outputfile); return result == FALSE ? MARKUP_ERROR : DISCARD_MARKUP; } htp-1.19/src/snprintf.h0000664000175000017500000000170612525674213015213 0ustar hoenickehoenicke#ifndef _PORTABLE_SNPRINTF_H_ #define _PORTABLE_SNPRINTF_H_ #define PORTABLE_SNPRINTF_VERSION_MAJOR 2 #define PORTABLE_SNPRINTF_VERSION_MINOR 2 #ifdef HAVE_SNPRINTF #include #else extern int snprintf(char *, size_t, const char *, /*args*/ ...); extern int vsnprintf(char *, size_t, const char *, va_list); #endif #if defined(HAVE_SNPRINTF) && defined(PREFER_PORTABLE_SNPRINTF) extern int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/ ...); extern int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap); #define snprintf portable_snprintf #define vsnprintf portable_vsnprintf #endif #ifdef NEED_ASPRINTF extern int asprintf (char **ptr, const char *fmt, /*args*/ ...); extern int vasprintf (char **ptr, const char *fmt, va_list ap); extern int asnprintf (char **ptr, size_t str_m, const char *fmt, /*args*/ ...); extern int vasnprintf(char **ptr, size_t str_m, const char *fmt, va_list ap); #endif #endif htp-1.19/src/png.c0000664000175000017500000000420012525674213014117 0ustar hoenickehoenicke/* // // png.c // // PNG (Portable Network Graphics) support functions // // By Rev. Bob, 1999 - derived from gif.c by Jim Nelson // // gif.c Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #include "htp.h" BOOL PngFormatFound(FILE *file) { BYTE header[8]; /* move to BOF */ if(fseek(file, 0, SEEK_SET) != 0) { DEBUG_PRINT(("unable to seek to start of PNG file")); return FALSE; } /* read first eight bytes, looking for PNG header + version info */ if(fread(header, 1, 8, file) != 8) { DEBUG_PRINT(("could not read PNG image file header")); return FALSE; } /* is this a PNG file? */ if(memcmp(header, "\211PNG\r\n\032\n", 8) == 0) { if(fseek(file, 12, SEEK_SET) != 0) { DEBUG_PRINT(("unable to seek to IHDR block of PNG file")); return FALSE; } if(fread(header, 1, 4, file) != 4) { DEBUG_PRINT(("could not read PNG image IHDR signature")); return FALSE; } if(memcmp(header, "IHDR", 4) == 0) { /* PNG signature and IHDR block found, must be good */ return TRUE; } } /* not a PNG file */ return FALSE; } /* Modify parms here and in png.h - must use 4-byte integers! */ BOOL PngReadDimensions(FILE *file, DWORD *height, DWORD *width) { /* PNG uses MSB LSB (B3 B2 B1 B0) notation - most significant first */ BYTE buff[8]; /* move to the image size position (+16) in the file header */ if(fseek(file, 16, SEEK_SET) != 0) { DEBUG_PRINT(("unable to seek to start of PNG file")); return FALSE; } /* read the width and height, byte by byte */ /* this gets around machine endian problems while retaining the */ /* fact that PNG uses MSB LSB (big-endian) notation */ if(fread(buff, 1, 8, file) != 8) { return FALSE; } *width = MAKE_DWORD(buff[0], buff[1], buff[2], buff[3]); *height = MAKE_DWORD(buff[4], buff[5], buff[6], buff[7]); return TRUE; } htp-1.19/src/file-proc.h0000664000175000017500000000153512525674213015230 0ustar hoenickehoenicke/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* // // -proc.h // // specialized markup processors // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #ifndef FILE_PROC_H #define FILE_PROC_H #include "defs.h" /* uint ExternalFileProcessor(TASK *task, HTML_MARKUP *htmlMarkup, const char *externalName, char **newPlaintext); uint FileExecuteProcessor(TASK *task, HTML_MARKUP *htmlMarkup); uint FileTemplateProcessor(TASK *task, HTML_MARKUP *htmlMarkup); uint FileIncludeProcessor(TASK *task, HTML_MARKUP *htmlMarkup); */ uint FileProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext); uint OutputProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext); #endif htp-1.19/src/util.c0000664000175000017500000001544612525674213014326 0ustar hoenickehoenicke/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* // // util.c // // common functions // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #include "defs.h" /* // // generic, global utility functions // */ /* // returns the markup type flag ... either the closing or opening delimiter // in the markup can be passed in */ uint MarkupType(char delim) { uint markupType; markupType = 0; if((delim == HTML_OPEN_MARKUP) || (delim == HTML_CLOSE_MARKUP)) { markupType |= MARKUP_TYPE_HTML; } if((delim == htpOpenMarkup) || (delim == htpCloseMarkup)) { markupType |= MARKUP_TYPE_HTP; } return markupType; } #ifndef HAVE_PIPE /* // temporary file name generator */ BOOL CreateTempFilename(char *tempfilename, uint size) { static char *tempDir; char *tmpName; assert(tempfilename != NULL); /* find a preferred temporary directory if not found already */ if(tempDir == NULL) { if((tempDir = getenv("TEMP")) == NULL) { if((tempDir = getenv("TMP")) == NULL) { tempDir = DIR_CURRENT_STRING; } } } /* get a temporary filename */ if((tmpName = tempnam(tempDir, (char *) PROGRAM_NAME)) != NULL) { /* copy the filename to the callers buffer */ StringCopy(tempfilename, tmpName, size); /* free the tempnam buffer and return success */ free(tmpName); return TRUE; } return FALSE; } #endif #if 0 /* // extract directory from a filename, if present */ char *GetFileDirectory(const char *filename, char *directory, uint size) { const char *filePtr; uint len; *directory = NUL; len = strlen(filename); if(len == 0) { return directory; } filePtr = filename + len - 1; while(filePtr != filename) { if(*filePtr == DIR_DELIMITER) { return StringCopy(directory, filename, (len <= size) ? len : size); } filePtr--; len--; } return directory; } #endif /* // ParseFilename // // Returns a pointer to the filename in a full pathname */ const char *FindFilename(const char *pathname) { const char *filePtr; uint len; assert(pathname != NULL); if(pathname == NULL) { return NULL; } len = strlen(pathname); if(len == 0) { return pathname; } filePtr = pathname + len - 1; while(filePtr != pathname) { if(strchr(ALL_FILESYSTEM_DELIMITERS, *filePtr) != NULL) { /* found the first delimiter, return pointer to character just */ /* past this one */ /* if pathname ended in a delimiter, then this will return a */ /* pointer to NUL, which is acceptable */ return filePtr + 1; } filePtr--; } return pathname; } /* // safe strncpy() wrapper (suggested by joseph.dandrea@att.com) ... strncpy() // by itself has some ugly problems, and strcpy() is simply dangerous. // Joseph recommended a macro, but I'm sticking to the bulkier solution of // using a function */ char *StringCopy(char *dest, const char *src, uint size) { assert(dest != NULL); assert(src != NULL); strncpy(dest, src, size); dest[size - 1] = NUL; return dest; } /* // re-entrant string tokenizer ... used because option.c requires simultaneous // uses of strtok(), and the standard version just dont cut it */ char *StringFirstToken(FIND_TOKEN *findToken, char *string, const char *tokens) { char *ptr; assert(string != NULL); assert(findToken != NULL); findToken->tokens = tokens; findToken->lastChar = string + strlen(string); findToken->nextStart = findToken->lastChar; if(tokens == NULL) { return string; } if((ptr = strpbrk(string, tokens)) != NULL) { *ptr = NUL; findToken->nextStart = ptr; } return string; } char *StringNextToken(FIND_TOKEN *findToken) { char *ptr; char *start; assert(findToken != NULL); assert(findToken->lastChar != NULL); ptr = findToken->nextStart; /* check if this is the end of the original string */ if(ptr == findToken->lastChar) { return NULL; } /* nextStart points to NUL left by last search, skip past it */ ptr++; start = ptr; /* keep going */ if((ptr = strpbrk(ptr, findToken->tokens)) != NULL) { *ptr = NUL; findToken->nextStart = ptr; } else { findToken->nextStart = findToken->lastChar; } return start; } /* // Wrapper function to (a) allocate memory for the duplicated string and // (b) copy the source string into the new memory location. Caller is // responsible to free the string eventually. */ char *DuplicateString(const char *src) { char *new; uint size; assert(src != NULL); size = strlen(src) + 1; /* allocate memory for the duplicate string */ if((new = AllocMemory(size)) == NULL) { return NULL; } /* copy the string */ return memcpy(new, src, size); } /* // Like DuplicateString, but only duplicate a sub string of length len. // The substring is NUL terminated. */ char *DuplicateSubString(const char *src, int len) { char *new; uint size; assert(src != NULL && len <= strlen(src)); size = len + 1; /* allocate memory for the duplicate string */ if((new = AllocMemory(size)) == NULL) { return NULL; } /* copy the string */ memcpy(new, src, len); new[len] = 0; return new; } /* // converts directory delimiters for any pathname into one supporting the // delimiters used by the present filesystem ... it is encumbent on the // caller to free() the string returned once finished */ char *ConvertDirDelimiter(const char *pathname) { char *newPathname; char *strptr; if(pathname == NULL) { return NULL; } /* duplicate the pathname for conversion */ if((newPathname = DuplicateString(pathname)) == NULL) { return NULL; } /* walk the string, looking for delimiters belonging to other filesystems */ /* replace with native filesystems delimiter */ strptr = newPathname; while(*strptr != NUL) { if(strchr(OTHER_FILESYSTEM_DELIMITER, *strptr) != NULL) { *strptr = DIR_DELIMITER; } strptr++; } return newPathname; } /* // uses stat() to check for file existance ... maybe not the best way? */ BOOL FileExists(const char *pathname) { struct stat dummy; return (stat(pathname, &dummy) == 0) ? TRUE : FALSE; } #ifndef HAVE_STPCPY char *stpcpy(char *d, const char *s) { do { *d++ = *s; } while (*s++); return d-1; } #endif htp-1.19/src/use-proc.h0000664000175000017500000000067112525674213015105 0ustar hoenickehoenicke/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* // // use-proc.h // // specialized markup processors // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #ifndef USE_PROC_H #define USE_PROC_H #include "defs.h" uint UseProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext); #endif htp-1.19/src/png.h0000664000175000017500000000056112525674213014132 0ustar hoenickehoenicke/* // // png.h // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #ifndef PNG_H #define PNG_H /* PNG format detected? */ BOOL PngFormatFound(FILE *file); /* get image dimensions */ BOOL PngReadDimensions(FILE *file, DWORD *height, DWORD *width); #endif htp-1.19/src/misc-proc.h0000664000175000017500000000140112525674213015234 0ustar hoenickehoenicke/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* // // misc-proc.h // // specialized markup processors // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #ifndef MISC_PROC_H #define MISC_PROC_H #include "defs.h" uint HeadProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext); uint QuoteProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext); uint HtpCommentProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext); uint ConditionalWarning(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext); uint PreProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext); #endif htp-1.19/src/def-proc.h0000664000175000017500000000174312525674213015050 0ustar hoenickehoenicke/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* // // def-proc.h // // specialized markup processors // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #ifndef DEF_PROC_H #define DEF_PROC_H #include "defs.h" /* Reads in a block and puts it into a temporary file. The name of * the temporary file is put into newFilename, which must be able to hold * MAX_PATHNAME_LEN characters. */ void BlockDestructor(const char *name, void *value, uint type, uint flags, void *param); BOOL ReadBlockToFile(TASK *task, BOOL expand, const char *tag, STREAM *blockStream); BOOL ReadinBlock(TASK *task, HTML_MARKUP *htmlMarkup, STREAM *blockStream); uint BlockProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext); uint UndefProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext); #endif htp-1.19/src/streams.c0000664000175000017500000002017112525674213015016 0ustar hoenickehoenicke/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* // // $Id: streams.c,v 1.14 2006-06-12 13:41:33 hoenicke Exp $ // // file/buffer stream functions // // Copyright (c) 2001 Jochen Hoenicke under Artistic License. // */ #include "htp.h" #include "snprintf.h" BOOL CreateNullWriter (STREAM* stream) { stream->sflags = STREAM_FLAG_NULL_FILE; stream->name = "NULL"; stream->lineNumber = 1; return TRUE; } BOOL CreateBufferWriter (STREAM* stream, const char *name) { stream->sflags = STREAM_FLAG_BUFFER; stream->u.buffer.length = 128; stream->u.buffer.buffer = AllocMemory(stream->u.buffer.length); stream->u.buffer.offset = 0; if (stream->u.buffer.buffer == NULL) { HtpMsg(MSG_ERROR, NULL, "unable to allocate stream buffer"); return FALSE; } return TRUE; } BOOL CreateBufferReader (STREAM* stream, STREAM *writeStream) { if (writeStream->sflags != STREAM_FLAG_BUFFER) { HtpMsg(MSG_ERROR, NULL, "CreateBufferReader: wrong buffer type"); return FALSE; } stream->sflags = STREAM_FLAG_BUFFER | STREAM_FLAG_READER; stream->name = writeStream->name; stream->lineNumber = writeStream->lineNumber; stream->u.buffer.length = writeStream->u.buffer.offset; stream->u.buffer.buffer = writeStream->u.buffer.buffer; stream->u.buffer.offset = 0; stream->hasUnread = FALSE; return TRUE; } BOOL FlushBufferWriter (STREAM *stream) { char *str; if (stream->sflags != STREAM_FLAG_BUFFER) { HtpMsg(MSG_ERROR, NULL, "CreateBufferReader: wrong buffer type"); return FALSE; } str = AllocMemory(stream->u.buffer.offset + 1); memcpy(str, stream->u.buffer.buffer, stream->u.buffer.offset); str[stream->u.buffer.offset] = 0; FreeMemory(stream->u.buffer.buffer); stream->u.buffer.buffer = str; return TRUE; } BOOL CreateFileReader (STREAM *stream, const char *filename) { stream->sflags = STREAM_FLAG_READER; stream->name = filename; stream->lineNumber = 1; stream->hasUnread = FALSE; return OpenFile(filename, "r", &stream->u.textfile); } BOOL CreateFDReader (STREAM *stream, const char *filename, int filedes) { stream->sflags = STREAM_FLAG_READER; stream->name = filename; stream->lineNumber = 1; stream->hasUnread = FALSE; return OpenFD(filedes, "r", &stream->u.textfile); } BOOL CreateFileWriter (STREAM *stream, const char *filename, BOOL append) { stream->sflags = 0; stream->name = filename; stream->lineNumber = 1; return OpenFile(filename, append ? "a" : "w", &stream->u.textfile); } void CloseStream (STREAM *stream) { if ((stream->sflags & STREAM_FLAG_BUFFER)) { if (!(stream->sflags & STREAM_FLAG_READER)) { FreeMemory(stream->u.buffer.buffer); FreeMemory((void *)stream->name); } } else if ((stream->sflags & STREAM_FLAG_NULL_FILE)) { /* nothing */ } else { CloseFile(&stream->u.textfile); } } BOOL GetStreamChar(STREAM *stream, char *c) { assert(stream != NULL); assert((stream->sflags & STREAM_FLAG_READER)); assert(stream->u.buffer.buffer != NULL); if (stream->hasUnread) { *c = stream->unread; stream->hasUnread = FALSE; return TRUE; } if ((stream->sflags & STREAM_FLAG_BUFFER)) { /* Check for EOF */ if (stream->u.buffer.length <= stream->u.buffer.offset) return FALSE; *c = stream->u.buffer.buffer[stream->u.buffer.offset++]; if (*c == '\n') stream->lineNumber++; return TRUE; } else { BOOL result = GetFileChar(&stream->u.textfile, c); if (*c == '\n') stream->lineNumber++; return result; } } BOOL UnreadStreamChar(STREAM *stream, char c) { assert(stream != NULL); assert((stream->sflags & STREAM_FLAG_READER)); assert(stream->u.buffer.buffer != NULL); assert(!stream->hasUnread); stream->hasUnread = TRUE; stream->unread = c; return TRUE; } uint GetStreamBlock(STREAM *stream, char *buffer, uint size, char delim[3]) { char *ptr, ch; int read = 0; assert(stream != NULL); assert((stream->sflags & STREAM_FLAG_READER)); assert(buffer != NULL); if (stream->hasUnread) { *buffer++ = ch = stream->unread; size--; stream->hasUnread = FALSE; if (ch == delim[0] || ch == delim[1]) return 1; read = 1; } if ((stream->sflags & STREAM_FLAG_BUFFER)) { char * end = stream->u.buffer.buffer + stream->u.buffer.length; char * start = stream->u.buffer.buffer + stream->u.buffer.offset; /* Check for EOF */ if (start >= end) return FALSE; /* leave space for trailing NUL. */ size--; if (start + size < end) end = start + size; /* Search for new line. */ ptr = start; while (ptr < end) { *buffer++ = ch = *ptr++; if (ch == '\n') stream->lineNumber++; if (ch == delim[0] || ch == delim[1] || ch == delim[2]) break; } *buffer = 0; stream->u.buffer.offset += ptr - start; return read + ptr - start; } else { if(feof(stream->u.textfile.file)) return FALSE; ptr = buffer; /* compare size to 1 rather than 0 to leave room for trailing NUL */ while(size-- > 1) { if(GetFileChar(&stream->u.textfile, ptr) == FALSE) { break; } ch = *ptr; if(ch == '\n') { stream->lineNumber++; } ptr++; if (ch == delim[0] || ch == delim[1] || ch == delim[2]) break; } *ptr = 0; return read + ptr - buffer; } } BOOL PutStreamString(STREAM *stream, const char *str) { /* check the arguments */ assert(stream != NULL); assert(!(stream->sflags & STREAM_FLAG_READER)); if ((stream->sflags & STREAM_FLAG_BUFFER)) { ulong len = strlen(str); ulong free = stream->u.buffer.length - stream->u.buffer.offset; if (len > free) { char * newbuffer; while (len > free) { free += stream->u.buffer.length; stream->u.buffer.length *= 2; } newbuffer = ResizeMemory(stream->u.buffer.buffer, stream->u.buffer.length); if (newbuffer == NULL) { /* unable to enlarge buffer area */ HtpMsg(MSG_ERROR, NULL, "unable to grow stream buffers"); return FALSE; } stream->u.buffer.buffer = newbuffer; } memcpy (stream->u.buffer.buffer + stream->u.buffer.offset, str, len); stream->u.buffer.offset += len; return TRUE; } else if ((stream->sflags & STREAM_FLAG_NULL_FILE)) { return TRUE; } else { return PutFileString(&stream->u.textfile, str); } } BOOL StreamPrintF(STREAM *stream, const char *format, ...) { va_list argptr; /* reserve room to hold the final string ... allocating 4K works * most time. If that isn't enough, we reallocate later. */ char buffer[4*KBYTE]; char *str = buffer; int len; /* convert formatted arguments into single string */ va_start(argptr, format); len = vsnprintf(str, sizeof(buffer), format, argptr); va_end(argptr); if (len > sizeof(buffer) - 1) { str = AllocMemory(len + 1); va_start(argptr, format); len = vsnprintf(str, len + 1, format, argptr); va_end(argptr); } len = PutStreamString(stream, str); if (str != buffer) FreeMemory(str); return len; } void ForceLinefeeds(STREAM *stream, BOOL forced) { if (!(stream->sflags & (STREAM_FLAG_BUFFER | STREAM_FLAG_NULL_FILE))) { if (forced) stream->u.textfile.flags |= TEXTFILE_FLAG_FORCE_CR; else stream->u.textfile.flags &= ~TEXTFILE_FLAG_FORCE_CR; } } htp-1.19/src/jpeg.h0000664000175000017500000000063512525674213014275 0ustar hoenickehoenicke/* // // jpeg.h // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #ifndef JPEG_H #define JPEG_H /* is this a JPEG File Interchange Format (JFIF) file? */ BOOL JpegFormatFound(FILE *file); /* one-shot-does-it-all function */ BOOL JpegReadDimensions(FILE *file, DWORD *height, DWORD *width); #endif htp-1.19/src/suballoc.c0000664000175000017500000004073012525674213015147 0ustar hoenickehoenicke/* // // suballoc.c // // Memory suballocation // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #include "htp.h" #ifdef USE_SUBALLOC /* // performance counters */ #if DEBUG uint freePoolHits = 0; uint totalAllocations = 0; #endif /* // pattern used to clear memory on allocation and free */ #define SUBALLOC_ALLOC_BYTE (0xA5) #define SUBALLOC_FREE_BYTE (0x5A) /* // each memory allocation has a small header, which is used by // this module alone */ #define SUBALLOC_MAX_HEADER_FILE_SIZE (16) typedef struct tagSUBALLOC_HEADER { struct tagSUBALLOC_HEADER *next; struct tagSUBALLOC_HEADER *prev; char file[SUBALLOC_MAX_HEADER_FILE_SIZE]; uint line; uint allocSize; uint userSize; DWORD signature; } SUBALLOC_HEADER; #define SUBALLOC_SIGNATURE (0xFEA55AEF) #define SUBALLOC_END_SIGNATURE (0xA5EFFE5A) /* // the memory pool is kept on a doubly-linked list */ typedef struct tagSUBALLOC_POOL { SUBALLOC_HEADER *head; SUBALLOC_HEADER *tail; uint totalMemorySize; } SUBALLOC_POOL; SUBALLOC_POOL freePool; SUBALLOC_POOL reservedPool; /* // memory pool functions */ void InitializePool(SUBALLOC_POOL *pool) { assert(pool != NULL); pool->head = NULL; pool->tail = NULL; pool->totalMemorySize = 0; } SUBALLOC_HEADER *PointerToHeader(void *ptr) { assert(ptr != NULL); return (SUBALLOC_HEADER *) (((BYTE *) ptr) - sizeof(SUBALLOC_HEADER)); } void *GetUserBuffer(SUBALLOC_HEADER *header) { /* cant assert good header, this function might be used during its */ /* construction */ assert(header != NULL); return ((BYTE *) header) + sizeof(SUBALLOC_HEADER); } BOOL IsHeaderOkay(SUBALLOC_HEADER *header) { if(header == NULL) { DebugMsg("IsHeaderOkay: NULL header\n"); return FALSE; } /* check head signature */ if(header->signature != SUBALLOC_SIGNATURE) { DebugMsg("IsHeaderOkay: bad start signature, file %s line %u\n", header->file, header->line); return FALSE; } return TRUE; } void SetEndSignature(SUBALLOC_HEADER *header) { BYTE *startSignature; static DWORD endSignature = SUBALLOC_END_SIGNATURE; assert(header != NULL); /* find the first byte of the area beyond the user-allocated buffer */ startSignature = (BYTE *) header + sizeof(SUBALLOC_HEADER) + header->userSize; /* since some machines don't like misaligned accesses, copy the signature */ /* in byte by byte */ memcpy(startSignature, &endSignature, sizeof(DWORD)); } BOOL IsEndSignatureOkay(SUBALLOC_HEADER *header) { BYTE *startSignature; static DWORD endSignature = SUBALLOC_END_SIGNATURE; assert(header != NULL); /* find the first byte beyond the user-allocated buffer */ startSignature = (BYTE *) header + sizeof(SUBALLOC_HEADER) + header->userSize; /* since some machines don't like misaligned accessed, compare the */ /* signature byte by byte */ return (memcmp(startSignature, &endSignature, sizeof(DWORD)) == 0) ? TRUE : FALSE; } SUBALLOC_HEADER *CreatePoolElement(uint size) { SUBALLOC_HEADER *header; uint allocSize; #if SUBALLOC_MINALLOCSIZE allocSize = (size < SUBALLOC_MINALLOCSIZE) ? SUBALLOC_MINALLOCSIZE : size; #else allocSize = size; #endif /* allocate header, end signature, and user buffer */ if((header = malloc(allocSize + sizeof(SUBALLOC_HEADER) + sizeof(DWORD))) == NULL) { return NULL; } #if DEBUG header->next = (void *) 0x12345678; header->prev = (void *) 0x12345678; #endif /* set up as much of the header as possible */ header->allocSize = allocSize; header->userSize = size; header->signature = SUBALLOC_SIGNATURE; #if SUBALLOC_CLEARMEM memset(GetUserBuffer(header), SUBALLOC_ALLOC_BYTE, allocSize); #endif /* set the end signature */ SetEndSignature(header); assert(IsHeaderOkay(header) == TRUE); assert(IsEndSignatureOkay(header) == TRUE); return header; } void FreePoolElement(SUBALLOC_HEADER *header) { assert(IsHeaderOkay(header) == TRUE); #if SUBALLOC_CLEARMEM memset(GetUserBuffer(header), SUBALLOC_FREE_BYTE, header->allocSize); #endif free(header); } SUBALLOC_HEADER *ResizePoolElement(SUBALLOC_HEADER *header, uint newSize) { uint allocSize; SUBALLOC_HEADER *newHeader; assert(IsHeaderOkay(header) == TRUE); assert(newSize != 0); #if SUBALLOC_MINALLOCSIZE allocSize = (newSize < SUBALLOC_MINALLOCSIZE) ? SUBALLOC_MINALLOCSIZE : newSize; #else allocSize = newSize; #endif /* it COULD already be this size */ if(header->allocSize >= allocSize) { header->userSize = newSize; SetEndSignature(header); assert(IsHeaderOkay(header) == TRUE); assert(IsEndSignatureOkay(header) == TRUE); return header; } newHeader = realloc(header, newSize + sizeof(SUBALLOC_HEADER) + sizeof(DWORD)); if(newHeader == NULL) { /* couldnt resize block */ return NULL; } #if DEBUG newHeader->prev = (void *) 0x12345678; newHeader->next = (void *) 0x12345678; #endif /* fill in the new header */ newHeader->userSize = newSize; newHeader->allocSize = allocSize; newHeader->signature = SUBALLOC_SIGNATURE; /* set the end signature */ SetEndSignature(newHeader); assert(IsHeaderOkay(newHeader) == TRUE); assert(IsEndSignatureOkay(newHeader) == TRUE); return newHeader; } void AddPoolElement(SUBALLOC_POOL *pool, SUBALLOC_HEADER *header) { assert(pool != NULL); assert(IsHeaderOkay(header) == TRUE); if(pool->head != NULL) { header->prev = pool->tail; pool->tail->next = header; } else { pool->head = header; header->prev = NULL; } header->next = NULL; pool->tail = header; pool->totalMemorySize += header->allocSize; } SUBALLOC_HEADER *RemoveFirstElement(SUBALLOC_POOL *pool) { SUBALLOC_HEADER *header; assert(pool != NULL); if(pool->head == NULL) { return NULL; } header = pool->head; if((pool->head = header->next) != NULL) { pool->head->prev = NULL; } assert(pool->totalMemorySize >= header->allocSize); pool->totalMemorySize -= header->allocSize; assert(IsHeaderOkay(header) == TRUE); return header; } void RemoveElement(SUBALLOC_POOL *pool, SUBALLOC_HEADER *header) { assert(pool != NULL); assert(IsHeaderOkay(header) == TRUE); if(pool->head == header) { pool->head = header->next; if(pool->head != NULL) { pool->head->prev = NULL; } } else if(pool->tail == header) { pool->tail = header->prev; if(pool->tail != NULL) { pool->tail->next = NULL; } } else { header->prev->next = header->next; header->next->prev = header->prev; } assert(pool->totalMemorySize >= header->allocSize); pool->totalMemorySize -= header->allocSize; } SUBALLOC_HEADER *RemovePoolElementBySize(SUBALLOC_POOL *pool, uint size) { SUBALLOC_HEADER *curr; #if !SUBALLOC_FIRSTFIT SUBALLOC_HEADER *bestfit; uint bestfitDiff; uint currDiff; #endif assert(pool != NULL); assert(size != 0); #if !SUBALLOC_FIRSTFIT bestfit = NULL; bestfitDiff = UINT_MAX; #endif curr = pool->head; while(curr != NULL) { assert(IsHeaderOkay(curr) == TRUE); if(curr->allocSize < size) { /* too small */ curr = curr->next; continue; } #if SUBALLOC_FIRSTFIT /* found one, unlink from the list */ RemoveElement(pool, curr); #if SUBALLOC_DEBLOG DebugMsg("suballoc: first fit found block of %u bytes for alloc of %u bytes\n", curr->allocSize, size); #endif return curr; #else #if SUBALLOC_MINALLOCSIZE /* if the block is the minimum allocation size, then it is the */ /* best fit, by definition */ if(curr->allocSize == SUBALLOC_MINALLOCSIZE) { bestfit = curr; break; } #endif currDiff = curr->allocSize - size; if(currDiff == 0) { /* this is as good as it gets */ bestfit = curr; break; } if(currDiff < bestfitDiff) { bestfitDiff = currDiff; bestfit = curr; } curr = curr->next; #endif } #if !SUBALLOC_FIRSTFIT if(bestfit != NULL) { RemoveElement(pool, bestfit); #if SUBALLOC_DEBLOG DebugMsg("suballoc: best fit found block of %u bytes for alloc of %u bytes\n", bestfit->allocSize, size); #endif return bestfit; } #endif /* nothing was found */ return NULL; } BOOL RemovePoolElementByAddr(SUBALLOC_POOL *pool, SUBALLOC_HEADER *header) { SUBALLOC_HEADER *curr; assert(pool != NULL); assert(IsHeaderOkay(header) == TRUE); curr = pool->head; while(curr != NULL) { assert(IsHeaderOkay(curr) == TRUE); if(curr == header) { RemoveElement(pool, curr); return TRUE; } curr = curr->next; } return FALSE; } void RemoveLargestPoolElement(SUBALLOC_POOL *pool) { SUBALLOC_HEADER *curr; SUBALLOC_HEADER *largest; assert(pool != NULL); largest = NULL; /* walk the list, looking for the largest allocated block */ for(curr = pool->head; curr != NULL; curr = curr->next) { assert(IsHeaderOkay(curr) == TRUE); if(largest == NULL) { largest = curr; continue; } if(curr->allocSize > largest->allocSize) { largest = curr; continue; } } /* if one was found, remove it */ if(largest != NULL) { #if SUBALLOC_DEBLOG DebugMsg("removing largest buffer of %u bytes from pool of %u bytes\n", largest->allocSize, pool->totalMemorySize); #endif if(largest->prev != NULL) { largest->prev->next = largest->next; } if(largest->next != NULL) { largest->next->prev = largest->prev; } /* removed, so destroy it and account for it in the pool */ assert(pool->totalMemorySize >= largest->allocSize); pool->totalMemorySize -= largest->allocSize; FreePoolElement(largest); } } /* // public functions */ void InitializeMemory(void) { InitializePool(&freePool); InitializePool(&reservedPool); } void TerminateMemory(void) { SUBALLOC_HEADER *header; if(reservedPool.head != NULL) { #if SUBALLOC_DEBLOG DebugMsg("UNFREED MEMORY: %u bytes held in reserved pool\n", reservedPool.totalMemorySize); #endif #if SUBALLOC_WARNING printf("suballoc: %u bytes unfreed\n", reservedPool.totalMemorySize); #endif } #if SUBALLOC_DEBLOG DebugMsg("suballoc: %u bytes held in free pool\n", freePool.totalMemorySize); #endif while((header = RemoveFirstElement(&reservedPool)) != NULL) { assert(IsHeaderOkay(header) == TRUE); assert(IsEndSignatureOkay(header) == TRUE); #if SUBALLOC_DEBLOG DebugMsg("Removing reserved alloc for %u bytes from %s line %u\n", header->userSize, header->file, header->line); #endif FreePoolElement(header); } while((header = RemoveFirstElement(&freePool)) != NULL) { assert(IsHeaderOkay(header) == TRUE); /* dont check end signature, it is not valid in free pool */ #if SUBALLOC_DEBLOG DebugMsg("Removing free alloc for %u bytes from %s line %u\n", header->userSize, header->file, header->line); #endif FreePoolElement(header); } } void *_AllocMemory(uint size, const char *file, uint line) { SUBALLOC_HEADER *header; #if SUBALLOC_DEBLOG DebugMsg("Allocating %u bytes in file %s line %u\n", size, file, line); #endif #if DEBUG totalAllocations++; #endif if(size == 0) { #if SUBALLOC_DEBLOG DebugMsg("Allocation for 0 bytes in file %s line %u\n", file, line); #endif return NULL; } /* if buffer of sufficient size already in pool, use that one */ if((header = RemovePoolElementBySize(&freePool, size)) == NULL) { /* need to create a new pool item */ if((header = CreatePoolElement(size)) == NULL) { /* out of memory! */ #if SUBALLOC_DEBLOG DebugMsg("System heap out of memory! file %s line %u\n", file, line); #endif return NULL; } } else { #if DEBUG freePoolHits++; #endif } assert(IsHeaderOkay(header) == TRUE); /* replace the headers file and line with this new information */ if(file != NULL) { StringCopy(header->file, file, SUBALLOC_MAX_HEADER_FILE_SIZE); } else { header->file[0] = NUL; } header->line = line; header->userSize = size; /* set the end signature */ SetEndSignature(header); /* add the new suballoc to the reserved pool */ AddPoolElement(&reservedPool, header); assert(IsHeaderOkay(header) == TRUE); assert(IsEndSignatureOkay(header) == TRUE); return GetUserBuffer(header); } void _FreeMemory(void *ptr, const char *file, uint line) { SUBALLOC_HEADER *header; #if !SUBALLOC_DEBLOG UNREF_PARAM(file); UNREF_PARAM(line); #endif if(ptr == NULL) { #if SUBALLOC_DEBLOG DebugMsg("Tried to free NULL pointer in file %s line %u\n", file, line); #endif return; } header = (SUBALLOC_HEADER *) (((BYTE *) ptr) - sizeof(SUBALLOC_HEADER)); assert(IsHeaderOkay(header) == TRUE); assert(IsEndSignatureOkay(header) == TRUE); #if SUBALLOC_DEBLOG DebugMsg("Freeing %u bytes (%u alloced) in file %s line %u\n", header->userSize, header->allocSize, file, line); #endif if(RemovePoolElementByAddr(&reservedPool, header) == FALSE) { /* doh! */ HtpMsg(MSG_ERROR, NULL, "Fatal error: block of memory freed not in reserved pool, exiting ...\n"); exit(1); } #if SUBALLOC_CLEARMEM memset(GetUserBuffer(header), SUBALLOC_FREE_BYTE, header->allocSize); #endif /* move it back into the free pool */ AddPoolElement(&freePool, header); #if SUBALLOC_MAXFREEPOOLSIZE /* check to see that the free pool size hasnt grown too big */ while(freePool.totalMemorySize > SUBALLOC_MAXFREEPOOLSIZE) { RemoveLargestPoolElement(&freePool); } #endif } void *_ResizeMemory(void *ptr, uint newSize, const char *file, uint line) { SUBALLOC_HEADER *header; SUBALLOC_HEADER *newHeader; #if SUBALLOC_DEBLOG DebugMsg("Reallocing to new size of %u bytes in file %s line %u\n", newSize, file, line); #endif if((newSize == 0) && (ptr != NULL)) { /* treat as a free */ FreeMemory(ptr); return NULL; } if((ptr == NULL) && (newSize != 0)) { /* treat as an alloc */ return AllocMemory(newSize); } if((ptr == NULL) && (newSize == 0)) { /* treat as a dumbo programmer */ return NULL; } header = PointerToHeader(ptr); assert(IsHeaderOkay(header) == TRUE); assert(IsEndSignatureOkay(header) == TRUE); if(RemovePoolElementByAddr(&reservedPool, header) == FALSE) { /* oof */ HtpMsg(MSG_ERROR, NULL, "Fatal error: block of memory freed not in reserved pool, exiting ...\n"); exit(1); } /* resize memory buffer */ newHeader = ResizePoolElement(header, newSize); if(newHeader == NULL) { /* failed to resize */ AddPoolElement(&reservedPool, header); return NULL; } /* succeeded, fill in rest of header */ if(file != NULL) { StringCopy(newHeader->file, file, SUBALLOC_MAX_HEADER_FILE_SIZE); } else { newHeader->file[0] = NUL; } newHeader->line = line; /* add to reserve pool and return to user */ AddPoolElement(&reservedPool, newHeader); assert(IsHeaderOkay(newHeader) == TRUE); assert(IsEndSignatureOkay(newHeader) == TRUE); return GetUserBuffer(newHeader); } uint MemorySize(void *ptr) { SUBALLOC_HEADER *header; if(ptr == NULL) { return 0; } header = PointerToHeader(ptr); assert(IsHeaderOkay(header) == TRUE); if(IsHeaderOkay(header) == FALSE) { return 0; } return header->userSize; } #endif htp-1.19/src/while-proc.h0000664000175000017500000000067712525674213015427 0ustar hoenickehoenicke/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* // // while-proc.h // // specialized markup processors // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #ifndef WHILE_PROC_H #define WHILE_PROC_H #include "defs.h" uint WhileProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext); #endif htp-1.19/src/set-proc.c0000664000175000017500000001213012525674213015070 0ustar hoenickehoenicke/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* // // set-proc.c // // specialized markup processors // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #include "set-proc.h" #include "defs.h" #include "snprintf.h" uint SetProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext) { char *name; char *value; uint flag; HTML_ATTRIBUTE *attrib; VARSTORE *varstore; UNREF_PARAM(newPlaintext); varstore = task->varstore; if (UnlinkBoolAttributeInMarkup(htmlMarkup, "GLOBAL")) { while (!varstore->isGlobal) varstore = varstore->parent; } /* have to declare at least one macro, but more are acceptable */ if(htmlMarkup->attrib == NULL) { HtpMsg(MSG_ERROR, task->infile, "incomplete macro declaration"); return MARKUP_ERROR; } /* walk the list and add each macro to the variable store */ while ((attrib = htmlMarkup->attrib) != NULL) { name = attrib->name; value = attrib->value; flag = VAR_FLAG_DEALLOC_NAME | VAR_FLAG_DEALLOC_VALUE; if (!value) { value = ""; flag &= ~VAR_FLAG_DEALLOC_VALUE; } /* put the new variable into the store */ if(StoreVariable(varstore, name, value, VAR_TYPE_SET_MACRO, flag, NULL, NULL) == FALSE) { HtpMsg(MSG_ERROR, task->infile, "unable to store macro \"%s\" (out of memory?)", name); return MARKUP_ERROR; } HtpMsg(MSG_INFO, task->infile, "macro \"%s\" assigned value \"%s\"", name, value); if (attrib->whitespace) FreeMemory(attrib->whitespace); /* unlink attrib */ htmlMarkup->attrib = attrib->next; FreeMemory(attrib); } return DISCARD_MARKUP; } uint UnsetProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext) { HTML_ATTRIBUTE *attrib; uint type; UNREF_PARAM(newPlaintext); attrib = htmlMarkup->attrib; /* need at least one attribute to undef */ if(attrib == NULL) { HtpMsg(MSG_ERROR, task->infile, "UNDEF requires at least one name"); return MARKUP_ERROR; } /* walk the list of attributes, deleting them as found */ while (attrib != NULL) { /* is it in the store? */ type = GetVariableType(task->varstore, attrib->name); if((type == VAR_TYPE_SET_MACRO) || (type == VAR_TYPE_BLOCK_MACRO)) { RemoveVariable(task->varstore, attrib->name); } else { HtpMsg(MSG_ERROR, task->infile, "No macro \"%s\" to unset", attrib->name); return MARKUP_ERROR; } HtpMsg(MSG_INFO, task->infile, "macro \"%s\" unset", attrib->name); attrib = attrib->next; } return DISCARD_MARKUP; } uint IncProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext) { const char *expansion; char valueStr[MAX_INC_VALUE_LENGTH]; int value; HTML_ATTRIBUTE *attrib; VARSTORE *varstore; varstore = task->varstore; if (UnlinkBoolAttributeInMarkup(htmlMarkup, "GLOBAL")) { while (!varstore->isGlobal) varstore = varstore->parent; } attrib = htmlMarkup->attrib; while (attrib != NULL) { /* make sure variable exists in store */ if(VariableExists(task->varstore, attrib->name) != TRUE) { /* only a warning */ HtpMsg(MSG_ERROR, task->infile, "unrecognized macro name \"%s\"", attrib->name); return MARKUP_ERROR; } /* block macros cannot be increased */ if(GetVariableType(task->varstore, attrib->name) != VAR_TYPE_SET_MACRO) { HtpMsg(MSG_ERROR, task->infile, "\"%s\" is not a set macro.", attrib->name); return MARKUP_ERROR; } /* get the macro value and replace the attribute value */ expansion = GetVariableValue(varstore, attrib->name); if(expansion == NULL) { HtpMsg(MSG_WARNING, task->infile, "no value for macro \"%s\"", attrib->name); return MARKUP_ERROR; } value = atoi(expansion); if (attrib->value != NULL) { value += atoi(attrib->value); } else { value++; } snprintf(valueStr, MAX_INC_VALUE_LENGTH, "%i", value); if(UpdateVariableValue(task->varstore, attrib->name, DuplicateString(valueStr)) == FALSE) { HtpMsg(MSG_WARNING, task->infile, "new value %s for macro \"%s\" could not be stored.", valueStr, attrib->name); return MARKUP_ERROR; } HtpMsg(MSG_INFO, task->infile, "incrementing macro \"%s\" to %s", attrib->name, valueStr); attrib = attrib->next; } return DISCARD_MARKUP; } htp-1.19/src/Makefile.sub0000664000175000017500000000331612525674213015426 0ustar hoenickehoenicke# # makefile - htp # # HTML pre-processor # Copyright (c) 2002 Jochen Hoenicke # p$(dir) := $(d) d := $(dir) ################# # # object files used # SRC$(d) := htp.c bool-proc.c def-proc.c defs.c file-proc.c gif.c html.c \ htp-files.c image-proc.c image.c jpeg.c macro.c misc-proc.c msg.c \ option.c png.c set-proc.c snprintf.c streams.c suballoc.c textfile.c \ use-proc.c util.c varstore.c ver.c while-proc.c HEADERS$(d) := bool-proc.h def-proc.h defs.h file-proc.h gif.h html.h \ htp-files.h htp.h image-proc.h image.h jpeg.h macro.h misc-proc.h \ msg.h option.h os.h png.h set-proc.h snprintf.h streams.h suballoc.h \ textfile.h use-proc.h varstore.h ver.h while-proc.h SRC$(d) := $(SRC$(d):%=$(d)/%) HEADERS$(d) := $(HEADERS$(d):%=$(d)/%) OBJ$(d) := $(SRC$(d):%.c=%.$(OBJEXT)) HTP := $(d)/$(MAIN)$(EXEEXT) DISTDIRS += $(d) DISTFILES += $(d)/Makefile.sub $(SRC$(d)) $(HEADERS$(d)) $(d)/LICENSE.txt CLEAN += $(d)/*~ $(d)/*.obj $(d)/*.o $(d)/version.inc $(HTP) all: $(HTP) $(d)/version.inc: force @echo '#define VER_STRING "$(FULLVERSION)"' > $@.tmp @echo '#define PROGRAM_NAME "$(MAIN)"' >> $@.tmp -@if ! cmp -s $@.tmp $@; \ then mv $@.tmp $@; \ echo Updated version number; \ else rm $@.tmp; fi .PHONY: install-bin install: install-bin install-bin: $(HTP) mkdir -p $(bindir) $(INSTALL) -s $(HTP) $(bindir) # # explicit dependency: final executable # $(HTP) : $(OBJ$(d)) $(LINK) -o $@ $^ $(LOPT) # # implicit dependencies for source code # $(OBJ$(d)) : %.$(OBJEXT) : %.c ifdef WIN32DMC cd $(dir $<); $(CC) $(CCOPT) $(DEFINES) $(notdir $<) else $(CC) $(CCOPT) $(DEFINES) -o $*.$(OBJEXT) $< endif $(d)/htp.$(OBJEXT) $(d)/ver.$(OBJEXT): $(d)/version.inc # restore parent dir d := $(p$(d)) htp-1.19/src/os.h0000664000175000017500000000523012525674213013765 0ustar hoenickehoenicke/* // // os.h // // Operating system definitions and constants // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #ifndef OS_H #define OS_H #if __MSDOS__ #define PROGRAM_OS ("DOS") /* // this section should (but is not guaranteed) to conform to most MS-DOS // compilers */ #include /* not defined in the standard include files */ typedef unsigned int uint; typedef unsigned long ulong; /* directory delimiters */ #define DIR_DELIMITER '\\' #define DIR_DELIMITER_STRING "\\" #define DIR_CURRENT_STRING ".\\" /* the "other" filesystem delimiter table (for conversion) */ #define OTHER_FILESYSTEM_DELIMITER "/" /* DOS filesystem does not support pathnames beyond 64 characters (!!) */ #define MAX_PATHNAME_LEN (64) #define MAX_CMDLINE_LEN (128) #define MAX_FILENAME_LEN (13) #elif defined(__WIN32__) || defined(_WIN32) #define PROGRAM_OS ("Win32") /* // this section specifically designed for Microsoft Visual C++ 4.0 */ #include /* not defined in the standard include files */ typedef unsigned int uint; typedef unsigned long ulong; /* directory delimiters */ #define DIR_DELIMITER '\\' #define DIR_DELIMITER_STRING "\\" #define DIR_CURRENT_STRING ".\\" /* the "other" filesystem delimiter table (for conversion) */ #define OTHER_FILESYSTEM_DELIMITER "/" /* Win32 filesystem supports long filenames! */ #define MAX_PATHNAME_LEN (1024) #define MAX_CMDLINE_LEN (1024) #define MAX_FILENAME_LEN (256) #else #define PROGRAM_OS ("Linux/Posix") /* // Linux/UNIX is the only other OS being actively developed // other UNIX platforms should pretty much look like this, though */ #include #define stricmp strcasecmp #define strnicmp strncasecmp #if __CYGWIN__ typedef unsigned long ulong; #endif /* directory delimiters */ #define DIR_DELIMITER '/' #define DIR_DELIMITER_STRING "/" #define DIR_CURRENT_STRING "./" /* the "other" filesystem delimiter table (for conversion) */ #define OTHER_FILESYSTEM_DELIMITER "\\" /* max pathname for UNIX (may be more, but this is sufficient) */ /* (BTW, these values may be incorrect, but they should be sufficient. */ /* Anyone with more concrete values, please email me.) */ #define MAX_PATHNAME_LEN (1024) #define MAX_CMDLINE_LEN (1024) #define MAX_FILENAME_LEN (256) #endif /* // all supported filesystem delimiters */ #define ALL_FILESYSTEM_DELIMITERS "/\\" #endif htp-1.19/src/ver.h0000664000175000017500000000054112525674213014140 0ustar hoenickehoenicke/* // // ver.h // // version and program information // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #ifndef VER_H #define VER_H /* // program version number */ #include "version.inc" void DisplayHeader(void); void usage(void); #endif htp-1.19/src/misc-proc.c0000664000175000017500000000461612525674213015242 0ustar hoenickehoenicke/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* // // misc-proc.c // // specialized markup processors // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #include "misc-proc.h" #include "defs.h" #include "option.h" uint HeadProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext) { UNREF_PARAM(htmlMarkup); UNREF_PARAM(newPlaintext); /* authors ego-gratifying easter egg */ /* put a generator meta-tag at the end of the HTML header */ StreamPrintF(task->outfile, "outfile, " />\n"); } else { StreamPrintF(task->outfile, ">\n"); } return MARKUP_OKAY; } uint HtpCommentProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext) { UNREF_PARAM(task); UNREF_PARAM(htmlMarkup); UNREF_PARAM(newPlaintext); return DISCARD_MARKUP; } uint QuoteProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext) { HTML_ATTRIBUTE *attrib; UNREF_PARAM(task); UNREF_PARAM(newPlaintext); attrib = htmlMarkup->attrib; if (attrib == NULL || attrib->value != NULL) { HtpMsg(MSG_ERROR, task->infile, "improper QUOTE syntax"); return MARKUP_ERROR; } FreeMemory(htmlMarkup->tag); if (htmlMarkup->whitespace) FreeMemory(htmlMarkup->whitespace); htmlMarkup->tag = attrib->name; htmlMarkup->whitespace = attrib->whitespace; htmlMarkup->attrib = attrib->next; FreeMemory(attrib); return MARKUP_OKAY; } uint ConditionalWarning(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext) { UNREF_PARAM(htmlMarkup); UNREF_PARAM(newPlaintext); HtpMsg(MSG_ERROR, task->infile, "IFNOT tag no longer recognized; use IF NOT instead"); return MARKUP_ERROR; } uint PreProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext) { UNREF_PARAM(htmlMarkup); UNREF_PARAM(newPlaintext); /* inside a
    ...
    the CR's are important */ if(IsMarkupTag(htmlMarkup, "PRE")) { ForceLinefeeds(task->outfile, TRUE); } else if(IsMarkupTag(htmlMarkup, "/PRE")) { ForceLinefeeds(task->outfile, FALSE); } return MARKUP_OKAY; } htp-1.19/src/htp.c0000664000175000017500000004351312525674213014140 0ustar hoenickehoenicke/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* // // htp.c // // main(), major functionality modules // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #include "defs.h" #include "htp-files.h" #include "macro.h" #include "option.h" /* The global and project specific htp.def files. These are used for * dependency checking. */ static char globalFilename[MAX_PATHNAME_LEN]; static char projectFilename[MAX_PATHNAME_LEN]; /* // HTML file stream functions */ BOOL ProcessTask(TASK *task) { char *newPlaintext; uint markupResult; HTML_MARKUP htmlMarkup; BOOL result; uint markupType; assert(task != NULL); assert(task->infile != NULL); assert(task->outfile != NULL); assert(task->varstore != NULL); task->conditionalLevel = 0; for(;;) { result = ReadHtmlMarkup(task->infile, task->outfile, &markupType, &htmlMarkup); if(result == ERROR) { /* problem reading in the file */ return FALSE; } else if(result == FALSE) { /* end-of-file */ break; } newPlaintext = NULL; markupResult = ExpandAll(task, &htmlMarkup, &newPlaintext, markupType); /* destroy the structure, now only interested in the markup string */ DestroyMarkupStruct(&htmlMarkup); switch(markupResult) { case MARKUP_OKAY: { /* add the markup to the output file as it should appear */ StreamPrintF(task->outfile, "%c%s%c", MARKUP_OPEN_DELIM(markupType), newPlaintext, MARKUP_CLOSE_DELIM(markupType)); } break; case NEW_MARKUP: case MARKUP_REPLACED: { /* the markup has been replaced by a normal string */ PutStreamString(task->outfile, newPlaintext); } break; case DISCARD_MARKUP: { /* markup will not be included in final output */ } break; case MARKUP_ERROR: { /* (need to destroy plaintext buffer before exiting) */ FreeMemory(newPlaintext); return FALSE; } default: { FreeMemory(newPlaintext); printf("%s: serious internal error\n", PROGRAM_NAME); exit(1); } } /* free the plain text buffer and continue with processing */ if (newPlaintext) { FreeMemory(newPlaintext); newPlaintext = NULL; } } if (task->conditionalLevel > 0) { HtpMsg(MSG_ERROR, task->infile, "Missing for in line %d", task->conditionalLine[task->conditionalLevel-1]); } return TRUE; } BOOL ProcessFileByName(VARSTORE *parentVarStore, const char *in, const char *out) { STREAM infile; STREAM outfile; TASK task; BOOL result; const char *templateFile; /* // the "file" variable store ... holds macros only for files in current // directory, or project (this is loaded from the project default file, // which is called htp.def) */ static VARSTORE fileVarStore; assert(in != NULL); assert(out != NULL); /* assume no processing required */ result = TRUE; /* check the global and project default files first */ if(*globalFilename != NUL) { result = FullyCheckDependencies(globalFilename, out); } if((result == TRUE) && (*projectFilename != NUL)) { result = FullyCheckDependencies(projectFilename, out); } /* check the dependencies of the target file to see whether or not */ /* to proceed ... the global and project default files are checked as well */ if(result == TRUE) { result = FullyCheckDependencies(in, out); } /* if TRUE, no need to go any further */ if(result == TRUE) { /* explain why no processing required, and return as if processing */ /* was completed */ printf("%s: File \"%s\" is completely up to date.\n", PROGRAM_NAME, out); return TRUE; } /* continue, at least one file was found that requires out to be updated */ /* initialize the project variable store and push it onto context */ InitializeVariableStore(&fileVarStore); PushVariableStoreContext(parentVarStore, &fileVarStore); fileVarStore.isGlobal = TRUE; /* open the output file */ if(CreateFileWriter(&outfile, out, FALSE) == FALSE) { printf("%s: unable to open file \"%s\" for writing\n", PROGRAM_NAME, out); DestroyVariableStore(&fileVarStore); return FALSE; } if(CreateFileReader(&infile, in) == FALSE) { printf("%s: unable to open file \"%s\" for reading\n", PROGRAM_NAME, in); CloseStream(&outfile); DestroyVariableStore(&fileVarStore); return FALSE; } if(InitializeLocalOption() == FALSE) { printf("%s: unable to initialize local option store\n", PROGRAM_NAME); CloseStream(&infile); CloseStream(&outfile); DestroyVariableStore(&fileVarStore); return FALSE; } /* build a task structure */ task.infile = &infile; task.outfile = &outfile; task.varstore = &fileVarStore; task.sourceFilename = in; StoreVariable(&fileVarStore, "_htpfile_in", (void *) in, VAR_TYPE_SET_MACRO, VAR_FLAG_NONE, NULL, NULL); StoreVariable(&fileVarStore, "_htpfile_out", (void *) out, VAR_TYPE_SET_MACRO, VAR_FLAG_NONE, NULL, NULL); printf("%s: Processing file \"%s\" to output file \"%s\" ...\n", PROGRAM_NAME, in, out); result = ProcessTask(&task); /* done with this file, want to reuse struct */ CloseStream(&infile); /* need to check for a template file */ if((result == TRUE) && (VariableExists(&fileVarStore, VAR_TEMPLATE_NAME))) { templateFile = GetVariableValue(&fileVarStore, VAR_TEMPLATE_NAME); if(CreateFileReader(&infile, templateFile) == FALSE) { printf("%s: unable to open template file \"%s\"\n", PROGRAM_NAME, templateFile); CloseStream(&outfile); DestroyLocalOption(); DestroyVariableStore(&fileVarStore); return FALSE; } task.infile = &infile; task.outfile = &outfile; task.varstore = &fileVarStore; task.sourceFilename = in; printf("%s: Processing template file \"%s\" ...\n", PROGRAM_NAME, templateFile); result = ProcessTask(&task); CloseStream(&infile); } if(result == TRUE) { printf("%s: final output file \"%s\" successfully created\n\n", PROGRAM_NAME, outfile.name); } else { printf("\n%s: error encountered, file \"%s\" not completed\n\n", PROGRAM_NAME, outfile.name); } CloseStream(&outfile); /* destroy incomplete file if not configured elsewise */ if(result != TRUE) { if(PRECIOUS == FALSE) { assert(out != NULL); remove(out); } } /* destroy the local options for these files */ DestroyLocalOption(); /* destroy the project store as well */ DestroyVariableStore(&fileVarStore); return result; } BOOL ProcessDefaultFile(VARSTORE *varstore, const char *file) { TASK defTask; STREAM infile; STREAM outfile; BOOL result; if(CreateFileReader(&infile, file) == FALSE) { printf("%s: unable to open default project file \"%s\"\n", PROGRAM_NAME, file); return FALSE; } /* use a null outfile because there is no file to write to */ CreateNullWriter(&outfile); /* build a task (just like any other) and process the file */ /* use the global variable store to hold all the macros found */ defTask.infile = &infile; defTask.outfile = &outfile; defTask.varstore = varstore; defTask.sourceFilename = file; printf("%s: Processing default file \"%s\" ... \n", PROGRAM_NAME, file); result = ProcessTask(&defTask); CloseStream(&infile); CloseStream(&outfile); return result; } BOOL ProcessResponseFile(VARSTORE *parentVarStore, const char *resp) { char textline[MAX_CMDLINE_LEN]; char defResp[MAX_PATHNAME_LEN]; char newDirectory[MAX_PATHNAME_LEN]; char oldDirectory[MAX_PATHNAME_LEN]; STREAM respfile; int result; char *in; char *out; char *ptr; BOOL useNewDir; BOOL respFileOpen; FIND_TOKEN findToken; uint numread; char nl_bitmap[3]; VARSTORE projectVarStore; assert(resp != NULL); nl_bitmap[0] = '\n'; nl_bitmap[1] = '\n'; nl_bitmap[2] = '\n'; useNewDir = FALSE; if(strchr(ALL_FILESYSTEM_DELIMITERS, resp[strlen(resp) - 1]) != NULL) { /* some tests as done to ensure that (a) newDirectory does not trail */ /* with a directory separator and that (b) the separator is present */ /* before appending the filename ... requirement (a) is a DOS issue */ /* the response file is actually a directory the response file is */ /* possibly kept in ... copy it to the newDirectory variable for */ /* later use, but remove the trailing delimiter (MS-DOS issue) */ strcpy(newDirectory, resp); newDirectory[strlen(newDirectory) - 1] = NUL; /* now, see if default response file is present */ strcpy(defResp, newDirectory); strcat(defResp, DIR_DELIMITER_STRING); strcat(defResp, DEFAULT_RESPONSE_FILE); useNewDir = TRUE; respFileOpen = CreateFileReader(&respfile, defResp); } else { respFileOpen = CreateFileReader(&respfile, resp); } if(respFileOpen == FALSE) { printf("%s: unable to open \"%s\" as a response file\n", PROGRAM_NAME, resp); return FALSE; } printf("%s: Processing response file \"%s\" ...\n", PROGRAM_NAME, respfile.name); /* processing a response file in another directory, change to that */ /* directory before processing the files */ if(useNewDir) { getcwd(oldDirectory, sizeof oldDirectory); chdir(newDirectory); } /* initialize the variable store for response file and push it */ InitializeVariableStore(&projectVarStore); PushVariableStoreContext(parentVarStore, &projectVarStore); projectVarStore.isGlobal = TRUE; /* find the local project default file */ if(FileExists("htp.def")) { StringCopy(projectFilename, "htp.def", MAX_PATHNAME_LEN); ProcessDefaultFile(&projectVarStore, projectFilename); } else { projectFilename[0] = NUL; } result = TRUE; do { numread = GetStreamBlock(&respfile, textline, sizeof(textline), nl_bitmap); if(numread == 0) { /* EOF */ break; } /* Kill the newline at the end of the line */ if (textline[numread-1] == '\n') textline[numread-1] = NUL; in = NULL; out = NULL; /* walk tokens ... allow for tab character as token and ignore */ /* multiple token characters between filenames */ ptr = StringFirstToken(&findToken, textline, " \t"); while(ptr != NULL) { /* is this just a repeated token? */ if((*ptr == ' ') || (*ptr == '\t') || !(*ptr)) { ptr = StringNextToken(&findToken); continue; } /* found something ... like parsing the command-line, look for */ /* options, then response files, then regular in and out filenames */ if(*ptr == '-') { ParseToken(NULL, ptr+1); } else if(*ptr == ';') { /* comment, ignore the rest of the line */ break; } else if(in == NULL) { in = ptr; } else if(out == NULL) { out = ptr; } else { /* hmm ... extra information on line */ HtpMsg(MSG_WARNING, &respfile, "extra option \"%s\" specified in response file, ignoring", ptr); } ptr = StringNextToken(&findToken); } if (in == NULL) continue; if (out == NULL) { char tempFilename[MAX_PATHNAME_LEN]; StringCopy(tempFilename, projectFilename, MAX_PATHNAME_LEN); /* in is the response file. * recurse but with the parentVarStore. */ PopVariableStoreContext(&projectVarStore); result = ProcessResponseFile(parentVarStore, in); PushVariableStoreContext(parentVarStore, &projectVarStore); /* restore the projectFilename for dependency checking */ StringCopy(projectFilename, tempFilename, MAX_PATHNAME_LEN); } else if((in != NULL) && (out != NULL)) { /* both in and out were specified, process a file */ result = ProcessFileByName(&projectVarStore, in, out); } } while(result == TRUE); /* destroy the response files store */ DestroyVariableStore(&projectVarStore); CloseStream(&respfile); /* restore the directory this all started in */ if(useNewDir) { chdir(oldDirectory); } return result; } int main(int argc, char *argv[]) { int result; uint ctr; char *in; char *out; char *resp; /* // the global variable store ... holds permanent, file-to-file macros // (these are set in the global default file) ... filename kept for // dependency checking */ VARSTORE globalVarStore; DisplayHeader(); if(argc == 1) { usage(); return 1; } /* initialize debugging */ #if DEBUG DebugInit("htpdeb.out"); atexit(DebugTerminate); #endif #ifdef USE_SUBALLOC /* initialize the suballoc memory module */ InitializeMemory(); atexit(TerminateMemory); #endif /* initialize global variable options */ if(InitializeGlobalOption() == FALSE) { printf("%s: fatal error, unable to initialize internal options\n", PROGRAM_NAME); return 1; } in = NULL; out = NULL; resp = NULL; /* search command-line for options */ for(ctr = 1; ctr < (uint) argc; ctr++) { if(*argv[ctr] == '-') { /* command-line option specified */ ParseToken(NULL, argv[ctr]+1); } else if(*argv[ctr] == '@') { /* response file specified */ resp = argv[ctr] + 1; if(*resp == NUL) { resp = (char *) DEFAULT_RESPONSE_FILE; } } else if(in == NULL) { /* input file was specified */ in = argv[ctr]; } else if(out == NULL) { /* output file was specified */ out = argv[ctr]; } else { printf("%s: unknown argument \"%s\" specified\n", PROGRAM_NAME, argv[ctr]); return 1; } } if(USAGE == TRUE) { usage(); return 1; } if((in == NULL || out == NULL) && (resp == NULL)) { usage(); return 1; } /* initialize the global variable store before proceeding */ if(InitializeVariableStore(&globalVarStore) != TRUE) { printf("%s: unable to initialize global variable store (out of memory?)\n", PROGRAM_NAME); return 1; } globalVarStore.isGlobal = TRUE; /* store htp version number in global store */ StoreVariable(&globalVarStore, "_htp_version", VER_STRING, VAR_TYPE_SET_MACRO, VAR_FLAG_NONE, NULL, NULL); /* before reading in the response file or processing any files, handle */ /* the default file, if there is one ... all of its macros are held in */ /* the global variable store */ if(HtpDefaultFilename(globalFilename, MAX_PATHNAME_LEN)) { ProcessDefaultFile(&globalVarStore, globalFilename); } else { globalFilename[0] = NUL; } /* now, process the response file (if there is one) or the files */ /* specified on the command-line */ if(resp != NULL) { result = ProcessResponseFile(&globalVarStore, resp); } else { /* find the local project default file */ if(FileExists("htp.def")) { StringCopy(projectFilename, "htp.def", MAX_PATHNAME_LEN); ProcessDefaultFile(&globalVarStore, projectFilename); } else { projectFilename[0] = NUL; } result = ProcessFileByName(&globalVarStore, in, out); } /* display varstore stats */ DEBUG_PRINT(("Variable lookups=%u string cmps=%u rotations=%u\n", variableLookups, variableStringCompares, variableRotations)); /* destroy the global variable store */ DestroyVariableStore(&globalVarStore); /* destroy global option */ DestroyGlobalOption(); #ifdef USE_SUBALLOC /* display suballoc stats */ DEBUG_PRINT(("suballoc total allocations=%u free pool hits=%u system heap allocs=%u\n", totalAllocations, freePoolHits, totalAllocations - freePoolHits)); #endif return (result == TRUE) ? 0 : 1; } htp-1.19/src/htp-files.h0000664000175000017500000000315212525674213015240 0ustar hoenickehoenicke/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* // // htp-files.h // // htp specific file access // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #ifndef HTP_FILES_H #define HTP_FILES_H #include "defs.h" /* // returns the full, qualified pathname of the default htp include file // // Returns FALSE if unable to find the file. */ BOOL HtpDefaultFilename(char *filename, uint size); /* // compare files modified time/date stamp, as a dependency check ... returns // TRUE if the dependency does not require an update, FALSE otherwise (which // could either be a timestamp discrepency, or simply that the resulting file // does not exist) ... if dependency checking is turned off, this function // will always return FALSE. // // Returns ERROR if dependency file does not exist. */ BOOL IsTargetUpdated(const char *dependency, const char *target); /* // searches for the specified file in the search path ... this function is // very stupid, it simply gets the first directory in the search string, // appends the file directly to the end, and tests for existance. Repeat. */ BOOL SearchForFile(const char *filename, char *fullPathname, uint size); /* // TRUE = htlmMarkup is filled with new markup, FALSE if end of file, // ERROR if a problem // !! Don't like using ERROR in any BOOL return values */ BOOL ReadHtmlMarkup(STREAM *infile, STREAM *outfile, uint *markupType, HTML_MARKUP *htmlMarkup); BOOL FullyCheckDependencies(const char *in, const char *out); #endif htp-1.19/src/textfile.h0000664000175000017500000000176612525674213015202 0ustar hoenickehoenicke/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* // // textfile.h // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #ifndef TEXTFILE_H #define TEXTFILE_H /* // text file function */ typedef struct tagFILEINFO { FILE *file; uint pendingSpaces; BOOL emptyLine; WORD flags; } TEXTFILE; /* // TEXTFILE flags */ #define TEXTFILE_FLAG_NONE (0) #define TEXTFILE_FLAG_NULL_FILE (0x0001) #define TEXTFILE_FLAG_FORCE_CR (0x0002) /* // text file functions */ BOOL OpenFile(const char *filename, const char *openFlags, TEXTFILE *textFile); BOOL OpenFD(int filedes, const char *openFlags, TEXTFILE *textFile); void CloseFile(TEXTFILE *textFile); void CreateNullFile(TEXTFILE *textFile); BOOL GetFileChar(TEXTFILE *textFile, char *ch); BOOL PutFileString(TEXTFILE *textFile, const char *ch); #endif htp-1.19/src/set-proc.h0000664000175000017500000000116712525674213015105 0ustar hoenickehoenicke/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* // // set-proc.h // // specialized markup processors // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #ifndef SET_PROC_H #define SET_PROC_H #include "defs.h" uint SetProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext); uint UnsetProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext); #define MAX_INC_VALUE_LENGTH (32) uint IncProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext); #endif htp-1.19/src/msg.h0000664000175000017500000000161612525674213014136 0ustar hoenickehoenicke/* // // msg.h // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #ifndef MSG_H #define MSG_H /* // message severity levels */ #define MSG_ERROR (2) #define MSG_WARNING (1) #define MSG_INFO (0) /* // set the printable message level ... if the message being written // does not meet the level, it is not printed */ void SetMessageSeverityLevel(uint level); /* // error/warning/info message display function */ #ifndef DUMB_MSG_PROTOTYPE void HtpMsg(uint severityLevel, STREAM *textFile, const char *format, ...); #endif #if DEBUG /* // debug message display, which also will dump to disk */ void DebugInit(const char *debugMsgFilename); void DebugTerminate(void); #ifndef DUMB_MSG_PROTOTYPE void DebugMsg(const char *format, ...); #endif #endif #endif htp-1.19/src/bool-proc.h0000664000175000017500000000067612525674213015251 0ustar hoenickehoenicke/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* // // bool-proc.h // // specialized markup processors // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #ifndef BOOL_PROC_H #define BOOL_PROC_H #include "defs.h" uint BooleanProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext); #endif htp-1.19/src/html.h0000664000175000017500000000370512525674213014315 0ustar hoenickehoenicke/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* // // html.h // // HTML markup tag functions // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #ifndef MARKUP_H #define MARKUP_H #define MAX_ATTRIBUTE_COUNT (32) #define QUOTES_NONE 0 #define QUOTES_DOUBLE 1 #define QUOTES_SINGLE 2 typedef struct tagHTML_ATTRIBUTE { char *name; char *value; int quotes; char *whitespace; struct tagHTML_ATTRIBUTE *next; } HTML_ATTRIBUTE; typedef struct tagHTML_MARKUP { char *tag; BOOL single; /* single tag (xml-style) ending with "/>" */ char *whitespace; HTML_ATTRIBUTE *attrib; } HTML_MARKUP; /* // functions */ /* whitespace functions are not specific to markup tags, but commonly used */ const char *FindWhitespace(const char *str); const char *FindNonWhitespace(const char *str); /* HTML_ATTRIBUTE functions */ BOOL ChangeAttributeName(HTML_ATTRIBUTE *htmlAttribute, char *name); BOOL ChangeAttributeValue(HTML_ATTRIBUTE *htmlAttribute, char *value, int quotes); void DestroyAttribute(HTML_ATTRIBUTE *htmlAttribute); /* HTML_MARKUP functions */ BOOL PlaintextToMarkup(const char *plaintext, HTML_MARKUP *htmlMarkup); BOOL MarkupToPlaintext(HTML_MARKUP *htmlMarkup, char **plaintext); BOOL AddAttributeToMarkup(HTML_MARKUP *htmlMarkup, const char *name, const char *value, int quotes); void DestroyMarkupStruct(HTML_MARKUP *htmlMarkup); BOOL IsMarkupTag(HTML_MARKUP *htmlMarkup, const char *tag); BOOL UnlinkBoolAttributeInMarkup(HTML_MARKUP *htmlMarkup, const char *name); const char *MarkupAttributeValue(HTML_MARKUP *htmlMarkup, const char *name); BOOL ChangeMarkupTag(HTML_MARKUP *htmlMarkup, char *tag); HTML_ATTRIBUTE *UnlinkAttributeInMarkup(HTML_MARKUP *htmlMarkup, const char *name); #endif htp-1.19/src/defs.c0000664000175000017500000000273112525674213014263 0ustar hoenickehoenicke/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* // // defs.c // // major definitions // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #include "defs.h" /* // default response filename */ const char *DEFAULT_RESPONSE_FILE = "htp.rsp"; /* // template file name (used internally to store name for post-processing) // use squirrelly characters and a space to avoid conflicting with // user names */ const char *VAR_TEMPLATE_NAME = "__!TEMPLATE FILE~"; /* // the user can configure what kind of characters to use to surround htp // markups, to avoid conflicts with HTML markups ... default is the standard // greater-than/less-than bracketing, but also acceptable are square // brackets and curly brackets (parentheses are just too common in normal // text to be useful) // // Because htp also processes standard HTML markups, a IS_OPEN_MARKUP and // IS_CLOSE_MARKUP macros are used instead of standard comparisons ... watch // out for side-effects // // MARKUP_TYPE_ANY is used for markup processors to define they are // interested in either kind of markup (currently unused) // // MARKUP_OPEN_DELIM and MARKUP_CLOSE_DELIM are used to return the proper // delimiter given the markup type */ char htpOpenMarkup = HTML_OPEN_MARKUP; char htpCloseMarkup = HTML_CLOSE_MARKUP; /* // include file search path */ char searchPath[SEARCH_PATH_SIZE] = { 0, }; htp-1.19/src/htp.h0000664000175000017500000000633712525674213014150 0ustar hoenickehoenicke/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* // // htp.h // // Common include file // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #ifndef HTP_H #define HTP_H /* // for assert() */ #ifndef DEBUG #define NDEBUG #endif /* // common definitions */ typedef unsigned int BOOL; #define FALSE (0) #define TRUE (1) #define ERROR ((uint) -1) #define NUL ((char) 0) typedef unsigned char BYTE; typedef unsigned short WORD; typedef unsigned long DWORD; /* // common data sizes */ #define KBYTE (1024L) #define MBYTE (KBYTE * KBYTE) #define GBYTE (MBYTE * KBYTE) /* // debug information macro */ #if DEBUG #define DEBUG_PRINT(p) \ DebugMsg("\n(%s) %s line %u: ", PROGRAM_NAME, __FILE__, __LINE__); \ DebugMsg p; \ DebugMsg("\n"); #else #define DEBUG_PRINT(p) #endif /* // macros to handle unused/unreferenced local variables & parameters in // functions // // DEBUG_* macros are defined as nothing in non-debug version, too catch // unreferenced stuff in final build version // // Macros wholesale ripped off from Windows NT device driver kit ... if // they originated elsewhere, this is the first I've seen them */ #define UNREF_PARAM(p) ((p) = (p)) #define UNREF_LOCAL(l) ((l) = (l)) #if DEBUG #define DEBUG_UNREF_PARAM(p) ((p) = (p)) #define DEBUG_UNREF_LOCAL(l) ((l) = (l)) #else #define DEBUG_UNREF_PARAM(p) #define DEBUG_UNREF_LOCAL(l) #endif /* // common macros */ #define MAKE_WORD(h, l) ((((WORD) (h)) << 8) | ((WORD) (l))) #define MAKE_DWORD(hh,hl,lh,ll) \ ((((DWORD) (hh)) << 24) | (((DWORD)(hl)) << 16) \ | (((DWORD) (lh)) << 8) | ((DWORD)(ll))) /* // C library */ #include #include #include #include #include #include #include #include #include #include #include /* // operating-system dependent header file */ #include "os.h" /* // modules */ #include "image.h" #include "html.h" #include "ver.h" #include "textfile.h" #include "streams.h" #include "varstore.h" #include "msg.h" #include "suballoc.h" /* // returns the markup type flag ... either the closing or opening delimiter // in the markup can be passed in */ uint MarkupType(char delim); /* // common functions (maintained in util.c) */ BOOL CreateTempFilename(char *tempfilename, uint size); char *StringCopy(char *dest, const char *src, uint size); char *ConvertDirDelimiter(const char *pathname); BOOL FileExists(const char *pathname); const char *FindFilename(const char *pathname); char *DuplicateString(const char *src); char *DuplicateSubString(const char *src, int len); #ifndef HAVE_STPCPY char *stpcpy(char *dest, const char *src); #endif /* // re-entrant strtok() functions and structures */ typedef struct tagFIND_TOKEN { const char *tokens; char *lastChar; char *nextStart; } FIND_TOKEN; char *StringFirstToken(FIND_TOKEN *findToken, char *string, const char *tokens); char *StringNextToken(FIND_TOKEN *findToken); #endif htp-1.19/src/image.h0000664000175000017500000000131212525674213014423 0ustar hoenickehoenicke/* // // image.h // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #ifndef IMAGE_H #define IMAGE_H /* // image file structure */ typedef struct tagIMAGEFILE { char *name; FILE *file; uint imageType; } IMAGEFILE; BOOL OpenImageFile(const char *filename, IMAGEFILE *imageFile); void CloseImageFile(IMAGEFILE *imageFile); BOOL GetImageDimensions(IMAGEFILE *imageFile, DWORD *width, DWORD *height); /* // image url substitution */ BOOL ExistsImageUrl (const char *url); BOOL StoreImageUrl (const char *url, char* path); BOOL RemoveImageUrl (const char *url); #endif htp-1.19/src/image.c0000664000175000017500000001253412525674213014426 0ustar hoenickehoenicke/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* // // image.c // // Image file functions // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #include "htp.h" #include "gif.h" #include "jpeg.h" #include "png.h" typedef struct tagIMAGEURL { char *url; char *path; struct tagIMAGEURL *next; } IMAGEURL; static IMAGEURL* imageurl_store = NULL; IMAGEURL *FindImageUrl (const char *url) { IMAGEURL* urls; urls = imageurl_store; while (urls != NULL) { if (stricmp(url, urls->url) == 0) { return urls; } urls = urls->next; } return NULL; } BOOL ExistsImageUrl (const char *url) { return (FindImageUrl(url) != NULL); } BOOL StoreImageUrl (const char *url, char* path) { IMAGEURL* urls; DEBUG_PRINT(("Storing image URL (%s,%s)...",url, path)); urls = FindImageUrl(url); if (urls == NULL) { if((urls = AllocMemory(sizeof(IMAGEURL))) == NULL) { DEBUG_PRINT(("unable to allocate memory for new image URL")); return FALSE; } if((urls->url = DuplicateString(url)) == NULL) { FreeMemory(urls); DEBUG_PRINT(("unable to allocate memory for new URL")); return FALSE; } urls->next = imageurl_store; imageurl_store = urls; } else { FreeMemory(urls->path); } urls->path = path; return TRUE; } BOOL RemoveImageUrl (const char *url) { IMAGEURL *urls, **prev; prev = &imageurl_store; urls = imageurl_store; while (urls != NULL) { if (stricmp(url, urls->url) == 0) { break; } prev = &urls->next; urls = urls->next; } if (urls == NULL) { DEBUG_PRINT(("unable to find image URL for remove")); return FALSE; } *prev = urls->next; FreeMemory(urls->url); FreeMemory(urls->path); FreeMemory(urls); return TRUE; } char *GetPathFor (IMAGEURL *imageurl, const char *src) { uint urlsize, srcsize, pathsize, suffixsize, length; char *filename, *suffix; DEBUG_PRINT(("GetPathFor (%s,%s) %s",imageurl->url,imageurl->path,src)); urlsize = strlen(imageurl->url); srcsize = strlen(src); if (srcsize < urlsize) { return NULL; } if (strnicmp(imageurl->url,src,urlsize) != 0) { return NULL; } pathsize = strlen(imageurl->path); suffix = ConvertDirDelimiter(src + urlsize); suffixsize = strlen(suffix); length = pathsize + suffixsize ; if ((filename = AllocMemory(length+1)) == NULL) { DEBUG_PRINT(("unable to allocate memory for filename in GetPathFor")); return NULL; } StringCopy(filename, imageurl->path, pathsize + 1); StringCopy(filename + pathsize, suffix, suffixsize +1); filename[length] = NUL; FreeMemory(suffix); return filename; } typedef struct { BOOL (*checkFormat) (FILE * file); BOOL (*readDimensions) (FILE * file, DWORD *height, DWORD *width); } ImageOps; ImageOps ops[] = { { GifFormatFound , GifReadDimensions }, { JpegFormatFound, JpegReadDimensions }, { PngFormatFound , PngReadDimensions } }; #define IMAGE_TYPE_COUNT (sizeof(ops) / sizeof(ImageOps)) #define IMAGE_TYPE_UNKNOWN IMAGE_TYPE_COUNT BOOL OpenImageFile(const char *filename, IMAGEFILE *imageFile) { uint type; IMAGEURL* imageurl; assert(filename != NULL); assert(imageFile != NULL); imageFile->name = NULL; DEBUG_PRINT(("trying imageurls...")); imageurl = imageurl_store; while (imageurl) { DEBUG_PRINT(("trying imageurl %s for %s",imageurl->url,filename)); if ((imageFile->name = GetPathFor(imageurl, filename))) { break; } imageurl = imageurl->next; } if (imageFile->name == NULL) { if ((imageFile->name = ConvertDirDelimiter(filename)) == NULL) { DEBUG_PRINT(("could not duplicate filename string")); return FALSE; } } imageFile->file = fopen(imageFile->name, "rb"); if (imageFile->file == NULL) { DEBUG_PRINT(("could not open image file %s", imageFile->name)); FreeMemory(imageFile->name); return FALSE; } /* build the rest of the image file structure */ /* by default, unknown image type */ for (type = 0; type < IMAGE_TYPE_COUNT; type++) { if (ops[type].checkFormat(imageFile->file)) break; } /* If type is unknown, the variable type is already * IMAGE_TYPE_COUNT == IMAGE_TYPE_UNKNOWN. */ imageFile->imageType = type; return TRUE; } void CloseImageFile(IMAGEFILE *imageFile) { assert(imageFile != NULL); assert(imageFile->name != NULL); assert(imageFile->file != NULL); FreeMemory(imageFile->name); fclose(imageFile->file); imageFile->name = NULL; imageFile->file = NULL; } BOOL GetImageDimensions(IMAGEFILE *imageFile, DWORD *width, DWORD *height) { assert(imageFile != NULL); assert(width != NULL); assert(height != NULL); /* unknown file type */ if(imageFile->imageType == IMAGE_TYPE_UNKNOWN) return FALSE; return ops[imageFile->imageType].readDimensions(imageFile->file, height, width); } htp-1.19/src/LICENSE.txt0000664000175000017500000001243012525674213015016 0ustar hoenickehoenickeThis is the license for the sprintf.* The Frontier Artistic License Version 1.0 Derived from the Artistic License at OpenSource.org. Submitted to OpenSource.org for Open Source Initiative certification. Preamble The intent of this document is to state the conditions under which a Package may be copied, such that the Copyright Holder maintains some semblance of artistic control over the development of the package, while giving the users of the package the right to use and distribute the Package in a more-or-less customary fashion, plus the right to make reasonable modifications. Definitions "Package" refers to the script, suite, file, or collection of scripts, suites, and/or files distributed by the Copyright Holder, and to derivatives of that Package created through textual modification. "Standard Version" refers to such a Package if it has not been modified, or has been modified in accordance with the wishes of the Copyright Holder. "Copyright Holder" is whoever is named in the copyright statement or statements for the package. "You" is you, if you're thinking about copying or distributing this Package. "Reasonable copying fee" is whatever you can justify on the basis of media cost, duplication charges, time of people involved, and so on. (You will not be required to justify it to the Copyright Holder, but only to the computing community at large as a market that must bear the fee.) "Freely Available" means that no fee is charged for the item itself, though there may be fees involved in handling the item. It also means that recipients of the item may redistribute it under the same conditions they received it. Terms 1. You may make and give away verbatim copies of the source form of the Standard Version of this Package without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may apply bug fixes, portability fixes, and other modifications derived from the Public Domain or from the Copyright Holder. A Package modified in such a way shall still be considered the Standard Version. 3. You may otherwise modify your copy of this Package in any way, provided that you insert a prominent notice in each changed script, suite, or file stating how and when you changed that script, suite, or file, and provided that you do at least ONE of the following: a) Use the modified Package only within your corporation or organization, or retain the modified Package solely for personal use. b) Place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or placing the modifications on a major archive site such as ftp.uu.net, or by allowing the Copyright Holder to include your modifications in the Standard Version of the Package. c) Rename any non-standard executables so the names do not conflict with standard executables, which must also be provided, and provide a separate manual page (or equivalent) for each non-standard executable that clearly documents how it differs from the Standard Version. d) Make other distribution arrangements with the Copyright Holder. 4. You may distribute the programs of this Package in object code or executable form, provided that you do at least ONE of the following: a) Distribute a Standard Version of the executables and library files, together with instructions (in the manual page or equivalent) on where to get the Standard Version. b) Accompany the distribution with the machine-readable source of the Package with your modifications. c) Accompany any non-standard executables with their corresponding Standard Version executables, give the non-standard executables non-standard names, and clearly document the differences in manual pages (or equivalent), together with instructions on where to get the Standard Version. d) Make other distribution arrangements with the Copyright Holder. 5. You may charge a reasonable copying fee for any distribution of this Package. You may charge any fee you choose for support of this Package. You may not charge a fee for this Package itself. However, you may distribute this Package in aggregate with other (possibly commercial) programs as part of a larger (possibly commercial) software distribution provided that you do not advertise this Package as a product of your own. 6. The scripts and library files supplied as input to or produced as output from the programs of this Package do not automatically fall under the copyright of this Package, but belong to whomever generated them, and may be sold commercially, and may be aggregated with this Package. 7. Scripts, suites, or programs supplied by you that depend on or otherwise make use of this Package shall not be considered part of this Package. 8. The name of the Copyright Holder may not be used to endorse or promote products derived from this software without specific prior written permission. 9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. The End http://www.spinwardstars.com/frontier/fal.html htp-1.19/src/bool-proc.c0000664000175000017500000001356612525674213015246 0ustar hoenickehoenicke/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* // // bool-proc.c // // specialized markup processors // // Copyright (c) 2002-2003 Jochen Hoenicke. // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #include "bool-proc.h" #include "defs.h" #include "htp-files.h" static BOOL EvaluateIfTag(TASK *task, HTML_MARKUP *htmlMarkup) { BOOL condTrue, notTagFound; HTML_ATTRIBUTE *attrib; const char *value; uint type; /* this is an ugly way to handle the IF-IF NOT test, but will need */ /* be cleaned up in the future */ notTagFound = UnlinkBoolAttributeInMarkup(htmlMarkup, "NOT"); /* should either be one or two attributes in markup */ if(htmlMarkup->attrib == NULL) { HtpMsg(MSG_ERROR, task->infile, "no conditional to test"); return MARKUP_ERROR; } if(htmlMarkup->attrib->next != NULL) { HtpMsg(MSG_ERROR, task->infile, "too many items in conditional expression"); return MARKUP_ERROR; } attrib = htmlMarkup->attrib; /* get the macros associated type (UNKNOWN if macro is not defined) */ type = GetVariableType(task->varstore, attrib->name); /* if only a name is specified, only care if macro is defined */ if(attrib->value == NULL) { condTrue = (type != VAR_TYPE_UNKNOWN) ? TRUE : FALSE; } else { /* macro value comparison */ if(type == VAR_TYPE_SET_MACRO) { /* macro comparison (case-sensitive) */ value = GetVariableValue(task->varstore, attrib->name); condTrue = (value && strcmp(value, attrib->value) == 0) ? TRUE : FALSE; } else { /* block macro, comparisons not allowed */ condTrue = FALSE; } } /* reverse conditional if NOT attribute found */ return condTrue != notTagFound; } static BOOL DiscardConditionalBlock(TASK *task, BOOL takeElseBlock) { HTML_MARKUP htmlMarkup; BOOL result; uint embeddedConditionals; uint markupType; char ch; /* discard the block, looking for the matching ELSE or /IF statement */ embeddedConditionals = 0; for(;;) { result = ReadHtmlMarkup(task->infile, NULL, &markupType, &htmlMarkup); if(result == ERROR) { return FALSE; } else if(result == FALSE) { /* end-of-file before end-of-conditional ... error */ HtpMsg(MSG_ERROR, task->infile, "Missing for in line %d", task->conditionalLine[task->conditionalLevel-1]); return FALSE; } /* another conditional started? */ if(IsMarkupTag(&htmlMarkup, "IF")) { embeddedConditionals++; } else if(IsMarkupTag(&htmlMarkup, "/IF")) { /* end of the conditional? */ if(embeddedConditionals == 0) { DestroyMarkupStruct(&htmlMarkup); task->conditionalLevel--; break; } embeddedConditionals--; } else if(embeddedConditionals == 0 && takeElseBlock) { /* Check whether this is an ELSE or a taken ELSEIF tag. */ if (IsMarkupTag(&htmlMarkup, "ELSE") || (IsMarkupTag(&htmlMarkup, "ELSEIF") && EvaluateIfTag(task, &htmlMarkup) == TRUE)) { DestroyMarkupStruct(&htmlMarkup); /* Skip EOL, but put it back if it's another character */ if (GetStreamChar(task->infile, &ch) && ch != '\n') { UnreadStreamChar(task->infile, ch); } break; } } /* destroy and continue */ DestroyMarkupStruct(&htmlMarkup); } return TRUE; } uint BooleanProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext) { char ch; UNREF_PARAM(newPlaintext); /* conditionalLevel keeps track of boolean depth */ if(task->conditionalLevel == 0 && !IsMarkupTag(htmlMarkup, "IF")) { HtpMsg(MSG_ERROR, task->infile, "<%s> without matching IF tag", htmlMarkup->tag); return MARKUP_ERROR; } if(IsMarkupTag(htmlMarkup, "IF")) { if (task->conditionalLevel >= MAX_CONDITIONAL_LEVEL) { HtpMsg(MSG_ERROR, task->infile, "Too many nested tags"); return MARKUP_ERROR; } task->conditionalLine[task->conditionalLevel++] = task->infile->lineNumber; if (EvaluateIfTag(task, htmlMarkup) == FALSE) { /* discard the rest of the conditional block since this * portion has evaluated false. We still can take the * ELSE, though */ if(DiscardConditionalBlock(task, TRUE) == FALSE) { return MARKUP_ERROR; } } else { /* Skip EOL, but put it back if it's another character */ if (GetStreamChar(task->infile, &ch) && ch != '\n') { UnreadStreamChar(task->infile, ch); } } } else if (IsMarkupTag(htmlMarkup, "ELSE") || IsMarkupTag(htmlMarkup, "ELSEIF")) { /* this can only occur if the associated conditional statement */ /* evaluated TRUE, so the remaining block must be discarded */ /* We must not even take the ELSE part */ if(DiscardConditionalBlock(task, FALSE) == FALSE) { return MARKUP_ERROR; } } else { /* end of conditional */ assert(task->conditionalLevel > 0); task->conditionalLevel--; } return DISCARD_MARKUP; } htp-1.19/src/use-proc.c0000664000175000017500000001415312525674213015100 0ustar hoenickehoenicke/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* // // use-proc.c // // specialized markup processors // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #include "use-proc.h" #include "defs.h" uint UseProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext) { const char *name; HTML_ATTRIBUTE *nameAttrib; const char *value; STREAM incfile; BOOL noexpand; int result; uint type; VARSTORE varstore; VARSTORE *topVarstore; nameAttrib = htmlMarkup->attrib; if(nameAttrib == NULL) { HtpMsg(MSG_ERROR, task->infile, "USE markup without parameter"); return MARKUP_ERROR; } if (nameAttrib->value) { if (stricmp(nameAttrib->name, "NAME") == 0) { HtpMsg(MSG_WARNING, task->infile, "deprecated USE syntax, see manual"); name = nameAttrib->value; } else { HtpMsg(MSG_ERROR, task->infile, "illegal USE markup"); return MARKUP_ERROR; } } else { name = nameAttrib->name; } htmlMarkup->attrib = nameAttrib->next; /* check if the noexpand flag is present */ noexpand = UnlinkBoolAttributeInMarkup(htmlMarkup, "NOEXPAND"); /* get the type of macro */ type = GetVariableType(task->varstore, name); /* verify the macro exists and of correct type */ if ((type != VAR_TYPE_SET_MACRO) && (type != VAR_TYPE_BLOCK_MACRO)) { HtpMsg(MSG_ERROR, task->infile, "macro %s has not been declared", name); DestroyAttribute(nameAttrib); FreeMemory(nameAttrib); return MARKUP_ERROR; } /* if more than one parameter is on the USE tag, then assume they are */ /* local variables for the macro */ if (htmlMarkup->attrib != NULL) { if(type == VAR_TYPE_SET_MACRO) { /* nope, not yet */ HtpMsg(MSG_ERROR, task->infile, "macro parameters can only be used for BLOCK macros"); DestroyAttribute(nameAttrib); FreeMemory(nameAttrib); return MARKUP_ERROR; } /* create a local variable store */ if(InitializeVariableStore(&varstore) == FALSE) { HtpMsg(MSG_ERROR, task->infile, "unable to initialize local context for macro"); DestroyAttribute(nameAttrib); FreeMemory(nameAttrib); return MARKUP_ERROR; } /* add each additional parameter to the local varstore */ while (htmlMarkup->attrib != NULL) { /* No need to duplicate values, as varstore is * destroyed before this function returns. */ if(StoreVariable(&varstore, htmlMarkup->attrib->name, htmlMarkup->attrib->value, VAR_TYPE_SET_MACRO, VAR_FLAG_NONE, NULL, NULL) == FALSE) { HtpMsg(MSG_ERROR, task->infile, "unable to add variable to block's local context"); DestroyVariableStore(&varstore); DestroyAttribute(nameAttrib); FreeMemory(nameAttrib); return MARKUP_ERROR; } htmlMarkup->attrib = htmlMarkup->attrib->next; } /* make this variable store the topmost context */ PushVariableStoreContext(task->varstore, &varstore); topVarstore = &varstore; } else { topVarstore = task->varstore; } if (type == VAR_TYPE_SET_MACRO) { /* get the value of the macro */ value = GetVariableValue(task->varstore, name); /* if NULL, then the macro was declared with no value, this is okay, */ /* just don't do anything */ if(value == NULL) { DestroyAttribute(nameAttrib); FreeMemory(nameAttrib); return DISCARD_MARKUP; } HtpMsg(MSG_INFO, task->infile, "dereferencing macro \"%s\"", name); PutStreamString(task->outfile, value); DestroyAttribute(nameAttrib); FreeMemory(nameAttrib); return DISCARD_MARKUP; } else /* type == VAR_TYPE_BLOCK_MACRO */ { /* !! magic number */ TASK newTask; STREAM *blockFile; /* get the blockFile of the macro */ blockFile = (STREAM*) GetVariableValue(task->varstore, name); /* if NULL, big-time error */ assert (blockFile != NULL); HtpMsg(MSG_INFO, task->infile, "dereferencing block macro \"%s\"%s", name, noexpand ? " with noexpand" : ""); if (noexpand) { PutStreamString(task->outfile, blockFile->u.buffer.buffer); DestroyAttribute(nameAttrib); FreeMemory(nameAttrib); return DISCARD_MARKUP; } result = CreateBufferReader(&incfile, blockFile); assert(result); /* build a new task structure */ newTask.infile = &incfile; newTask.outfile = task->outfile; newTask.sourceFilename = task->sourceFilename; /* re-use current variable store if no local variable store was */ /* allocated, otherwise use the new one */ newTask.varstore = topVarstore; /* process the new input file */ result = ProcessTask(&newTask); if (!result) { /* Error message was already spitted out. However, we * should give a hint where the meta-tag was called. */ HtpMsg(MSG_ERROR, task->infile, "... in block macro \"%s\"", name); } /* remove the new context (and make sure it is, in fact, the block's */ /* context) */ if(topVarstore == &varstore) { assert(varstore.child == NULL); PopVariableStoreContext(&varstore); DestroyVariableStore(&varstore); } CloseStream(&incfile); /* if the new file did not process, return an error, otherwise discard */ /* the markup */ DestroyAttribute(nameAttrib); FreeMemory(nameAttrib); return (result == TRUE) ? DISCARD_MARKUP : MARKUP_ERROR; } } htp-1.19/src/defs.h0000664000175000017500000001040112525674213014261 0ustar hoenickehoenicke/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* // // defs.h // // major definitions // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #ifndef DEFS_H #define DEFS_H #include "htp.h" /* // default response filename */ extern const char *DEFAULT_RESPONSE_FILE; /* // variable types */ #define VAR_TYPE_SET_MACRO (1) #define VAR_TYPE_BLOCK_MACRO (2) #define VAR_TYPE_INTERNAL (3) #define VAR_TYPE_ALTTEXT (4) #define VAR_TYPE_DEF_MACRO (5) #define VAR_TYPE_BLOCKDEF_MACRO (6) /* // variable flags */ #define VAR_FLAG_NONE (0x0000) #define VAR_FLAG_DEALLOC_VALUE (0x0002) #define VAR_FLAG_DEALLOC_NAME (0x0004) #define VAR_FLAG_UNDEFINED (0x0008) /* // specialized markup processors type definitions */ /* MARKUP_FUNC return codes */ #define MARKUP_OKAY (0) #define MARKUP_REPLACED (1) #define DISCARD_MARKUP (2) #define MARKUP_ERROR ((uint) -1) #define NEW_MARKUP (3) /* // when reading source files, need to dynamically allocate memory to avoid // overruns ... use a stronger strategy for "real" operating systems, more // conservative for wimpy DOS */ #if __MSDOS__ #define MIN_PLAINTEXT_SIZE (128) #define PLAINTEXT_GROW_SIZE (32) #else #define MIN_PLAINTEXT_SIZE (2048) #define PLAINTEXT_GROW_SIZE (2048) #endif /* // miscellaneous definitions */ #define MAX_TIME_DATE_SIZE (128) #define DEFAULT_PRECISION (0) #define SEARCH_PATH_SIZE (1024) #define MAX_CONDITIONAL_LEVEL (32) /* // htp task structure // // (the word "task" is not to be confused with the traditional operating system // term ... it is used here to represent all the information associated with // the particular job at hand, which is reading in a file, writing out to // a file, and maintaining information during the entire operation) */ typedef struct tagTASK { STREAM *infile; STREAM *outfile; VARSTORE *varstore; const char *sourceFilename; uint conditionalLevel; uint conditionalLine[MAX_CONDITIONAL_LEVEL]; } TASK; /* // markup processor function and array association structure */ typedef uint (*MARKUP_FUNC)(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext); typedef struct tagMARKUP_PROCESSORS { const char *tag; uint markupType; MARKUP_FUNC markupFunc; } MARKUP_PROCESSORS; /* // template file name (used internally to store name for post-processing) // use squirrelly characters and a space to avoid conflicting with // user names */ extern const char *VAR_TEMPLATE_NAME; /* // forward references */ BOOL ProcessTask(TASK *task); BOOL OptionCallback(const char *name, const char *value, ulong userParam); /* // the user can configure what kind of characters to use to surround htp // markups, to avoid conflicts with HTML markups ... default is the standard // greater-than/less-than bracketing, but also acceptable are square // brackets and curly brackets (parentheses are just too common in normal // text to be useful) // // Because htp also processes standard HTML markups, a IS_OPEN_MARKUP and // IS_CLOSE_MARKUP macros are used instead of standard comparisons ... watch // out for side-effects // // MARKUP_TYPE_ANY is used for markup processors to define they are // interested in either kind of markup (currently unused) // // MARKUP_OPEN_DELIM and MARKUP_CLOSE_DELIM are used to return the proper // delimiter given the markup type */ #define HTML_OPEN_MARKUP ('<') #define HTML_CLOSE_MARKUP ('>') extern char htpOpenMarkup; extern char htpCloseMarkup; #define IS_OPEN_MARKUP(c) (((c) == '<') || ((c) == htpOpenMarkup)) #define IS_CLOSE_MARKUP(c) (((c) == '>') || ((c) == htpCloseMarkup)) #define MARKUP_TYPE_HTML (0x0001) #define MARKUP_TYPE_HTP (0x0002) #define MARKUP_TYPE_ANY (0xFFFF) #define MARKUP_OPEN_DELIM(t) \ (((t) & MARKUP_TYPE_HTP) ? htpOpenMarkup : HTML_OPEN_MARKUP) #define MARKUP_CLOSE_DELIM(t) \ (((t) & MARKUP_TYPE_HTP) ? htpCloseMarkup : HTML_CLOSE_MARKUP) /* // include file search path */ extern char searchPath[SEARCH_PATH_SIZE]; #endif htp-1.19/src/macro.c0000664000175000017500000005457712525674213014462 0ustar hoenickehoenicke/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* // // macro.c // // specialized markup processors // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #include "macro.h" #include "defs.h" #include "def-proc.h" /* // specialized markup processors */ #include "option.h" #include "image-proc.h" #include "file-proc.h" #include "def-proc.h" #include "use-proc.h" #include "set-proc.h" #include "bool-proc.h" #include "misc-proc.h" #include "while-proc.h" static MARKUP_PROCESSORS markupProcessor[] = { { "IMG", MARKUP_TYPE_HTML, ImageProcessor }, { "OPT", MARKUP_TYPE_HTP, OptionProcessor }, { "FILE", MARKUP_TYPE_HTP, FileProcessor }, { "INC", MARKUP_TYPE_HTP, IncProcessor }, { "SET", MARKUP_TYPE_HTP, SetProcessor }, { "BLOCK", MARKUP_TYPE_HTP, BlockProcessor }, { "BLOCKDEF", MARKUP_TYPE_HTP, BlockProcessor }, { "USE", MARKUP_TYPE_HTP, UseProcessor }, { "IF", MARKUP_TYPE_HTP, BooleanProcessor }, { "/IF", MARKUP_TYPE_HTP, BooleanProcessor }, { "IFNOT", MARKUP_TYPE_HTP, ConditionalWarning }, { "ELSE", MARKUP_TYPE_HTP, BooleanProcessor }, { "ELSEIF", MARKUP_TYPE_HTP, BooleanProcessor }, { "/HEAD", MARKUP_TYPE_HTML, HeadProcessor }, { "UNSET", MARKUP_TYPE_HTP, UnsetProcessor }, { "PRE", MARKUP_TYPE_HTML, PreProcessor }, { "/PRE", MARKUP_TYPE_HTML, PreProcessor }, { "ALTTEXT", MARKUP_TYPE_HTP, AltTextProcessor }, { "DEF", MARKUP_TYPE_HTP, BlockProcessor }, { "OUTPUT", MARKUP_TYPE_HTP, OutputProcessor }, { "UNDEF", MARKUP_TYPE_HTP, UndefProcessor }, { "WHILE", MARKUP_TYPE_HTP, WhileProcessor }, { "/WHILE", MARKUP_TYPE_HTP, WhileProcessor }, { "!---", MARKUP_TYPE_HTP, HtpCommentProcessor }, { "QUOTE", MARKUP_TYPE_HTP, QuoteProcessor }, { "IMAGEURL", MARKUP_TYPE_HTP, ImageUrlProcessor } }; #define MARKUP_PROCESSOR_COUNT (sizeof(markupProcessor)/sizeof(markupProcessor[0])) /* // HTML processing */ static BOOL FindMatchingBrace(TASK *task, const char **text) { const char *textPtr; int braceLevel; textPtr = *text; DEBUG_PRINT(("FindMatchingBrace on %s", textPtr)); assert (*textPtr == '{'); textPtr++; braceLevel = 0; while (TRUE) { switch(*textPtr) { case NUL: HtpMsg(MSG_ERROR, task->infile, "ending brace not found in macro name"); return FALSE; case '}': if (!braceLevel) { *text = textPtr + 1; return TRUE; } braceLevel--; break; case '{': braceLevel++; break; } textPtr++; } } BOOL ExpandMacrosInString(TASK *task, const char *text, char **newText, int *quotes, BOOL *changed) { const char *expansion; char *macro, *newMacro; const char *textPtr; uint expansionLength; uint skipped; uint textLength; int singletonMacro, dummy; BOOL macroChanged, destAlloced; char *destText; uint destTextSize; uint copiedSoFar; assert(task != NULL); assert(text != NULL); assert(newText != NULL); assert(quotes != NULL); assert(changed != NULL); textLength = strlen(text); destText = (char *) text; destTextSize = textLength + 1; destAlloced = FALSE; *changed = FALSE; *newText = destText; /* assume singletonMacro until we find some other text */ singletonMacro = 1; /* loop repeatedly to evaluate the string until no more macros are found */ while ((textPtr = strchr(text, '$')) != NULL) { /* Copy skipped text to destText */ if (textPtr > text) { int len = textPtr - text; if (destAlloced) { memcpy(destText, text, len); } singletonMacro = 0; text += len; textLength -= len; destText += len; } /* skip the '$' */ text++; textLength--; /* process the macro */ /* find the end of the macro name and let textPtr point to it. */ /* macro specified with braces? */ if(*text == '{') { textPtr = text; if (! FindMatchingBrace(task, &textPtr)) { if (destAlloced) { FreeMemory(*newText); } *newText = NULL; return FALSE; } macro = DuplicateSubString(text + 1, textPtr - text - 2); } else if (isalnum(*text) || *text == '_' || *text == '-') { /* start of macro, no braces, copy until first non * alphanumeric (including '_' and '-') character. */ textPtr = text+1; while (isalnum(*textPtr) || *textPtr == '_' || *textPtr == '-') textPtr++; macro = DuplicateSubString(text, textPtr - text); } else { /* macro-name consisting of a single control character. */ int len = ((*text == NUL) ? 0 : 1); textPtr = text + len; macro = DuplicateSubString(text, len); } /* skip macro name */ skipped = textPtr - text; text = textPtr; textLength -= skipped; if (strcmp(macro, "$") == 0) { /* special case, expand $$ to $. */ expansion = "$"; expansionLength = 1; } else { uint type; /* Recursivly expand macro */ if (!ExpandMacrosInString(task, macro, &newMacro, &dummy, ¯oChanged)) { FreeMemory(macro); if (destAlloced) { FreeMemory(*newText); } *newText = NULL; return FALSE; } if (macroChanged) { FreeMemory(macro); macro = newMacro; } /* make sure variable exists in store */ if(VariableExists(task->varstore, macro) != TRUE) { HtpMsg(MSG_ERROR, task->infile, "unrecognized macro name \"%s\"", macro); FreeMemory(macro); if (destAlloced) { FreeMemory(*newText); } *newText = NULL; return FALSE; } type = GetVariableType(task->varstore, macro); /* block macros need a special expand routine */ if (type == VAR_TYPE_BLOCK_MACRO) { STREAM *blockFile = (STREAM*) GetVariableValue(task->varstore, macro); assert(blockFile->sflags == STREAM_FLAG_BUFFER); expansion = blockFile->u.buffer.buffer; expansionLength = blockFile->u.buffer.offset; } else if (type == VAR_TYPE_SET_MACRO) { /* get the macros value and replace the attribute value */ expansion = GetVariableValue(task->varstore, macro); if (expansion == NULL) expansion = ""; expansionLength = strlen(expansion); } else { if (destAlloced) { FreeMemory(*newText); } *newText = NULL; HtpMsg(MSG_ERROR, task->infile, "macro \"%s\" is a meta-tag", macro); FreeMemory(macro); return FALSE; } HtpMsg(MSG_INFO, task->infile, "expanding macro \"%s\" to \"%s\"", macro, expansion); } FreeMemory(macro); destTextSize += expansionLength - skipped - 1; if (expansionLength > skipped || !destAlloced) { copiedSoFar = destText - *newText; destText = AllocMemory(destTextSize); if (destText == NULL) { if (destAlloced) { FreeMemory(*newText); } *newText = NULL; HtpMsg(MSG_ERROR, task->infile, "Out of memory"); return FALSE; } memcpy(destText, *newText, copiedSoFar); if (destAlloced) { FreeMemory(*newText); } *newText = destText; destText += copiedSoFar; destAlloced = TRUE; } /* Macro did not change, copy it directly */ memcpy(destText, expansion, expansionLength); destText += expansionLength; /* increment the change count */ *changed = TRUE; if (singletonMacro && !textLength) { /* since the macro is the entire value, no harm (and */ /* more robust) to surround it by quotes */ *quotes = QUOTES_DOUBLE; *destText = 0; return TRUE; } /* need to go back and re-evaluate the value for more macros */ } if (destAlloced) { memcpy(destText, text, textLength); destText += textLength; *destText = 0; } return TRUE; } BOOL ExpandMacros(TASK *task, HTML_MARKUP *htmlMarkup) { HTML_ATTRIBUTE *attrib; char *newName, *newValue, *newTag; int quotes; BOOL changed; assert(task != NULL); assert(htmlMarkup != NULL); /* expand any macros in the tags */ if(htmlMarkup->tag != NULL) { if(ExpandMacrosInString(task, htmlMarkup->tag, &newTag, "es, &changed) != TRUE) { return FALSE; } if(changed) { ChangeMarkupTag(htmlMarkup, newTag); } } if (stricmp(htmlMarkup->tag, "WHILE") == 0 || stricmp(htmlMarkup->tag, "!---") == 0) { return TRUE; } /* do the same for all attributes, both name and value */ attrib = htmlMarkup->attrib; while (attrib != NULL) { if(attrib->name != NULL) { if (!ExpandMacrosInString(task, attrib->name, &newName, "es, &changed)) { return FALSE; } if(changed) { ChangeAttributeName(attrib, newName); } } if(attrib->value != NULL) { quotes = attrib->quotes; if (!ExpandMacrosInString(task, attrib->value, &newValue, "es, &changed)) { return FALSE; } if(changed) { ChangeAttributeValue(attrib, newValue, quotes); } } attrib = attrib->next; } return TRUE; } uint ExpandMetatag(TASK *task, HTML_MARKUP *htmlMarkup) { const char *options; char *optionCopy; FIND_TOKEN findToken; char *optionPtr; HTML_ATTRIBUTE *attrib; VARSTORE defVarstore; uint flag; char *value; const char *defName; STREAM *blockStream; STREAM *defStream; STREAM defFile; TASK newTask; BOOL result; BOOL hasWildcard; uint macroType; /* first things first: find the tag in the metatag store */ if(VariableExists(task->varstore, htmlMarkup->tag) == FALSE) { /* don't change a thing */ return MARKUP_OKAY; } /* verify the macro in the store is a metatag definition */ macroType = GetVariableType(task->varstore, htmlMarkup->tag); if(macroType != VAR_TYPE_DEF_MACRO && macroType != VAR_TYPE_BLOCKDEF_MACRO) { return MARKUP_OKAY; } /* get a pointer to the name */ defName = htmlMarkup->tag; /* get the filename the DEF macro is held in */ if ((defStream = (STREAM *) GetVariableValue(task->varstore, defName)) == NULL) { /* this shouldnt be */ HtpMsg(MSG_ERROR, task->infile, "DEF macro \"%s\" was not store properly", defName); return MARKUP_ERROR; } /* get options to compare against markups paramater list */ options = GetVariableParam(task->varstore, defName); /* initialize a local variable store, even if its not used */ InitializeVariableStore(&defVarstore); /* if NULL, then no options allowed */ if (options != NULL) { /* options should be space-delimited, use StringToken() */ if((optionCopy = DuplicateString(options)) == NULL) { HtpMsg(MSG_ERROR, task->infile, "Unable to duplicate option macro (out of memory?)"); DestroyVariableStore(&defVarstore); return MARKUP_ERROR; } hasWildcard = FALSE; /* build array of pointers to null-terminated option */ optionPtr = StringFirstToken(&findToken, optionCopy, " "); while (optionPtr != NULL) { /* ignore multiple spaces */ if (*optionPtr == NUL) continue; if (strcmp(optionPtr, "*") == 0) { hasWildcard = TRUE; } else if ((attrib = UnlinkAttributeInMarkup(htmlMarkup, optionPtr)) != NULL) { /* since this is a good attribute, add it to the * local store */ flag = VAR_FLAG_DEALLOC_NAME | VAR_FLAG_DEALLOC_VALUE; value = attrib->value; if (value == NULL) { value = ""; flag &= ~VAR_FLAG_DEALLOC_VALUE; } if(StoreVariable(&defVarstore, attrib->name, attrib->value, VAR_TYPE_SET_MACRO, flag, NULL, NULL) == FALSE) { HtpMsg(MSG_ERROR, task->infile, "Unable to store local macro for metatag"); DestroyVariableStore(&defVarstore); DestroyAttribute(attrib); FreeMemory(attrib); FreeMemory(optionCopy); return MARKUP_ERROR; } if (attrib->whitespace) FreeMemory(attrib->whitespace); FreeMemory(attrib); } else { char *name = DuplicateString(optionPtr); /* This option is undefined. Add an explicit * undefined value to hide variables with same * name in outer scope. */ if (StoreVariable(&defVarstore, name, NULL, VAR_TYPE_UNKNOWN, VAR_FLAG_DEALLOC_NAME | VAR_FLAG_UNDEFINED, NULL, NULL) == FALSE) { HtpMsg(MSG_ERROR, task->infile, "Unable to store local macro for metatag"); DestroyVariableStore(&defVarstore); FreeMemory(name); FreeMemory(optionCopy); return MARKUP_ERROR; } } optionPtr = StringNextToken(&findToken); } FreeMemory(optionCopy); if (hasWildcard) { uint wildcardLength = 0; char *wildcards; /* get length of wildcard parameter */ attrib = htmlMarkup->attrib; while (attrib != NULL) { wildcardLength += strlen(attrib->name) + 1; if (attrib->value) { wildcardLength += strlen(attrib->value) + 1; if (attrib->quotes) wildcardLength += 2; } attrib = attrib->next; } if (wildcardLength > 0) { /* Build the wildcard string. */ char *ptr; wildcards = AllocMemory(wildcardLength); ptr = wildcards; while ((attrib = htmlMarkup->attrib) != NULL) { ptr = stpcpy(ptr, attrib->name); if (attrib->value) { *ptr++ = '='; if (attrib->quotes == QUOTES_DOUBLE) *ptr++ = '"'; else if (attrib->quotes == QUOTES_SINGLE) *ptr++ = '\''; ptr = stpcpy(ptr, attrib->value); if (attrib->quotes == QUOTES_DOUBLE) *ptr++ = '"'; else if (attrib->quotes == QUOTES_SINGLE) *ptr++ = '\''; } *ptr++ = ' '; htmlMarkup->attrib = attrib->next; DestroyAttribute(attrib); FreeMemory(attrib); } /* Replace last space with NUL to terminate wildcards */ *(ptr-1) = 0; flag = VAR_FLAG_DEALLOC_VALUE; } else { wildcards = ""; flag = VAR_FLAG_NONE; } if(StoreVariable(&defVarstore, "*", wildcards, VAR_TYPE_SET_MACRO, flag, NULL, NULL) == FALSE) { HtpMsg(MSG_ERROR, task->infile, "Unable to store local macro for metatag"); DestroyVariableStore(&defVarstore); if ((flag & VAR_FLAG_DEALLOC_VALUE)) FreeMemory(wildcards); return MARKUP_ERROR; } } } /* If this is a BLOCKDEF macro expand the trailing block into */ /* the macro named block */ if (macroType == VAR_TYPE_BLOCKDEF_MACRO) { blockStream = (STREAM*) AllocMemory(sizeof(STREAM)); if (!ReadinBlock(task, htmlMarkup, blockStream)) { DestroyVariableStore(&defVarstore); return MARKUP_ERROR; } /* store the block file name and the block macro name as a variable */ if(StoreVariable(&defVarstore, "BLOCK", blockStream, VAR_TYPE_BLOCK_MACRO, VAR_FLAG_NONE, NULL, BlockDestructor) == FALSE) { HtpMsg(MSG_ERROR, task->infile, "unable to store macro information (out of memory?)"); DestroyVariableStore(&defVarstore); return MARKUP_ERROR; } } if (htmlMarkup->attrib != NULL) { HtpMsg(MSG_ERROR, task->infile, "%s metatag \"%s\" does not accept a parameter named \"%s\"", macroType == VAR_TYPE_BLOCKDEF_MACRO ? "blockdef" : "def", defName, htmlMarkup->attrib->name); DestroyVariableStore(&defVarstore); return MARKUP_ERROR; } /* expand the DEF macro like a block macro ... */ /* open the file the macro is held in */ if(CreateBufferReader(&defFile, defStream) == FALSE) { HtpMsg(MSG_ERROR, task->infile, "unable to open block for %s metatag \"%s\"", macroType == VAR_TYPE_BLOCKDEF_MACRO ? "blockdef" : "def", defName); DestroyVariableStore(&defVarstore); return MARKUP_ERROR; } HtpMsg(MSG_INFO, task->infile, "dereferencing %s metatag \"%s\"", macroType == VAR_TYPE_BLOCKDEF_MACRO ? "blockdef" : "def", defName); /* build a new task structure */ newTask.infile = &defFile; newTask.outfile = task->outfile; newTask.sourceFilename = task->sourceFilename; if (options != NULL || macroType == VAR_TYPE_BLOCKDEF_MACRO) { /* Put in the defVarstore */ PushVariableStoreContext(task->varstore, &defVarstore); newTask.varstore = &defVarstore; } else { newTask.varstore = task->varstore; } /* process the new input file */ result = ProcessTask(&newTask); /* remove the new context if necessary */ if(newTask.varstore == &defVarstore) { assert(defVarstore.child == NULL); PopVariableStoreContext(&defVarstore); } /* no matter what, destroy the local store */ DestroyVariableStore(&defVarstore); CloseStream(&defFile); if (!result) { /* Error message was already spitted out. However, we should * give a hint where the meta-tag was called. */ HtpMsg(MSG_ERROR, task->infile, "... in metatag \"%s\"", defName); return MARKUP_ERROR; } return DISCARD_MARKUP; } uint ExpandAll(TASK *task, HTML_MARKUP *htmlMarkup, char** newPlaintextPtr, uint markupType) { uint ctr; uint markupResult; if(ExpandMacros(task, htmlMarkup) == FALSE) { /* problem encountered trying to expand macros */ return MARKUP_ERROR; } /* give the metatag processor a chance to expand metatags */ /* this is a little strange, but if MARKUP_OKAY it means the the */ /* metatag processor didnt recognize the tag, and therefore should */ /* be handled by the other processors */ if((markupResult = ExpandMetatag(task, htmlMarkup)) == MARKUP_OKAY) { /* find the first processor that wants to do something with the */ /* markup tag */ for(ctr = 0; ctr < MARKUP_PROCESSOR_COUNT; ctr++) { if(markupProcessor[ctr].markupType & markupType) { if(IsMarkupTag(htmlMarkup, markupProcessor[ctr].tag)) { assert(markupProcessor[ctr].markupFunc != NULL); markupResult = markupProcessor[ctr] .markupFunc(task, htmlMarkup, newPlaintextPtr); break; } } } } /* unless the function requested to use its new markup string, */ /* take the HTML_MARKUP structure and build a new markup */ if((markupResult != NEW_MARKUP) && (markupResult != DISCARD_MARKUP)) { if(MarkupToPlaintext(htmlMarkup, newPlaintextPtr) == FALSE) { HtpMsg(MSG_ERROR, task->infile, "unable to build plain text from markup (out of memory?)"); return MARKUP_ERROR; } } return markupResult; } htp-1.19/src/textfile.c0000664000175000017500000000745712525674213015200 0ustar hoenickehoenicke/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* // // textfile.c // // Text file functions // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #include "htp.h" #include "option.h" BOOL OpenFile(const char *filename, const char *openFlags, TEXTFILE *textFile) { char *os_filename; assert(filename != NULL); assert(openFlags != NULL); assert(textFile != NULL); /* convert the filename to the native machine's format */ /* (MS-DOS to UNIX and vice-versa) */ /* this returns an allocated copy of the string, so it must be freed */ /* when the structure is destroyed */ if((os_filename = ConvertDirDelimiter(filename)) == NULL) { DEBUG_PRINT(("unable to convert dir delimiter")); return FALSE; } /* initialize the rest of the structure */ textFile->emptyLine = TRUE; textFile->pendingSpaces = 0; textFile->flags = TEXTFILE_FLAG_NONE; textFile->file = fopen(os_filename, openFlags); FreeMemory(os_filename); if(textFile->file == NULL) { DEBUG_PRINT(("unable to open file %s", filename)); return FALSE; } return TRUE; } BOOL OpenFD(int filedes, const char *openFlags, TEXTFILE *textFile) { assert(openFlags != NULL); assert(textFile != NULL); /* initialize the rest of the structure */ textFile->emptyLine = TRUE; textFile->pendingSpaces = 0; textFile->flags = TEXTFILE_FLAG_NONE; textFile->file = fdopen(filedes, openFlags); if(textFile->file == NULL) { DEBUG_PRINT(("unable to open fd %d", filedes)); return FALSE; } return TRUE; } void CloseFile(TEXTFILE *textFile) { assert(textFile != NULL); assert(textFile->file != NULL); fclose(textFile->file); textFile->file = NULL; } BOOL GetFileChar(TEXTFILE *textFile, char *ch) { int getCh; assert(textFile != NULL); assert(ch != NULL); assert(textFile->file != NULL); if((getCh = fgetc(textFile->file)) == EOF) { return FALSE; } *ch = (char) getCh; return TRUE; } BOOL PutFileString(TEXTFILE *textFile, const char *str) { char ch; uint pendingSpaces; uint condensing; BOOL emptyLine; assert(textFile != NULL); assert(textFile->file != NULL); condensing = (textFile->flags & TEXTFILE_FLAG_FORCE_CR) != 0 ? OPT_V_FALSE : GetOptionValue(OPT_I_CONDENSE); emptyLine = textFile->emptyLine; pendingSpaces = textFile->pendingSpaces; while ((ch = *str++) != NUL) { if (ch == '\r') continue; if (ch == ' ') { pendingSpaces++; continue; } if (ch == '\n') { /* suppress linefeeds? */ if (condensing == OPT_V_TRUE) { /* Handle newline just as a space. * C/R being dropped between words */ pendingSpaces++; continue; } if (condensing == OPT_V_SEMI) { /* Remove spaces at end of line */ pendingSpaces = 0; /* Remove empty lines */ if (emptyLine) continue; } emptyLine = TRUE; } else { emptyLine = FALSE; } while (pendingSpaces > 0) { fputc(' ', textFile->file); pendingSpaces--; if (condensing == OPT_V_TRUE) pendingSpaces = 0; } fputc(ch, textFile->file); } textFile->emptyLine = emptyLine; textFile->pendingSpaces = pendingSpaces; return TRUE; } htp-1.19/src/option.h0000664000175000017500000000432412525674213014657 0ustar hoenickehoenicke/* // // option.h // // Program options and setting // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #ifndef OPTION_H #define OPTION_H #include "defs.h" /* option names */ #define OPT_I_IMGXY 0 #define OPT_I_MESSAGE 1 #define OPT_I_DEPEND 2 #define OPT_I_PRECIOUS 3 #define OPT_I_CONDENSE 4 #define OPT_I_USAGE 5 #define OPT_I_DELIM 6 #define OPT_I_XML 7 #define OPT_I_COUNT 8 /* option values */ #define OPT_V_FALSE 0 #define OPT_V_TRUE 1 #define OPT_V_SEMI 2 #define OPT_V_DELIM_HTML 3 #define OPT_V_DELIM_SQUARE 4 #define OPT_V_DELIM_CURLY 5 /* maximum length of an option name */ #define MAX_OPTION_LENGTH 32 extern uint *currentOptions; /* these are used at the beginning and end of program execution, respectively */ BOOL InitializeGlobalOption(void); void DestroyGlobalOption(void); /* these are used at the beginning and end of local context, that is, as a new */ /* file is being created and completed */ BOOL InitializeLocalOption(void); void DestroyLocalOption(void); /* parse text or markups for options ... global setting dictates whether to */ /* use current context or default to global option settings */ BOOL ParseToken(TASK *task, const char *string); uint OptionProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext); /* retrieve option information ... IsOptionEnabled() doesnt mean much for */ /* options that require values rather than boolean states, and for boolean */ /* options, GetOptionValue() returns OPT_V_TRUE or OPT_V_FALSE */ #define IsOptionEnabled(i) (currentOptions[i] == OPT_V_TRUE) #define IsOptionValue(i,v) (currentOptions[i] == (v)) #define GetOptionValue(i) (currentOptions[i]) /* macros for quick lookups */ #define IMGXY (IsOptionEnabled(OPT_I_IMGXY)) #define DEPEND (IsOptionEnabled(OPT_I_DEPEND)) #define PRECIOUS (IsOptionEnabled(OPT_I_PRECIOUS)) #define CONDENSE (IsOptionValue(OPT_I_CONDENSE,OPT_V_TRUE)) #define SEMICONDENSE (IsOptionValue(OPT_I_CONDENSE,OPT_V_SEMI)) #define USAGE (IsOptionEnabled(OPT_I_USAGE)) #endif htp-1.19/src/streams.h0000664000175000017500000000354212525674213015026 0ustar hoenickehoenicke/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* // // $Id: streams.h,v 1.5 2002-10-15 12:30:07 hoenicke Exp $ // // file/buffer stream functions // // Copyright (c) 2001 Jochen Hoenicke under Artistic License. // */ #ifndef STREAM_H #define STREAM_H #include "textfile.h" #define STREAM_FLAG_BUFFER 1 #define STREAM_FLAG_NULL_FILE 2 #define STREAM_FLAG_READER 4 #define BITS_PER_UNIT (8*sizeof(unsigned long)) typedef unsigned long bitmap[256 / BITS_PER_UNIT]; #define BITMAP_COFF(c) (((unsigned char)(c))/BITS_PER_UNIT) #define BITMAP_CMASK(c) ((unsigned long)1 << ((c) & (BITS_PER_UNIT-1))) #define BITMAP_SET(b,c) b[BITMAP_COFF(c)] |= BITMAP_CMASK(c) #define BITMAP_GET(b,c) (b[BITMAP_COFF(c)] & BITMAP_CMASK(c)) typedef struct tagSTREAMBUFFER { char *buffer; ulong offset; ulong length; } STREAMBUFFER; typedef struct tagSTREAM { uint sflags; uint lineNumber; const char *name; BOOL hasUnread; char unread; union { TEXTFILE textfile; STREAMBUFFER buffer; } u; } STREAM; BOOL CreateNullWriter (STREAM* stream); BOOL CreateBufferWriter (STREAM* stream, const char *name); BOOL CreateBufferReader (STREAM* stream, STREAM *writeStream); BOOL FlushBufferWriter (STREAM *stream); BOOL CreateFileReader (STREAM *stream, const char *filename); BOOL CreateFDReader (STREAM *stream, const char *filename, int fd); BOOL CreateFileWriter (STREAM *stream, const char *filename, BOOL append); void CloseStream (STREAM *stream); BOOL GetStreamChar(STREAM *stream, char *c); BOOL UnreadStreamChar(STREAM *stream, char c); BOOL GetStreamBlock(STREAM *stream, char *buffer, uint size, char delims[3]); BOOL PutStreamString(STREAM *stram, const char *buffer); BOOL StreamPrintF(STREAM *stream, const char *format, ...); void ForceLinefeeds(STREAM *stream, BOOL forced); #endif htp-1.19/src/gif.h0000664000175000017500000000056012525674213014112 0ustar hoenickehoenicke/* // // gif.h // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #ifndef GIF_H #define GIF_H /* GIF format detected? */ BOOL GifFormatFound(FILE *file); /* get image dimensions */ BOOL GifReadDimensions(FILE *file, DWORD *height, DWORD *width); #endif htp-1.19/src/snprintf.c0000664000175000017500000006010212525674213015201 0ustar hoenickehoenicke/* * NOTE: If you change this file, please merge it into rsync, samba, etc. */ /* * Copyright Patrick Powell 1995 * This code is based on code written by Patrick Powell (papowell@astart.com) * It may be used for any purpose as long as this notice remains intact * on all source code distributions */ /************************************************************** * Original: * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 * A bombproof version of doprnt (dopr) included. * Sigh. This sort of thing is always nasty do deal with. Note that * the version here does not include floating point... * * snprintf() is used instead of sprintf() as it does limit checks * for string length. This covers a nasty loophole. * * The other functions are there to prevent NULL pointers from * causing nast effects. * * More Recently: * Brandon Long 9/15/96 for mutt 0.43 * This was ugly. It is still ugly. I opted out of floating point * numbers, but the formatter understands just about everything * from the normal C string format, at least as far as I can tell from * the Solaris 2.5 printf(3S) man page. * * Brandon Long 10/22/97 for mutt 0.87.1 * Ok, added some minimal floating point support, which means this * probably requires libm on most operating systems. Don't yet * support the exponent (e,E) and sigfig (g,G). Also, fmtint() * was pretty badly broken, it just wasn't being exercised in ways * which showed it, so that's been fixed. Also, formated the code * to mutt conventions, and removed dead code left over from the * original. Also, there is now a builtin-test, just compile with: * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm * and run snprintf for results. * * Thomas Roessler 01/27/98 for mutt 0.89i * The PGP code was using unsigned hexadecimal formats. * Unfortunately, unsigned formats simply didn't work. * * Michael Elkins 03/05/98 for mutt 0.90.8 * The original code assumed that both snprintf() and vsnprintf() were * missing. Some systems only have snprintf() but not vsnprintf(), so * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. * * Andrew Tridgell (tridge@samba.org) Oct 1998 * fixed handling of %.0f * added test for HAVE_LONG_DOUBLE * * tridge@samba.org, idra@samba.org, April 2001 * got rid of fcvt code (twas buggy and made testing harder) * added C99 semantics * * date: 2002/12/19 19:56:31; author: herb; state: Exp; lines: +2 -0 * actually print args for %g and %e * * date: 2002/06/03 13:37:52; author: jmcd; state: Exp; lines: +8 -0 * Since includes.h isn't included here, VA_COPY has to be defined here. I don't * see any include file that is guaranteed to be here, so I'm defining it * locally. Fixes AIX and Solaris builds. * * date: 2002/06/03 03:07:24; author: tridge; state: Exp; lines: +5 -13 * put the ifdef for HAVE_VA_COPY in one place rather than in lots of * functions * * date: 2002/05/17 14:51:22; author: jmcd; state: Exp; lines: +21 -4 * Fix usage of va_list passed as an arg. Use __va_copy before using it * when it exists. * * date: 2002/04/16 22:38:04; author: idra; state: Exp; lines: +20 -14 * Fix incorrect zpadlen handling in fmtfp. * Thanks to Ollie Oldham for spotting it. * few mods to make it easier to compile the tests. * addedd the "Ollie" test to the floating point ones. * * Martin Pool (mbp@samba.org) April 2003 * Remove NO_CONFIG_H so that the test case can be built within a source * tree with less trouble. * Remove unnecessary SAFE_FREE() definition. * * Martin Pool (mbp@samba.org) May 2003 * Put in a prototype for dummy_snprintf() to quiet compiler warnings. * * Move #endif to make sure VA_COPY, LDOUBLE, etc are defined even * if the C library has some snprintf functions already. **************************************************************/ /* Change by Jochen Hoenicke, Oct 2003: deautoconfigured :) */ #define HAVE_STRING_H #define HAVE_CTYPE_H #define HAVE_STDLIB_H #ifdef PREFER_PORTABLE_SNPRINTF #undef HAVE_SNPRINTF #define snprintf portable_snprintf #define vsnprintf portable_vsnprintf #endif #ifdef HAVE_SNPRINTF #define HAVE_VSNPRINTF #define HAVE_C99_VSNPRINTF #endif #ifdef TEST_SNPRINTF /* need math library headers for testing */ /* In test mode, we pretend that this system doesn't have any snprintf * functions, regardless of what config.h says. */ # undef HAVE_SNPRINTF # undef HAVE_VSNPRINTF # undef HAVE_C99_VSNPRINTF # undef HAVE_ASPRINTF # undef HAVE_VASPRINTF # include #endif /* TEST_SNPRINTF */ #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_STRINGS_H #include #endif #ifdef HAVE_CTYPE_H #include #endif #include #include #ifdef HAVE_STDLIB_H #include #endif #if defined(HAVE_SNPRINTF) && defined(HAVE_VSNPRINTF) && defined(HAVE_C99_VSNPRINTF) /* only include stdio.h if we are not re-defining snprintf or vsnprintf */ #include /* make the compiler happy with an empty file */ void dummy_snprintf(void); void dummy_snprintf(void) {} #endif /* HAVE_SNPRINTF, etc */ #ifdef HAVE_LONG_DOUBLE #define LDOUBLE long double #else #define LDOUBLE double #endif #ifdef HAVE_LONG_LONG #define LLONG long long #else #define LLONG long #endif #ifndef VA_COPY #ifdef HAVE_VA_COPY #define VA_COPY(dest, src) va_copy(dest, src) #else #ifdef HAVE___VA_COPY #define VA_COPY(dest, src) __va_copy(dest, src) #else #define VA_COPY(dest, src) (dest) = (src) #endif #endif /* * dopr(): poor man's version of doprintf */ /* format read states */ #define DP_S_DEFAULT 0 #define DP_S_FLAGS 1 #define DP_S_MIN 2 #define DP_S_DOT 3 #define DP_S_MAX 4 #define DP_S_MOD 5 #define DP_S_CONV 6 #define DP_S_DONE 7 /* format flags - Bits */ #define DP_F_MINUS (1 << 0) #define DP_F_PLUS (1 << 1) #define DP_F_SPACE (1 << 2) #define DP_F_NUM (1 << 3) #define DP_F_ZERO (1 << 4) #define DP_F_UP (1 << 5) #define DP_F_UNSIGNED (1 << 6) /* Conversion Flags */ #define DP_C_SHORT 1 #define DP_C_LONG 2 #define DP_C_LDOUBLE 3 #define DP_C_LLONG 4 #define char_to_int(p) ((p)- '0') #ifndef MAX #define MAX(p,q) (((p) >= (q)) ? (p) : (q)) #endif /* yes this really must be a ||. Don't muck with this (tridge) */ #if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF) static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args_in); static void fmtstr(char *buffer, size_t *currlen, size_t maxlen, char *value, int flags, int min, int max); static void fmtint(char *buffer, size_t *currlen, size_t maxlen, long value, int base, int min, int max, int flags); static void fmtfp(char *buffer, size_t *currlen, size_t maxlen, LDOUBLE fvalue, int min, int max, int flags); static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c); static size_t dopr(char *buffer, size_t maxlen, const char *format, va_list args_in) { char ch; LLONG value; LDOUBLE fvalue; char *strvalue; int min; int max; int state; int flags; int cflags; size_t currlen; va_list args; VA_COPY(args, args_in); state = DP_S_DEFAULT; currlen = flags = cflags = min = 0; max = -1; ch = *format++; while (state != DP_S_DONE) { if (ch == '\0') state = DP_S_DONE; switch(state) { case DP_S_DEFAULT: if (ch == '%') state = DP_S_FLAGS; else dopr_outch (buffer, &currlen, maxlen, ch); ch = *format++; break; case DP_S_FLAGS: switch (ch) { case '-': flags |= DP_F_MINUS; ch = *format++; break; case '+': flags |= DP_F_PLUS; ch = *format++; break; case ' ': flags |= DP_F_SPACE; ch = *format++; break; case '#': flags |= DP_F_NUM; ch = *format++; break; case '0': flags |= DP_F_ZERO; ch = *format++; break; default: state = DP_S_MIN; break; } break; case DP_S_MIN: if (isdigit((unsigned char)ch)) { min = 10*min + char_to_int (ch); ch = *format++; } else if (ch == '*') { min = va_arg (args, int); ch = *format++; state = DP_S_DOT; } else { state = DP_S_DOT; } break; case DP_S_DOT: if (ch == '.') { state = DP_S_MAX; ch = *format++; } else { state = DP_S_MOD; } break; case DP_S_MAX: if (isdigit((unsigned char)ch)) { if (max < 0) max = 0; max = 10*max + char_to_int (ch); ch = *format++; } else if (ch == '*') { max = va_arg (args, int); ch = *format++; state = DP_S_MOD; } else { state = DP_S_MOD; } break; case DP_S_MOD: switch (ch) { case 'h': cflags = DP_C_SHORT; ch = *format++; break; case 'l': cflags = DP_C_LONG; ch = *format++; if (ch == 'l') { /* It's a long long */ cflags = DP_C_LLONG; ch = *format++; } break; case 'L': cflags = DP_C_LDOUBLE; ch = *format++; break; default: break; } state = DP_S_CONV; break; case DP_S_CONV: switch (ch) { case 'd': case 'i': if (cflags == DP_C_SHORT) value = va_arg (args, int); else if (cflags == DP_C_LONG) value = va_arg (args, long int); else if (cflags == DP_C_LLONG) value = va_arg (args, LLONG); else value = va_arg (args, int); fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); break; case 'o': flags |= DP_F_UNSIGNED; if (cflags == DP_C_SHORT) value = va_arg (args, unsigned int); else if (cflags == DP_C_LONG) value = (long)va_arg (args, unsigned long int); else if (cflags == DP_C_LLONG) value = (long)va_arg (args, unsigned LLONG); else value = (long)va_arg (args, unsigned int); fmtint (buffer, &currlen, maxlen, value, 8, min, max, flags); break; case 'u': flags |= DP_F_UNSIGNED; if (cflags == DP_C_SHORT) value = va_arg (args, unsigned int); else if (cflags == DP_C_LONG) value = (long)va_arg (args, unsigned long int); else if (cflags == DP_C_LLONG) value = (LLONG)va_arg (args, unsigned LLONG); else value = (long)va_arg (args, unsigned int); fmtint (buffer, &currlen, maxlen, value, 10, min, max, flags); break; case 'X': flags |= DP_F_UP; case 'x': flags |= DP_F_UNSIGNED; if (cflags == DP_C_SHORT) value = va_arg (args, unsigned int); else if (cflags == DP_C_LONG) value = (long)va_arg (args, unsigned long int); else if (cflags == DP_C_LLONG) value = (LLONG)va_arg (args, unsigned LLONG); else value = (long)va_arg (args, unsigned int); fmtint (buffer, &currlen, maxlen, value, 16, min, max, flags); break; case 'f': if (cflags == DP_C_LDOUBLE) fvalue = va_arg (args, LDOUBLE); else fvalue = va_arg (args, double); /* um, floating point? */ fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); break; case 'E': flags |= DP_F_UP; case 'e': if (cflags == DP_C_LDOUBLE) fvalue = va_arg (args, LDOUBLE); else fvalue = va_arg (args, double); fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); break; case 'G': flags |= DP_F_UP; case 'g': if (cflags == DP_C_LDOUBLE) fvalue = va_arg (args, LDOUBLE); else fvalue = va_arg (args, double); fmtfp (buffer, &currlen, maxlen, fvalue, min, max, flags); break; case 'c': dopr_outch (buffer, &currlen, maxlen, va_arg (args, int)); break; case 's': strvalue = va_arg (args, char *); if (!strvalue) strvalue = "(NULL)"; if (max == -1) { max = strlen(strvalue); } if (min > 0 && max >= 0 && min > max) max = min; fmtstr (buffer, &currlen, maxlen, strvalue, flags, min, max); break; case 'p': strvalue = va_arg (args, void *); fmtint (buffer, &currlen, maxlen, (long) strvalue, 16, min, max, flags); break; case 'n': if (cflags == DP_C_SHORT) { short int *num; num = va_arg (args, short int *); *num = currlen; } else if (cflags == DP_C_LONG) { long int *num; num = va_arg (args, long int *); *num = (long int)currlen; } else if (cflags == DP_C_LLONG) { LLONG *num; num = va_arg (args, LLONG *); *num = (LLONG)currlen; } else { int *num; num = va_arg (args, int *); *num = currlen; } break; case '%': dopr_outch (buffer, &currlen, maxlen, ch); break; case 'w': /* not supported yet, treat as next char */ ch = *format++; break; default: /* Unknown, skip */ break; } ch = *format++; state = DP_S_DEFAULT; flags = cflags = min = 0; max = -1; break; case DP_S_DONE: break; default: /* hmm? */ break; /* some picky compilers need this */ } } if (maxlen != 0) { if (currlen < maxlen - 1) buffer[currlen] = '\0'; else if (maxlen > 0) buffer[maxlen - 1] = '\0'; } return currlen; } static void fmtstr(char *buffer, size_t *currlen, size_t maxlen, char *value, int flags, int min, int max) { int padlen, strln; /* amount to pad */ int cnt = 0; #ifdef DEBUG_SNPRINTF printf("fmtstr min=%d max=%d s=[%s]\n", min, max, value); #endif if (value == 0) { value = ""; } for (strln = 0; value[strln]; ++strln); /* strlen */ padlen = min - strln; if (padlen < 0) padlen = 0; if (flags & DP_F_MINUS) padlen = -padlen; /* Left Justify */ while ((padlen > 0) && (cnt < max)) { dopr_outch (buffer, currlen, maxlen, ' '); --padlen; ++cnt; } while (*value && (cnt < max)) { dopr_outch (buffer, currlen, maxlen, *value++); ++cnt; } while ((padlen < 0) && (cnt < max)) { dopr_outch (buffer, currlen, maxlen, ' '); ++padlen; ++cnt; } } /* Have to handle DP_F_NUM (ie 0x and 0 alternates) */ static void fmtint(char *buffer, size_t *currlen, size_t maxlen, long value, int base, int min, int max, int flags) { int signvalue = 0; unsigned long uvalue; char convert[20]; int place = 0; int spadlen = 0; /* amount to space pad */ int zpadlen = 0; /* amount to zero pad */ int caps = 0; if (max < 0) max = 0; uvalue = value; if(!(flags & DP_F_UNSIGNED)) { if( value < 0 ) { signvalue = '-'; uvalue = -value; } else { if (flags & DP_F_PLUS) /* Do a sign (+/i) */ signvalue = '+'; else if (flags & DP_F_SPACE) signvalue = ' '; } } if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ do { convert[place++] = (caps? "0123456789ABCDEF":"0123456789abcdef") [uvalue % (unsigned)base ]; uvalue = (uvalue / (unsigned)base ); } while(uvalue && (place < 20)); if (place == 20) place--; convert[place] = 0; zpadlen = max - place; spadlen = min - MAX (max, place) - (signvalue ? 1 : 0); if (zpadlen < 0) zpadlen = 0; if (spadlen < 0) spadlen = 0; if (flags & DP_F_ZERO) { zpadlen = MAX(zpadlen, spadlen); spadlen = 0; } if (flags & DP_F_MINUS) spadlen = -spadlen; /* Left Justifty */ #ifdef DEBUG_SNPRINTF printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n", zpadlen, spadlen, min, max, place); #endif /* Spaces */ while (spadlen > 0) { dopr_outch (buffer, currlen, maxlen, ' '); --spadlen; } /* Sign */ if (signvalue) dopr_outch (buffer, currlen, maxlen, signvalue); /* Zeros */ if (zpadlen > 0) { while (zpadlen > 0) { dopr_outch (buffer, currlen, maxlen, '0'); --zpadlen; } } /* Digits */ while (place > 0) dopr_outch (buffer, currlen, maxlen, convert[--place]); /* Left Justified spaces */ while (spadlen < 0) { dopr_outch (buffer, currlen, maxlen, ' '); ++spadlen; } } static LDOUBLE abs_val(LDOUBLE value) { LDOUBLE result = value; if (value < 0) result = -value; return result; } static LDOUBLE POW10(int exp) { LDOUBLE result = 1; while (exp) { result *= 10; exp--; } return result; } static LLONG ROUND(LDOUBLE value) { LLONG intpart; intpart = (LLONG)value; value = value - intpart; if (value >= 0.5) intpart++; return intpart; } /* a replacement for modf that doesn't need the math library. Should be portable, but slow */ static double my_modf(double x0, double *iptr) { int i; long l; double x = x0; double f = 1.0; for (i=0;i<100;i++) { l = (long)x; if (l <= (x+1) && l >= (x-1)) break; x *= 0.1; f *= 10.0; } if (i == 100) { /* yikes! the number is beyond what we can handle. What do we do? */ (*iptr) = 0; return 0; } if (i != 0) { double i2; double ret; ret = my_modf(x0-l*f, &i2); (*iptr) = l*f + i2; return ret; } (*iptr) = l; return x - (*iptr); } static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, LDOUBLE fvalue, int min, int max, int flags) { int signvalue = 0; double ufvalue; char iconvert[311]; char fconvert[311]; int iplace = 0; int fplace = 0; int padlen = 0; /* amount to pad */ int zpadlen = 0; int caps = 0; int idx; double intpart; double fracpart; double temp; /* * AIX manpage says the default is 0, but Solaris says the default * is 6, and sprintf on AIX defaults to 6 */ if (max < 0) max = 6; ufvalue = abs_val (fvalue); if (fvalue < 0) { signvalue = '-'; } else { if (flags & DP_F_PLUS) { /* Do a sign (+/i) */ signvalue = '+'; } else { if (flags & DP_F_SPACE) signvalue = ' '; } } #if 0 if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ #endif #if 0 if (max == 0) ufvalue += 0.5; /* if max = 0 we must round */ #endif /* * Sorry, we only support 16 digits past the decimal because of our * conversion method */ if (max > 16) max = 16; /* We "cheat" by converting the fractional part to integer by * multiplying by a factor of 10 */ temp = ufvalue; my_modf(temp, &intpart); fracpart = ROUND((POW10(max)) * (ufvalue - intpart)); if (fracpart >= POW10(max)) { intpart++; fracpart -= POW10(max); } /* Convert integer part */ do { temp = intpart*0.1; my_modf(temp, &intpart); idx = (int) ((temp -intpart +0.05)* 10.0); /* idx = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */ /* printf ("%llf, %f, %x\n", temp, intpart, idx); */ iconvert[iplace++] = (caps? "0123456789ABCDEF":"0123456789abcdef")[idx]; } while (intpart && (iplace < 311)); if (iplace == 311) iplace--; iconvert[iplace] = 0; /* Convert fractional part */ if (fracpart) { do { temp = fracpart*0.1; my_modf(temp, &fracpart); idx = (int) ((temp -fracpart +0.05)* 10.0); /* idx = (int) ((((temp/10) -fracpart) +0.05) *10); */ /* printf ("%lf, %lf, %ld\n", temp, fracpart, idx ); */ fconvert[fplace++] = (caps? "0123456789ABCDEF":"0123456789abcdef")[idx]; } while(fracpart && (fplace < 311)); if (fplace == 311) fplace--; } fconvert[fplace] = 0; /* -1 for decimal point, another -1 if we are printing a sign */ padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); zpadlen = max - fplace; if (zpadlen < 0) zpadlen = 0; if (padlen < 0) padlen = 0; if (flags & DP_F_MINUS) padlen = -padlen; /* Left Justifty */ if ((flags & DP_F_ZERO) && (padlen > 0)) { if (signvalue) { dopr_outch (buffer, currlen, maxlen, signvalue); --padlen; signvalue = 0; } while (padlen > 0) { dopr_outch (buffer, currlen, maxlen, '0'); --padlen; } } while (padlen > 0) { dopr_outch (buffer, currlen, maxlen, ' '); --padlen; } if (signvalue) dopr_outch (buffer, currlen, maxlen, signvalue); while (iplace > 0) dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]); #ifdef DEBUG_SNPRINTF printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen); #endif /* * Decimal point. This should probably use locale to find the correct * char to print out. */ if (max > 0) { dopr_outch (buffer, currlen, maxlen, '.'); while (zpadlen > 0) { dopr_outch (buffer, currlen, maxlen, '0'); --zpadlen; } while (fplace > 0) dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]); } while (padlen < 0) { dopr_outch (buffer, currlen, maxlen, ' '); ++padlen; } } static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c) { if (*currlen < maxlen) { buffer[(*currlen)] = c; } (*currlen)++; } int vsnprintf (char *str, size_t count, const char *fmt, va_list args) { return dopr(str, count, fmt, args); } #endif /* yes this really must be a ||. Don't muck with this (tridge) * * The logic for these two is that we need our own definition if the * OS *either* has no definition of *sprintf, or if it does have one * that doesn't work properly according to the autoconf test. */ #if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF) int snprintf(char *str,size_t count,const char *fmt,...) { size_t ret; va_list ap; va_start(ap, fmt); ret = vsnprintf(str, count, fmt, ap); va_end(ap); return ret; } #endif #endif #ifdef NEED_ASPRINTF #ifndef HAVE_VASPRINTF int vasprintf(char **ptr, const char *format, va_list ap) { int ret; va_list ap2; VA_COPY(ap2, ap); ret = vsnprintf(NULL, 0, format, ap2); if (ret <= 0) return ret; (*ptr) = (char *)malloc(ret+1); if (!*ptr) return -1; VA_COPY(ap2, ap); ret = vsnprintf(*ptr, ret+1, format, ap2); return ret; } #endif #ifndef HAVE_ASPRINTF int asprintf(char **ptr, const char *format, ...) { va_list ap; int ret; *ptr = NULL; va_start(ap, format); ret = vasprintf(ptr, format, ap); va_end(ap); return ret; } #endif #endif #ifdef TEST_SNPRINTF int sprintf(char *str,const char *fmt,...); int main (void) { char buf1[1024]; char buf2[1024]; char *fp_fmt[] = { "%1.1f", "%-1.5f", "%1.5f", "%123.9f", "%10.5f", "% 10.5f", "%+22.9f", "%+4.9f", "%01.3f", "%4f", "%3.1f", "%3.2f", "%.0f", "%f", "-16.16f", NULL }; double fp_nums[] = { 6442452944.1234, -1.5, 134.21, 91340.2, 341.1234, 203.9, 0.96, 0.996, 0.9996, 1.996, 4.136, 5.030201, 0.00205, /* END LIST */ 0}; char *int_fmt[] = { "%-1.5d", "%1.5d", "%123.9d", "%5.5d", "%10.5d", "% 10.5d", "%+22.33d", "%01.3d", "%4d", "%d", NULL }; long int_nums[] = { -1, 134, 91340, 341, 0203, 0}; char *str_fmt[] = { "10.5s", "5.10s", "10.1s", "0.10s", "10.0s", "1.10s", "%s", "%.1s", "%.10s", "%10s", NULL }; char *str_vals[] = {"hello", "a", "", "a longer string", NULL}; int x, y; int fail = 0; int num = 0; printf ("Testing snprintf format codes against system sprintf...\n"); for (x = 0; fp_fmt[x] ; x++) { for (y = 0; fp_nums[y] != 0 ; y++) { int l1 = snprintf(NULL, 0, fp_fmt[x], fp_nums[y]); int l2 = snprintf(buf1, sizeof(buf1), fp_fmt[x], fp_nums[y]); sprintf (buf2, fp_fmt[x], fp_nums[y]); if (strcmp (buf1, buf2)) { printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n", fp_fmt[x], buf1, buf2); fail++; } if (l1 != l2) { printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, fp_fmt[x]); fail++; } num++; } } for (x = 0; int_fmt[x] ; x++) { for (y = 0; int_nums[y] != 0 ; y++) { int l1 = snprintf(NULL, 0, int_fmt[x], int_nums[y]); int l2 = snprintf(buf1, sizeof(buf1), int_fmt[x], int_nums[y]); sprintf (buf2, int_fmt[x], int_nums[y]); if (strcmp (buf1, buf2)) { printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n", int_fmt[x], buf1, buf2); fail++; } if (l1 != l2) { printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, int_fmt[x]); fail++; } num++; } } for (x = 0; str_fmt[x] ; x++) { for (y = 0; str_vals[y] != 0 ; y++) { int l1 = snprintf(NULL, 0, str_fmt[x], str_vals[y]); int l2 = snprintf(buf1, sizeof(buf1), str_fmt[x], str_vals[y]); sprintf (buf2, str_fmt[x], str_vals[y]); if (strcmp (buf1, buf2)) { printf("snprintf doesn't match Format: %s\n\tsnprintf = [%s]\n\t sprintf = [%s]\n", str_fmt[x], buf1, buf2); fail++; } if (l1 != l2) { printf("snprintf l1 != l2 (%d %d) %s\n", l1, l2, str_fmt[x]); fail++; } num++; } } printf ("%d tests failed out of %d.\n", fail, num); printf("seeing how many digits we support\n"); { double v0 = 0.12345678901234567890123456789012345678901; for (x=0; x<100; x++) { double p = pow(10, x); double r = v0*p; snprintf(buf1, sizeof(buf1), "%1.1f", r); sprintf(buf2, "%1.1f", r); if (strcmp(buf1, buf2)) { printf("we seem to support %d digits\n", x-1); break; } } } return 0; } #endif /* TEST_SNPRINTF */ htp-1.19/src/while-proc.c0000664000175000017500000001214612525674213015414 0ustar hoenickehoenicke/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* // // bool-proc.c // // specialized markup processors // // Copyright (c) 1995-96 Jim Nelson. Permission to distribute // granted by the author. No warranties are made on the fitness of this // source code. // */ #include "while-proc.h" #include "defs.h" #include "def-proc.h" #include "htp-files.h" #include "macro.h" BOOL ConditionValue(TASK *task, HTML_ATTRIBUTE *attrib, BOOL notTagFound) { char *name; int quotes; BOOL changed; BOOL condTrue; const char* value; char *attribValue; uint type; if (!ExpandMacrosInString(task, attrib->name, &name, "es, &changed)) { return ERROR; } HtpMsg(MSG_INFO, task->infile, "while loop check %s", name); /* get the macros associated value (NULL if macro not defined) */ if((value = GetVariableValue(task->varstore, name)) != NULL) { type = GetVariableType(task->varstore, name); } else { type = VAR_TYPE_SET_MACRO; } if (changed) FreeMemory(name); /* if only a name is specified, only care if macro is defined */ if(attrib->value == NULL) { condTrue = (value != NULL) ? TRUE : FALSE; } else { /* macro value comparison */ if(type == VAR_TYPE_SET_MACRO) { /* macro comparison (case-sensitive) */ if (!ExpandMacrosInString(task, attrib->value, &attribValue, "es, &changed)) { return ERROR; } condTrue = (value != NULL && strcmp(value, attribValue) == 0); if (changed) FreeMemory(attribValue); } else { /* block macro, comparisons not allowed */ condTrue = FALSE; } } /* reverse conditional if NOT attribute found */ if(notTagFound == TRUE) { condTrue = (condTrue == TRUE) ? FALSE : TRUE; } return condTrue; } BOOL ProcessWhileBlock(TASK *task, STREAM* blockStream) { TASK newTask; BOOL result; HtpMsg(MSG_INFO, task->infile, "expanding WHILE loop"); /* build a new task structure */ newTask.infile = blockStream; newTask.outfile = task->outfile; newTask.sourceFilename = task->sourceFilename; newTask.varstore = task->varstore; /* process the new input file */ result = ProcessTask(&newTask); CloseStream(blockStream); return result; } uint WhileProcessor(TASK *task, HTML_MARKUP *htmlMarkup, char **newPlaintext) { static uint whileLevel = 0; BOOL condTrue; BOOL notTagFound; STREAM blockFile; STREAM inFile; HTML_ATTRIBUTE *attrib; UNREF_PARAM(newPlaintext); condTrue = FALSE; /* conditionalLevel keeps track of boolean depth */ if(whileLevel == 0) { if((IsMarkupTag(htmlMarkup, "/WHILE"))) { HtpMsg(MSG_ERROR, task->infile, "while block must start with WHILE tag"); return MARKUP_ERROR; } } if(IsMarkupTag(htmlMarkup, "WHILE")) { whileLevel++; /* this is an ugly way to handle the IF-IF NOT test, but will need */ /* be cleaned up in the future */ notTagFound = UnlinkBoolAttributeInMarkup(htmlMarkup, "NOT"); /* should be exactly one remaining attribute in markup */ attrib = htmlMarkup->attrib; if (attrib == NULL) { HtpMsg(MSG_ERROR, task->infile, "no conditional to test"); return MARKUP_ERROR; } if(attrib->next != NULL) { HtpMsg(MSG_ERROR, task->infile, "too many items in conditional expression"); return MARKUP_ERROR; } htmlMarkup->attrib = NULL; condTrue = ConditionValue(task, attrib, notTagFound); if (condTrue == ERROR) { DestroyAttribute(attrib); FreeMemory(attrib); return MARKUP_ERROR; } if(ReadinBlock(task, htmlMarkup, &blockFile) == FALSE) { DestroyAttribute(attrib); FreeMemory(attrib); return MARKUP_ERROR; } while (condTrue) { /* condition is true, so we have to expand the block */ CreateBufferReader(&inFile, &blockFile); if(! ProcessWhileBlock(task, &inFile)) { CloseStream(&blockFile); DestroyAttribute(attrib); FreeMemory(attrib); return MARKUP_ERROR; } /* check condition */ condTrue = ConditionValue(task, attrib, notTagFound); if (condTrue == ERROR) { CloseStream(&blockFile); DestroyAttribute(attrib); FreeMemory(attrib); return MARKUP_ERROR; } } CloseStream(&blockFile); DestroyAttribute(attrib); FreeMemory(attrib); return DISCARD_MARKUP; } else { /* end of while */ assert(whileLevel > 0); whileLevel--; } return DISCARD_MARKUP; } htp-1.19/Makefile.config0000664000175000017500000000367612543301326015314 0ustar hoenickehoenicke# # makefile - htp # # HTML pre-processor # Copyright (c) 2002-2003 Jochen Hoenicke # RELEASE = 1 #WIN32DMC = 1 #LINUX32 = 1 # # development tools # ifdef WIN32DMC CC = dmc LINK = dmc OBJEXT = obj EXEEXT = .exe OS = Win32 else CC = gcc LINK = gcc OBJEXT = o EXEEXT = OS := $(shell uname -s)-$(shell uname -m) endif STRIP = strip #CC = i686-w64-mingw32-gcc #CC = i686-w64-mingw32-gcc #LINK = $(CC) #STRIP = i686-w64-mingw32-strip #OBJEXT = o #EXEEXT = .exe #OS = Win32 INSTALL = install RSYNC = rsync --rsh=ssh -v DIFF = diff -q DESTDIR = prefix = $(DESTDIR)/usr/local bindir = $(prefix)/bin docdir = $(prefix)/share/doc pkgdocdir = $(prefix)/share/doc/htp # # tool command-line options ... notice that these are geared towards GNU # CCOPT = -c ifdef WIN32DMC CCOPT += -o else CCOPT += -Wall -O2 endif ifndef RELEASE CCOPT += -g -DDEBUG=1 endif # Adapt the following defines to the features of your OS. ifdef WIN32DMC DEFINES = -DHAVE_SNPRINTF -DPREFER_PORTABLE_SNPRINTF -DHAVE_STPCPY else DEFINES = -DHAVE_SNPRINTF -DHAVE_PIPE -DHAVE_STPCPY -DHAVE_VA_COPY -D_GNU_SOURCE=1 endif #DEFINES = -DHAVE_SNPRINTF -DHAVE_VA_COPY -D_GNU_SOURCE=1 LOPT = # -lefence # -lmpatrol -lbfd -liberty #Memory debug: #LOPT = -lmpatrol -L$(HOME)/zola/lib -lbfd -liberty # for cygwin/win32 ? #LOPT = -lc -Wl,-u,_WinMain@16 ifdef LINUX32 CCOPT += -m32 LOPT += -m32 OS = Linux-i386 endif # # project name and version # MAIN = htp VERSION := 1.19 ifndef RELEASE REVISION:= $(shell svn -R info . | grep ^Revision: | cut -c 11- | sort |tail -1) VERSION := $(VERSION)r$(REVISION) endif FULLVERSION := $(VERSION) RELDIR = $(MAIN)-$(VERSION) # # Layout of web server # ifdef RELEASE TESTDIR = else TESTDIR = /$(USER) endif CGIBIN = http://htp.sourceforge.net/cgi-bin RSYNCBASE = $(USER),htp@shell.sourceforge.net:/home/project-web/htp RSYNCCGI = $(RSYNCBASE)/cgi-bin HTP_DIR = /home/groups/h/ht/htp/htdocs$(TESTDIR) RSYNCDIR = $(RSYNCBASE)/htdocs$(TESTDIR) REF_URL = $(TESTDIR)/ref export CGIBIN