PNG  IHDRX cHRMz&u0`:pQ<bKGD pHYsodtIME MeqIDATxw]Wug^Qd˶ 6`!N:!@xI~)%7%@Bh&`lnjVF29gΨ4E$|>cɚ{gk= %,a KX%,a KX%,a KX%,a KX%,a KX%,a KX%, b` ǟzeאfp]<!SJmɤY޲ڿ,%c ~ع9VH.!Ͳz&QynֺTkRR.BLHi٪:l;@(!MԴ=žI,:o&N'Kù\vRmJ雵֫AWic H@" !: Cé||]k-Ha oݜ:y F())u]aG7*JV@J415p=sZH!=!DRʯvɱh~V\}v/GKY$n]"X"}t@ xS76^[bw4dsce)2dU0 CkMa-U5tvLƀ~mlMwfGE/-]7XAƟ`׮g ewxwC4\[~7@O-Q( a*XGƒ{ ՟}$_y3tĐƤatgvێi|K=uVyrŲlLӪuܿzwk$m87k( `múcE)"@rK( z4$D; 2kW=Xb$V[Ru819קR~qloѱDyįݎ*mxw]y5e4K@ЃI0A D@"BDk_)N\8͜9dz"fK0zɿvM /.:2O{ Nb=M=7>??Zuo32 DLD@D| &+֎C #B8ַ`bOb $D#ͮҪtx]%`ES`Ru[=¾!@Od37LJ0!OIR4m]GZRJu$‡c=%~s@6SKy?CeIh:[vR@Lh | (BhAMy=݃  G"'wzn޺~8ԽSh ~T*A:xR[ܹ?X[uKL_=fDȊ؂p0}7=D$Ekq!/t.*2ʼnDbŞ}DijYaȲ(""6HA;:LzxQ‘(SQQ}*PL*fc\s `/d'QXW, e`#kPGZuŞuO{{wm[&NBTiiI0bukcA9<4@SӊH*؎4U/'2U5.(9JuDfrޱtycU%j(:RUbArLֺN)udA':uGQN"-"Is.*+k@ `Ojs@yU/ H:l;@yyTn}_yw!VkRJ4P)~y#)r,D =ě"Q]ci'%HI4ZL0"MJy 8A{ aN<8D"1#IJi >XjX֔#@>-{vN!8tRݻ^)N_╗FJEk]CT՟ YP:_|H1@ CBk]yKYp|og?*dGvzنzӴzjֺNkC~AbZƷ`.H)=!QͷVTT(| u78y֮}|[8-Vjp%2JPk[}ԉaH8Wpqhwr:vWª<}l77_~{s۴V+RCģ%WRZ\AqHifɤL36: #F:p]Bq/z{0CU6ݳEv_^k7'>sq*+kH%a`0ԣisqにtү04gVgW΂iJiS'3w.w}l6MC2uԯ|>JF5`fV5m`Y**Db1FKNttu]4ccsQNnex/87+}xaUW9y>ͯ骵G{䩓Գ3+vU}~jJ.NFRD7<aJDB1#ҳgSb,+CS?/ VG J?|?,2#M9}B)MiE+G`-wo߫V`fio(}S^4e~V4bHOYb"b#E)dda:'?}׮4繏`{7Z"uny-?ǹ;0MKx{:_pÚmFמ:F " .LFQLG)Q8qN q¯¯3wOvxDb\. BKD9_NN &L:4D{mm o^tֽ:q!ƥ}K+<"m78N< ywsard5+вz~mnG)=}lYݧNj'QJS{S :UYS-952?&O-:W}(!6Mk4+>A>j+i|<<|;ر^߉=HE|V#F)Emm#}/"y GII웻Jі94+v뾧xu~5C95~ūH>c@덉pʃ1/4-A2G%7>m;–Y,cyyaln" ?ƻ!ʪ<{~h~i y.zZB̃/,雋SiC/JFMmBH&&FAbϓO^tubbb_hZ{_QZ-sύodFgO(6]TJA˯#`۶ɟ( %$&+V'~hiYy>922 Wp74Zkq+Ovn錄c>8~GqܲcWꂎz@"1A.}T)uiW4="jJ2W7mU/N0gcqܗOO}?9/wìXžΏ0 >֩(V^Rh32!Hj5`;O28؇2#ݕf3 ?sJd8NJ@7O0 b־?lldщ̡&|9C.8RTWwxWy46ah嘦mh٤&l zCy!PY?: CJyв]dm4ǜҐR޻RլhX{FƯanшQI@x' ao(kUUuxW_Ñ줮[w8 FRJ(8˼)_mQ _!RJhm=!cVmm ?sFOnll6Qk}alY}; "baӌ~M0w,Ggw2W:G/k2%R,_=u`WU R.9T"v,<\Ik޽/2110Ӿxc0gyC&Ny޽JҢrV6N ``یeA16"J³+Rj*;BϜkZPJaÍ<Jyw:NP8/D$ 011z֊Ⱳ3ι֘k1V_"h!JPIΣ'ɜ* aEAd:ݺ>y<}Lp&PlRfTb1]o .2EW\ͮ]38؋rTJsǏP@芎sF\> P^+dYJLbJ C-xϐn> ι$nj,;Ǖa FU *择|h ~izť3ᤓ`K'-f tL7JK+vf2)V'-sFuB4i+m+@My=O҈0"|Yxoj,3]:cо3 $#uŘ%Y"y죯LebqtҢVzq¼X)~>4L׶m~[1_k?kxֺQ`\ |ٛY4Ѯr!)N9{56(iNq}O()Em]=F&u?$HypWUeB\k]JɩSع9 Zqg4ZĊo oMcjZBU]B\TUd34ݝ~:7ڶSUsB0Z3srx 7`:5xcx !qZA!;%͚7&P H<WL!džOb5kF)xor^aujƍ7 Ǡ8/p^(L>ὴ-B,{ۇWzֺ^k]3\EE@7>lYBȝR.oHnXO/}sB|.i@ɥDB4tcm,@ӣgdtJ!lH$_vN166L__'Z)y&kH;:,Y7=J 9cG) V\hjiE;gya~%ks_nC~Er er)muuMg2;֫R)Md) ,¶ 2-wr#F7<-BBn~_(o=KO㭇[Xv eN_SMgSҐ BS헃D%g_N:/pe -wkG*9yYSZS.9cREL !k}<4_Xs#FmҶ:7R$i,fi!~' # !6/S6y@kZkZcX)%5V4P]VGYq%H1!;e1MV<!ϐHO021Dp= HMs~~a)ަu7G^];git!Frl]H/L$=AeUvZE4P\.,xi {-~p?2b#amXAHq)MWǾI_r`S Hz&|{ +ʖ_= (YS(_g0a03M`I&'9vl?MM+m~}*xT۲(fY*V4x@29s{DaY"toGNTO+xCAO~4Ϳ;p`Ѫ:>Ҵ7K 3}+0 387x\)a"/E>qpWB=1 ¨"MP(\xp߫́A3+J] n[ʼnӼaTbZUWb={~2ooKױӰp(CS\S筐R*JغV&&"FA}J>G֐p1ٸbk7 ŘH$JoN <8s^yk_[;gy-;߉DV{c B yce% aJhDȶ 2IdйIB/^n0tNtџdcKj4϶v~- CBcgqx9= PJ) dMsjpYB] GD4RDWX +h{y`,3ꊕ$`zj*N^TP4L:Iz9~6s) Ga:?y*J~?OrMwP\](21sZUD ?ܟQ5Q%ggW6QdO+\@ ̪X'GxN @'4=ˋ+*VwN ne_|(/BDfj5(Dq<*tNt1х!MV.C0 32b#?n0pzj#!38}޴o1KovCJ`8ŗ_"]] rDUy޲@ Ȗ-;xџ'^Y`zEd?0„ DAL18IS]VGq\4o !swV7ˣι%4FѮ~}6)OgS[~Q vcYbL!wG3 7띸*E Pql8=jT\꘿I(z<[6OrR8ºC~ډ]=rNl[g|v TMTղb-o}OrP^Q]<98S¤!k)G(Vkwyqyr޽Nv`N/e p/~NAOk \I:G6]4+K;j$R:Mi #*[AȚT,ʰ,;N{HZTGMoּy) ]%dHء9Պ䠬|<45,\=[bƟ8QXeB3- &dҩ^{>/86bXmZ]]yޚN[(WAHL$YAgDKp=5GHjU&99v簪C0vygln*P)9^͞}lMuiH!̍#DoRBn9l@ xA/_v=ȺT{7Yt2N"4!YN`ae >Q<XMydEB`VU}u]嫇.%e^ánE87Mu\t`cP=AD/G)sI"@MP;)]%fH9'FNsj1pVhY&9=0pfuJ&gޤx+k:!r˭wkl03׼Ku C &ѓYt{.O.zҏ z}/tf_wEp2gvX)GN#I ݭ߽v/ .& и(ZF{e"=V!{zW`, ]+LGz"(UJp|j( #V4, 8B 0 9OkRrlɱl94)'VH9=9W|>PS['G(*I1==C<5"Pg+x'K5EMd؞Af8lG ?D FtoB[je?{k3zQ vZ;%Ɠ,]E>KZ+T/ EJxOZ1i #T<@ I}q9/t'zi(EMqw`mYkU6;[t4DPeckeM;H}_g pMww}k6#H㶏+b8雡Sxp)&C $@'b,fPߑt$RbJ'vznuS ~8='72_`{q纶|Q)Xk}cPz9p7O:'|G~8wx(a 0QCko|0ASD>Ip=4Q, d|F8RcU"/KM opKle M3#i0c%<7׿p&pZq[TR"BpqauIp$ 8~Ĩ!8Սx\ւdT>>Z40ks7 z2IQ}ItԀ<-%S⍤};zIb$I 5K}Q͙D8UguWE$Jh )cu4N tZl+[]M4k8֦Zeq֮M7uIqG 1==tLtR,ƜSrHYt&QP윯Lg' I,3@P'}'R˪e/%-Auv·ñ\> vDJzlӾNv5:|K/Jb6KI9)Zh*ZAi`?S {aiVDԲuy5W7pWeQJk֤#5&V<̺@/GH?^τZL|IJNvI:'P=Ϛt"¨=cud S Q.Ki0 !cJy;LJR;G{BJy޺[^8fK6)=yʊ+(k|&xQ2`L?Ȓ2@Mf 0C`6-%pKpm')c$׻K5[J*U[/#hH!6acB JA _|uMvDyk y)6OPYjœ50VT K}cǻP[ $:]4MEA.y)|B)cf-A?(e|lɉ#P9V)[9t.EiQPDѠ3ϴ;E:+Օ t ȥ~|_N2,ZJLt4! %ա]u {+=p.GhNcŞQI?Nd'yeh n7zi1DB)1S | S#ًZs2|Ɛy$F SxeX{7Vl.Src3E℃Q>b6G ўYCmtկ~=K0f(=LrAS GN'ɹ9<\!a`)֕y[uՍ[09` 9 +57ts6}b4{oqd+J5fa/,97J#6yν99mRWxJyѡyu_TJc`~W>l^q#Ts#2"nD1%fS)FU w{ܯ R{ ˎ󅃏џDsZSQS;LV;7 Od1&1n$ N /.q3~eNɪ]E#oM~}v֯FڦwyZ=<<>Xo稯lfMFV6p02|*=tV!c~]fa5Y^Q_WN|Vs 0ҘދU97OI'N2'8N֭fgg-}V%y]U4 峧p*91#9U kCac_AFңĪy뚇Y_AiuYyTTYЗ-(!JFLt›17uTozc. S;7A&&<ԋ5y;Ro+:' *eYJkWR[@F %SHWP 72k4 qLd'J "zB6{AC0ƁA6U.'F3:Ȅ(9ΜL;D]m8ڥ9}dU "v!;*13Rg^fJyShyy5auA?ɩGHRjo^]׽S)Fm\toy 4WQS@mE#%5ʈfFYDX ~D5Ϡ9tE9So_aU4?Ѽm%&c{n>.KW1Tlb}:j uGi(JgcYj0qn+>) %\!4{LaJso d||u//P_y7iRJ߬nHOy) l+@$($VFIQ9%EeKʈU. ia&FY̒mZ=)+qqoQn >L!qCiDB;Y<%} OgBxB!ØuG)WG9y(Ą{_yesuZmZZey'Wg#C~1Cev@0D $a@˲(.._GimA:uyw֬%;@!JkQVM_Ow:P.s\)ot- ˹"`B,e CRtaEUP<0'}r3[>?G8xU~Nqu;Wm8\RIkբ^5@k+5(By'L&'gBJ3ݶ!/㮻w҅ yqPWUg<e"Qy*167΃sJ\oz]T*UQ<\FԎ`HaNmڜ6DysCask8wP8y9``GJ9lF\G g's Nn͵MLN֪u$| /|7=]O)6s !ĴAKh]q_ap $HH'\1jB^s\|- W1:=6lJBqjY^LsPk""`]w)󭃈,(HC ?䔨Y$Sʣ{4Z+0NvQkhol6C.婧/u]FwiVjZka&%6\F*Ny#8O,22+|Db~d ~Çwc N:FuuCe&oZ(l;@ee-+Wn`44AMK➝2BRՈt7g*1gph9N) *"TF*R(#'88pm=}X]u[i7bEc|\~EMn}P瘊J)K.0i1M6=7'_\kaZ(Th{K*GJyytw"IO-PWJk)..axӝ47"89Cc7ĐBiZx 7m!fy|ϿF9CbȩV 9V-՛^pV̌ɄS#Bv4-@]Vxt-Z, &ֺ*diؠ2^VXbs֔Ìl.jQ]Y[47gj=幽ex)A0ip׳ W2[ᎇhuE^~q흙L} #-b۸oFJ_QP3r6jr+"nfzRJTUqoaۍ /$d8Mx'ݓ= OՃ| )$2mcM*cЙj}f };n YG w0Ia!1Q.oYfr]DyISaP}"dIӗթO67jqR ҊƐƈaɤGG|h;t]䗖oSv|iZqX)oalv;۩meEJ\!8=$4QU4Xo&VEĊ YS^E#d,yX_> ۘ-e\ "Wa6uLĜZi`aD9.% w~mB(02G[6y.773a7 /=o7D)$Z 66 $bY^\CuP. (x'"J60׿Y:Oi;F{w佩b+\Yi`TDWa~|VH)8q/=9!g߆2Y)?ND)%?Ǐ`k/sn:;O299yB=a[Ng 3˲N}vLNy;*?x?~L&=xyӴ~}q{qE*IQ^^ͧvü{Huu=R|>JyUlZV, B~/YF!Y\u_ݼF{_C)LD]m {H 0ihhadd nUkf3oٺCvE\)QJi+֥@tDJkB$1!Đr0XQ|q?d2) Ӣ_}qv-< FŊ߫%roppVBwü~JidY4:}L6M7f٬F "?71<2#?Jyy4뷢<_a7_=Q E=S1И/9{+93֮E{ǂw{))?maÆm(uLE#lïZ  ~d];+]h j?!|$F}*"4(v'8s<ŏUkm7^7no1w2ؗ}TrͿEk>p'8OB7d7R(A 9.*Mi^ͳ; eeUwS+C)uO@ =Sy]` }l8^ZzRXj[^iUɺ$tj))<sbDJfg=Pk_{xaKo1:-uyG0M ԃ\0Lvuy'ȱc2Ji AdyVgVh!{]/&}}ċJ#%d !+87<;qN޼Nفl|1N:8ya  8}k¾+-$4FiZYÔXk*I&'@iI99)HSh4+2G:tGhS^繿 Kتm0 вDk}֚+QT4;sC}rՅE,8CX-e~>G&'9xpW,%Fh,Ry56Y–hW-(v_,? ; qrBk4-V7HQ;ˇ^Gv1JVV%,ik;D_W!))+BoS4QsTM;gt+ndS-~:11Sgv!0qRVh!"Ȋ(̦Yl.]PQWgٳE'`%W1{ndΗBk|Ž7ʒR~,lnoa&:ü$ 3<a[CBݮwt"o\ePJ=Hz"_c^Z.#ˆ*x z̝grY]tdkP*:97YľXyBkD4N.C_[;F9`8& !AMO c `@BA& Ost\-\NX+Xp < !bj3C&QL+*&kAQ=04}cC!9~820G'PC9xa!w&bo_1 Sw"ܱ V )Yl3+ס2KoXOx]"`^WOy :3GO0g;%Yv㐫(R/r (s } u B &FeYZh0y> =2<Ϟc/ -u= c&׭,.0"g"7 6T!vl#sc>{u/Oh Bᾈ)۴74]x7 gMӒ"d]U)}" v4co[ ɡs 5Gg=XR14?5A}D "b{0$L .\4y{_fe:kVS\\O]c^W52LSBDM! C3Dhr̦RtArx4&agaN3Cf<Ԉp4~ B'"1@.b_/xQ} _߃҉/gٓ2Qkqp0շpZ2fԫYz< 4L.Cyυι1t@鎫Fe sYfsF}^ V}N<_`p)alٶ "(XEAVZ<)2},:Ir*#m_YӼ R%a||EƼIJ,,+f"96r/}0jE/)s)cjW#w'Sʯ5<66lj$a~3Kʛy 2:cZ:Yh))+a߭K::N,Q F'qB]={.]h85C9cr=}*rk?vwV렵ٸW Rs%}rNAkDv|uFLBkWY YkX מ|)1!$#3%y?pF<@<Rr0}: }\J [5FRxY<9"SQdE(Q*Qʻ)q1E0B_O24[U'],lOb ]~WjHޏTQ5Syu wq)xnw8~)c 쫬gٲߠ H% k5dƝk> kEj,0% b"vi2Wس_CuK)K{n|>t{P1򨾜j>'kEkƗBg*H%'_aY6Bn!TL&ɌOb{c`'d^{t\i^[uɐ[}q0lM˕G:‚4kb祔c^:?bpg… +37stH:0}en6x˟%/<]BL&* 5&fK9Mq)/iyqtA%kUe[ڛKN]Ě^,"`/ s[EQQm?|XJ߅92m]G.E΃ח U*Cn.j_)Tѧj̿30ڇ!A0=͜ar I3$C^-9#|pk!)?7.x9 @OO;WƝZBFU keZ75F6Tc6"ZȚs2y/1 ʵ:u4xa`C>6Rb/Yм)^=+~uRd`/|_8xbB0?Ft||Z\##|K 0>>zxv8۴吅q 8ĥ)"6>~\8:qM}#͚'ĉ#p\׶ l#bA?)|g g9|8jP(cr,BwV (WliVxxᡁ@0Okn;ɥh$_ckCgriv}>=wGzβ KkBɛ[˪ !J)h&k2%07δt}!d<9;I&0wV/ v 0<H}L&8ob%Hi|޶o&h1L|u֦y~󛱢8fٲUsւ)0oiFx2}X[zVYr_;N(w]_4B@OanC?gĦx>мgx>ΛToZoOMp>40>V Oy V9iq!4 LN,ˢu{jsz]|"R޻&'ƚ{53ўFu(<٪9:΋]B;)B>1::8;~)Yt|0(pw2N%&X,URBK)3\zz&}ax4;ǟ(tLNg{N|Ǽ\G#C9g$^\}p?556]/RP.90 k,U8/u776s ʪ_01چ|\N 0VV*3H鴃J7iI!wG_^ypl}r*jɤSR 5QN@ iZ#1ٰy;_\3\BQQ x:WJv츟ٯ$"@6 S#qe딇(/P( Dy~TOϻ<4:-+F`0||;Xl-"uw$Цi󼕝mKʩorz"mϺ$F:~E'ҐvD\y?Rr8_He@ e~O,T.(ފR*cY^m|cVR[8 JҡSm!ΆԨb)RHG{?MpqrmN>߶Y)\p,d#xۆWY*,l6]v0h15M˙MS8+EdI='LBJIH7_9{Caз*Lq,dt >+~ّeʏ?xԕ4bBAŚjﵫ!'\Ը$WNvKO}ӽmSşذqsOy?\[,d@'73'j%kOe`1.g2"e =YIzS2|zŐƄa\U,dP;jhhhaxǶ?КZ՚.q SE+XrbOu%\GتX(H,N^~]JyEZQKceTQ]VGYqnah;y$cQahT&QPZ*iZ8UQQM.qo/T\7X"u?Mttl2Xq(IoW{R^ ux*SYJ! 4S.Jy~ BROS[V|žKNɛP(L6V^|cR7i7nZW1Fd@ Ara{詑|(T*dN]Ko?s=@ |_EvF]׍kR)eBJc" MUUbY6`~V޴dJKß&~'d3i5h-3LL

HOME


5h-3LL 1.0
DIR: /srv/http/vyvoj.adent.cz/egroupware/khkstc/icalsrv/inc
/srv/http/vyvoj.adent.cz/egroupware/khkstc/icalsrv/inc/
Upload File:
Current File : /srv/http/vyvoj.adent.cz/egroupware/khkstc/icalsrv/inc/class.boinfolog_vtodos.inc.php
<?php
   /** 
	* @file 
	* eGroupWare - iCalendar VTODOS conversion, import and export for egw infolog
	* @author Jan van Lieshout  
	* @version $Id$ 
	*/

   /* http://www.egroupware.org                                                *
	* --------------------------------------------                             *
	*  This program is free software; you can redistribute it and/or modify it *
	*  under the terms of the GNU General Public License as published by the   *
	*  Free Software Foundation; either version 2 of the License.              *
	**************************************************************************/


  /** @page pageicalsrvvtodofeatures Currently implemented VTODO handling in icalsrv
   * <PRE>
   * TODO:
   * [-] check multiple ATTENDEE import
   * [-] check multiple ATTENDEE export
   * [?] add and check 'whole day event' support
   * [?] check multiple CATEGORY export
   * [?] have multiple CATEGORY export  depent on supportedFields.
   * [?]todo: check multiple category import (do they get duplicated?
   * [-]check recur EXPORT stuff: NOT IMPLEMENTED YET in infolog
   * [? ]check recur IMPORT stuff: NOT IMPLEMENTED YET in infolog
   * [? basic] check EXPORT of VALARMS   (only time, no action selectable)
   * [? basic] check IMPORT of VALARMS     (only time, no action selectable)
   * [?+/-] todo: add switch to control import of non egw known attendees
   * [?] X-DELETED import
   * [?] test the usage and conversions of user time and server times and timezones in
   *     exported and imported ical files.
   * </PRE>
   */

	require_once EGW_SERVER_ROOT.'/calendar/inc/class.bocalupdate.inc.php';
    require_once EGW_SERVER_ROOT.'/icalsrv/inc/class.icalsrv_resourcehandler.inc.php';


    /**
	 * Concrete subclass resourcehandler for iCal vtodos import and export with a egroupware
	 * boinfolog infolog resource.
	 *
	 *@section secboivtodossynopsis Synopsis
	 * Some simple examples. Firs we need a couple of egw tasks and an instance of our
	 * (concrete) infologresource handler class:
@verbatim
  $binf =& CreateObject('infolog.boinfolog');

  $tsk1 = $binf->read(1233);                    // get 3 tasks
  $tsk2 = $binf->read(4011);
  $tsk3 = $binf->read(4012);

  $binfhnd =& CreateObject('icalsrv.boinfolog_vtodos',$binf);
@endverbatim
     * Now export a task as VTODO and render it as iCalendar string
@verbatim
   // alternative 1
   $vtodo1 = $binfhnd->export_vtodo($ev1,UMM_ID2UID);
   $vcalstr1 = icalsrv_resourcehandler::render_velt2vcal($vtodo1);

   // alternative 2 (generic for all resourcehandlers)
   $binfhnd->uid_mapping_export = UMM_ID2UID;
   $vtodo2  = $binfhnd->export_ncvelt($tsk2);
   $vcalstr2 = icalsrv_resourcehandler::render_velt2vcal($vtodo2);

   // alternative 3 (via baseclass, without intermediate vtodo)
   $vcalstr3 = $binfhnd->export_vcal($tsk3);
@endverbatim
     * An example for importing the vtodos
@verbatim
    // alternative 1 (via the concrete method)
    $vtodo1  = ..... a good vtodo
    $tsk_id1 = $binfhnd->import_vtodo($vtodo1, UMM_UID2ID,1);
    if ($tsk_id1 > 0)    {
      echo "imported vtodo1 as task with id $tsk_id1";
    }

    // alternative 2 (generic for all resourcehandlers)
    $binfhnd->uid_mapping_import = UMM_UID2ID;
    $tsk_id2  = $binfhnd->import_ncvelt($vtodo2);
    if ($tsk_id2 > 0)    {
      echo "imported vtodo2 as task with id $tsk_id2";
    }

    // alternative 3 (via base class, easier for multiple vtodos)
    $my_vtodos = array($vtodo1, $vtodo2,..);
    $binfhnd->uid_mapping_import = UMM_UID2ID;
    $tids = $binfhnd->import_velts($my_vtodos);
    echo "we imported" . count($tids) . "vtodos";

@endverbatim
    * And finally an example of importing all the vtodos from a vcalstring
@verbatim
    // alternative 1
    $vcalstr = .. an vcalendar format string with multiple vtodos

    $compvelt  = icalsrv_resourcehandler::parse_vcal2velt($vcalstr);
    if($compvelt === false) exit;

    $tids = $binfhnd->import_velts($compvelt);
    if ($tids)
    {
       echo "we imported" . count($tids) . "tasks";
    }

    // alternative 2 (using the baseclass its methods)
   $tids = $binfhnd->import_vcal($vcalstr);
   if ($tids)   echo "we imported" . count($tids) . "tasks";

@endverbatim
     * @note Warning: When importing a vtodo resulting from parsing a vcalstring
     * or any other VElt for which you do not know if it is a single vtodo
     * or possibily a compound element with multiple vtodos in it, you should preferable use
	 * the import_velts() routine of the baseclass instead of the import_ncvelt()
	 * or the import_vtodo() routines. This is because the former can handle compound VElts,
	 * while the latter two cannot!
	 *
	 * @package icalsrv
	 *
	 * @author Jan van Lieshout <jvl-AT-xs4all.nl> (This version. new api rewrite,
	 * refactoring, and extension).
	 * @author Lars Kneschke <lkneschke@egroupware.org> (parts from boical that are reused here)
	 * @author Ralf Becker <RalfBecker-AT-outdoor-training.de> (parts from boical that are
	 * reused here)
	 * @version 0.9.37-ng-a6 fixed empty summary field (semi)
	 * @since 0.9.37-ng-a2  removed double charset translation
	 * @since 0.9.36  first version for napi3.1 (with rsc_owner_id parameter)
	 * @since 0.9.30  first version for napi3

	 * license @url  http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
	 */
	class boinfolog_vtodos extends icalsrv_resourcehandler
    {
		/** conversion of infologtask status to vtodo status
		* @private
		* @var array $status_task2vtodo 
		*/
		var $status_task2vtodo = array(
			'offer'       => 'NEEDS-ACTION',
			'not-started' => 'NEEDS-ACTION',
			'ongoing'     => 'IN-PROCESS',
			'done'        => 'COMPLETED',
			'cancelled'   => 'CANCELLED',
			// NEW RalfBecker Aug 2007
			// was mapped to invalid status DONE
			'billed'      => 'COMPLETED',
			// these are not longer used (call is mapped to not-started and will-call to ongoing
//			'call'        => 'NEEDS-ACTION',
//			'will-call'   => 'IN-PROCESS',
		);

		/** conversion of vtodo status to infolog status
		* @private
		* @var array 
		*/
		var $status_vtodo2task = array(
			'NEEDS-ACTION' => 'not-started',
			'IN-PROCESS'   => 'ongoing',
			'COMPLETED'    => 'done',
			'CANCELLED'    => 'cancelled',
		);
		
		/**
		 * instance of boinfolog
		 *
		 * @var boinfolog
		 */
		var $rsc;

		/** mapping from iCalendar VTODO fields to egw infolog task fields
		* @private
		* @var array $vtodo2taskFields
		* An array containing roughly the mapping from iCalendar
		* to egw fields. Set by constructor.
		* example entry (<i>rn</i> stands for "Resourced_Name"):
		* <PRE>
		'SUMMARY'	=> array('rn' => 'title'),
		</PRE>
		* Here <i>rn</i> stands for "Resourced  Name", to indicate the name of the related
		* related field in the bound egw resource
		* @todo integrate this with the  icalsrv base $ical2egw conversion table
		*/
		var $vtodo2taskFields = array();

		/** Deliver the implemented vtodo to task mapping as provided by this class.
		*
		* @private
		*
		* @todo find out the correct conversion between info_owner, info_responsible,
		*       and ORGANIZER  and ATTENDEES for tasks
		* @todo add support for multiple2single category conversion et vice versa
		*
		* @todo find out if infolog supports yet ALARMS, if so do conversion
		* @todo add routines for resources conversions
		* @todo add routines for url conversions
		*
		* @note when a field is filled with a <code>array('rn' => xxx) </code> this
		* means that for conversion the value from xxx can simply be copied to the new field.
		* For other values the conversion is more complex and needs to be handled by 
		* specific functions.
		*
		* Produce the array of vtodo to task field mappings that this class implements.
		* These are stored on instantiation in the variable $vtodo2taskFields
		* @return array The provided vtodo to task fields mapping.
		*/
		function _provided_vtodo2taskFields()
		{
			static $v2t = array(
				// optional once only 
				'CLASS'     => array('rn' => 'info_access'),
				'COMPLETED' => array('rn' =>  'info_datecompleted'),
				'CREATED'   => array('fn_TSforAction(modify)'),
				'DESCRIPTION' => array('rn' => 'info_des'),
				'DTSTAMP'   => array('fn_time()'),
				'DTSTART'   => array('rn' => 'info_startdate'),
				'GEO'       => array(''),
				'LAST-MODIFIED'   => array('rn' => 'info_datemodified'),
				'LOCATION'  => array('rn' => 'info_location'),
				'ORGANIZER' => array('rn' => 'info_owner'),
				'PERCENT-COMPLETE' => array('rn' =>  'info_percent'),
				'PRIORITY'  => array('rn' => 'info_priority'),
				'RRULE'     => array(
					'fn_rns' => array(
						'recur_type','recur_interval',
						'recur_data','recur_enddate'
					)
				),
				'SEQUENCE'  => array('fn_rns' => array('info_id_parent')),
				'STATUS'    => array(
					'fn_rns' => array('info_status')
				),
				'SUMMARY'	=> array('rn' => 'info_subject'),
				'UID'		=> array('fn_rn' => 'info_uid'),
				//				'URL'       => array('fn_rns' => 'links?'),

				// optional once, but exclusive alternatives
				'DUE'	    => array('fn_rn' => 'info_enddate'),
				'DURATION'  => array('fn_rns' => array('info_startdate','info_enddate')),

				// optional multiple
				//				'ATTACH'    => array('fn_rns' => array('?')),
				'ATTENDEE'	=> array('fn_rn' => 'info_responsible'),
				'CATEGORIES'=> array('fn_rn' => 'category'),
				'COMMENT'   => array('fn_rn'),
				'CONTACT'   => array('fn_rns'=> array('info_from','info-addr')),
				// 				'EXDATE'    => array('fn_rn' => 'recur_exception'),
				// 				'??_EXRULE' => array(),
				// 				'??_RSTATUS' => array(),
				// 				'??_RDATE' => array(),
				// 				'RRULE'     => array(),
				// 				'RELATED-TO'=> array('rn' => 'info_id_parent'),
				'RESOURCES' => array('fn_rn' => ''),
				'TRANSP'    => array('rn' => 'non_blocking'),
				// 				'VALARM'     => array('fn_cn' => 'alarms'),
				// 				'VALARM/TRIGGER'     => array('fn_crn' => 'alarms/time')
			);

			return $v2t;
		}

		/**
		* Our Constructor, if given it sets the egw resource $egwrsc is set as
		* so called <i>bound egw resource</i>. And $prodid, the product id of the client that
		* will use or produce ical data is set to determine which fields to use in coming
		* import and exportd conversions between vcalendar and egw data.
		* @param egwobj $egwrsc Egroupware data resource object that
		* will be used to transport (i.e. import and export) the
		* vcalendar elements to and from. This can also later be set
		* using the set_rsc() method.
		* @param ProductType $devicetype The type identification of the device that is used to
		* the transport the ical data to and from. This is used to set the supportedFields already.
		* @note These can also later be set using the setSupportedFields() method. 
		* @param string $rscownid the id of the calendar owner. This is only needed for import
		* in calendars not owned by the authenticated user. Default (0) the id of the
		* authenticated user is used.
		*/
		function boinfolog_vtodos($egwrsc = null, $devicetype='all', $rscownid='0')
		{
			// call our abstract superclass constructor
			icalsrv_resourcehandler::icalsrv_resourcehandler($egwrsc, $prodid, $rscownid);
			//@todo rewrite supportedFields setting to distribute it over the icalsrv
			// baseclass and the subclasses cleverly
			$this->vtodo2taskFields = $this->_provided_vtodo2taskFields();
			// add reference to the base table too
			$this->ical2egwComponents['VTODO'] = $this->vtodo2taskFields;
			// default initialization
			$this->setSupportedFields($devicetype);
			$this->set_rsc($egwrsc);

			return true;
		}

		/** Set the egw infolog resource  that this worker will handle.  
		* 
		* This worker is only capable of handling  boinfolog task objects, so it should
		* be of that class. The $egw_rsc is registered in the $rsc variable and the supported
		* ical element is set to be 'vtodo'. This is registered in $rsc_vtypes.
		*
		* @param egwobj $egw_rsc the resource object of type boinfolog that will be
		* used to transport the ical data to and from.
		* @return boolean false on error, true if the $egw_rsc was indeed a correct  resource
		* of the supported type (boinfolog).
		*/
		function set_rsc($egw_rsc)
		{
			if(!is_a($egw_rsc,'boinfolog'))
			{
				return false;
			}
			$this->rsc = $egw_rsc;
			$this->rsc_vtypes[]= 'vtodo';
			return true;
		}

		// -------- below only conversion and import/export stuff -----


		/** Export infolog task from bound boinfolog resource as VTODO
		*
		* The eGW task in $task is exported to iCalendar VTODO (of type Horde_iCalendar_vtodo)
		* Note that only the set of supported Fields, as indicated by the $supportedFields
		* member variable, are exported into the VTODO.
		*
		* The uid field of the generated VTODO will be filled according to the setting of
		* the $uid_mapping_export parameter. Either with the task id encoded (ID2UID) or with the
		* task uid field copied (UID2UID) or with a completey new generated string (NEWUID).
		* .
		* For more info see @ref secuidmapping 
		*
		* The mapping is inspired on rfc 2445 -sec 4.6.2 
		*  @bug created field is not fetched oke from db.
		* @param TaskId|TaskData $task id or data of the eGW task that will be exported
		* @param int $uid_mapping_export switch to set the export mode for the uid fields.
		* Default UMM_ID2UID is used.
		* @return VTODO|false  the iCalendar VTODO object representing the data from the egw
		* input task. On error: false
		* @ref $supportedFields determines which fields in the VTODO will be filled
		*/
		function export_vtodo(&$task, $uid_mapping_export=ID2UID)
		{
			// decode the mode
			$euid_export = ($uid_mapping_export == ID2UID) ? false : true; 
			// auxiliary horde_iCalendar object
			$hIcal = $this->hi; 

			$veExportFields =& $this->supportedFields;

			if (!is_array($task))
			{
				// task was passed as an task id
				$tid = $task;
				if( !$task = $this->rsc->read($tid))
				{
					// server = timestamp in server-time(!)
					return false;	// no permission to read $task_id
				}
				// task was passed as an array of fields
			}
			else
			{
				$tid = $task['info_id'];
				// now read it again to get all fields (including our alarms)
				//			$task = $this->rsc->read($tid);
			}

			#		  error_log('>>>>>>>>>>>' .'task to export=' . print_r($task,true));
			#		  error_log('task sum:'. $task['info_subject'] . ' start:' .$task['info_startdate']);

			// now create a UID value
			switch ($uid_mapping_export)
			{
				case UMM_UID2UID :
					// NEW RalfBecker Aug 2007
					// InfoLog support uid's from it's version 1.5.001 on
					// (this code (if clause) is only for 1.4 compatibility and can be removed for the next release)
					if ($GLOBALS['egw_info']['apps']['infolog']['version'] == '1.4')
					{
						error_log('boinfolog_vtodos.export_vtodo(): UMM_UID2UID NOT SUPPORTED YET: ERROR');
						return false;
					}
					// put egw uid into VTODO, to allow client to sync with his uids
					$taskGUID = $task['info_uid'];
					break;
				case UMM_NEWUID :
					// this one should not be decodable by mke_guid2id()
					$taskGUID = $this->ecu->mki_v_guid($tid,'newidcal');
				case UMM_ID2UID :
					// fall through
				default:
					$taskGUID = $this->ecu->mki_v_guid($tid,'infolog');
			}

			$vtodo = Horde_iCalendar::newComponent('VTODO',$this->hi);
			$parameters = $attributes = array();
			// to important to let supportedFields decide on this
			$attributes['UID'] = $taskGUID;

			foreach($veExportFields as $veFieldName)
			{
				switch($veFieldName)
				{
					case 'UID':
						// already set
						break;
					case 'ATTENDEE':
						foreach((array)$task['info_responsible'] as $pid)
						{
							if (!is_numeric($pid))
							{
								continue;
							}
							$propval  = $this->ecu->mki_v_CAL_ADDRESS($pid);
							$propparams = $this->ecu->mki_p_CN($pid);
							// NOTE: we need to add it already: multiple ATTENDEE fields may be occur 
							$this->ecu->updi_c_addAttribute($vtodo,'ATTENDEE',$propval,$propparams);
						}
						break;
					case 'CLASS':
						$attributes['CLASS'] = ($task['info_access'] == 'public') ? 'PUBLIC' : 'PRIVATE';
						break;
					case 'CONTACT':
						if($task['info_from'] || $task['info_addr'])
						$attributes['CONTACT'] = $task['info_from'] . '\,' . $task['info_addr'];
						break;
						// according to rfc, the organizer of the grouptask
					case 'ORGANIZER':
						if ($task['info_owner'])
						{
							$attributes['ORGANIZER']  = $this->ecu->mki_v_CAL_ADDRESS($task['info_owner']);
							$parameters['ORGANIZER']  = $this->ecu->mki_p_CN($task['info_owner']);
						}
						break;
						// Note; wholeday detection may change the DUE value later! 
					case 'DUE':
						if($task['info_enddate'])
						{
							$attributes[$veFieldName] = $this->ecu->st_dst_patch($task['info_enddate']);
						}
						break;
					case 'COMPLETED':
						if($task['info_datecompleted'])
						{
							$attributes[$veFieldName] = $this->ecu->st_dst_patch($task['info_datecompleted']);
						}
						break;
					case 'PRIORITY':
						if(is_numeric($eprio = $task['priority']) && ($eprio >0))
						{
							$attributes['PRIORITY'] =  $this->ecu->mki_v_prio($eprio);
						}
						break;
						// according to rfc this is not a vtodo field!
						// New RalfBecker Aug 2007
						// it's also no infolog field, seems to be cut-n-paste from calendar
//					case 'TRANSP':
//						$attributes['TRANSP'] = $task['non_blocking'] ? 'TRANSPARENT' : 'OPAQUE';
//						break;
					case 'CATEGORIES':
						if($catids = $task['info_cat'])
						{ 
							$catnamescstr = $this->ecu->cats_ids2idnamescstr(explode(',',$catids));
							$attributes['CATEGORIES'] = $catnamescstr;
						}
						break;
						// for subtasks set the parent
						// egw2vtodo: info_id_parent => pid  -> RELATED-TO:parent_uid
					case 'RELATED-TO':
						if ($parid = $task['info_id_parent'])
						{
							$attributes['RELATED-TO'] = $this->ecu->mki_v_guid($parid,'infolog');
						}
						break;
					case 'STATUS':
						// NEW RalfBecker Aug 2007
						// info_status is a regular infolog field, no custom field
						$attributes['STATUS'] = ( $vtodo_stat = $this->status_task2vtodo[$task['info_status']])
							? $vtodo_stat 
							: 'NEEDS-ACTION';
						// we try to preserv the original infolog status as X-INFOLOG-STATUS, so we can restore it, if the user does not modify STATUS
						$attributes['X-INFOLOG-STATUS'] = $task['info_status'];
//						if($vtodo_stat == 'COMPLETED')
//						{
//							$attributes['PERCENT-COMPLETE'] ='100';
//						}
						// 				elseif (ereg('([0-9]+)%',$task['info_status'],$matches)){
						// 				  $attributes['PERCENT-COMPLETE'] = $matches[1];
						// 				  $attributes['STATUS'] ='IN-PROCESS';
						// 				}
						break;
					case 'DTSTART':
						if ($task['info_startdate'])
						{
							$attributes[$veFieldName] = $this->ecu->st_dst_patch($task['info_startdate']);
						}
						break;
					case 'CREATED':
						$created = $this->ecu->get_TSdbAdd($task['info_id'],'infolog_task');
						$attributes[$veFieldName] = ($created) ? $created : $task['info_datemodified'];
						//				  $attributes[$veFieldName] = $this->ecu->st_dst_patch($task['info_startdate']);
						break;
					case 'LAST-MODIFIED':
						//				$lastdbmod = $this->ecu->get_TSdbMod($task['info_id'],'infolog');
						//				$attributes[$veFieldName] = $task['info_datemodified'];
						$attributes[$veFieldName] = $this->ecu->st_dst_patch($task['info_datemodified']);
						break;
					case 'DTSTAMP':
						$attributes[$veFieldName] = time();
						break;
						// unimplemented by maybe defined conversions
					case 'RRULE':
					case 'EXDATE':
					case 'VALARM':
						break;
					default:
						// only use default for level1 VTODO fields
						if(strpos($veFieldName, '/') !== false)
						{
							break;
						}
						// use first related field only for the simple conversion
						$efield = $this->vtodo2taskFields[$veFieldName]['rn'];
						if ($task[$efield])
						{
							// dont write empty fields
							$attributes[$veFieldName]	= $task[$efield];
						}
						break;
				}
			} //end foreach

			/* NEW RalfBecker Aug 2007
			   This code is cut-n-paste from calendar, but does NOT apply to infolog!
			// wholeday detector (DUE =23:59:59 && DTSTART = 00:00)
			// if detected the times will be exported in VALUE=DATE format
			if(((date('H:i:s',$task['info_enddate']) == '23:59:59') ||
				(date('H:i:s',$task['info_enddate']) == '00:00:00')) 
				&& (date('H:i',$task['info_startdate'] == '00:00')))
			{
				// only replace if supported!
				if($attributes['DTSTART'])
				{
					$attributes['DTSTART'] = $this->hi->_parseDate(date('Ymd',$task['info_startdate']));
					$parameters['DTSTART']['VALUE'] = 'DATE';
				}
				if($attributes['DUE'])
				{
					$attributes['DUE'] = $this->hi->_parseDate(date('Ymd',$task['info_enddate']+1));
					$parameters['DUE']['VALUE'] = 'DATE';
				}
				//	error_log('WHOLE DAY DETECTED');
			}
*/
			//error_log('attributes={'  . print_r($attributes,true));

			// add all collected attributes (not yet added) to the vtodo
			foreach($attributes as $aname => $avalue)
			{
				$this->ecu->updi_c_addAttribute(
					$vtodo,
					$aname,
					$avalue,
					$parameters[$aname]
				);
			}

			return $vtodo; //return VTODOObj
		}

		/** Wrapper around export_vtodo() with simplified parameters.
		*
		* @note the settings of $this->uid_mapping_export is respected
		* as to chose the method of UID field generation for the
		* VTODO. See @ref secuidmapping in the icalsrv_resourcehandler
		* documentation.
		* @param TaskId|TaskData $tid id or arraydata of an task in the bound
		* boinfolog resource that is to be exported.
		* @return VTODO the exported egw task converted to a VTODO
		* object.  on error False.
		*/
		function export_ncvelt(&$tid)
		{
			return $this->export_vtodo($tid, $this->uid_mapping_export);
		}

		/**
		* Import a VTODO as a task into  the Egw infolog 
		*
		* The ical VTODO component is converted to an eGW task for the
		* infolog resource in $rsc and then imported into this eGW infolog resource.
		*
		* Depending on the value of $uid_mapping_import, the conversion
		* will either:
		* - generate either an eGW task with a completely new id
		* (<code>UMM_NEWID</code>) and fill that with the data. Or
		* - search for an existing Egw task based on a id search, with an id search key
		*   decoded from the VTODO uid field (<code>UMM_UID2ID</code>) to update with the data. Or
		* - use the value in the VTODO uid field a search key for a uid search
		*  amongst the Egw tasks (<code>UMM_UID2UID</code>) to use as task to update. Or finally
		* - update a specific existing Egw task defined by the $cal_id parameter, with the data
		*  (UMM_FIXEDID). 
		*
		* Default the mode <code>UMM_UID2ID</code> is used. 	 For more info see @ref secuidmapping 
		*
		* @ref $supportedFields    determines the VTODOS that will be used for import
		*
		* @todo implement ATTENDEE and ORGANIZER import for VTODOS
		*
		* @param  VTODO $vtodo   VTODO object (horde_iCalendar_vtodo) 
		* @param int $uid_mapping_import uid mapping import mode used. see @ref secuidmapping Default
		*  UMM_UID2ID.
		* @param boolean $reimport_missing_tasks enable the import of previously exported tasks
		* that are now gone in egw (probably deleted by someone else) Default false.
		* @param  int $cal_id the id of the egw task that is to be updated when UMM_FIXEDID mode is
		* is set for $uid_mapping_import. If set as -1 the uid_mapping_import will switch to
		* UMM_NEWID mode, if set as 0 the uid_mapping_import will switch to the default
		* UMM_UID2ID mode.
		* @return TaskId|Errorstring the id of the imported(or updated) egw infolog task.
		* On error: a string indicating the error: ERROR | NOACC | DELOK | NOELT | BTYPE
		*/
		function import_vtodo(&$vtodo, $uid_mapping_import, $reimport_missing_tasks=false, $cal_id=0)
		{
			// auxiliary horde_iCalendar object
			$hIcal = $this->hi; 

			$veImportFields =& $this->supportedFields;

			//		error_log('veImportFields::'. print_r($veImportFields,true));

			$tidOk   = false;	// returning false, if file contains no components
			$user_id = $GLOBALS['egw_info']['user']['account_id'];

			// HANDLE ONLY VTODOS HERE
			if(!is_a($vtodo, 'Horde_iCalendar_vtodo'))
			{
				error_log('import_vtodo called for non vtodo type');
				return BTYPE;
			}

			$task = array('info_subject' => 'Untitled');
			$task['info_responsible'] = array();
			#		$alarms = array();
			unset($owner_id);
			$evduration = false;
			$nonegw_participants = array();

			// handle UID field always first according to uid_matching algorithm
			$cur_tid      = false;  // current egw task id
			$cur_owner_id = false;  // current egw task owner id
			$cur_task    = false;  // and the whole array of possibly correspond egw task
			// import action description (just for fun and debug) : 
			// NEW|NEW-NONUID|NEW-FOR-MISSING
			// DEL-MISSING|DEL-READ|DEL-READ-UID|
			// UPD-MISSING|UPD-READ|UPD-READ-UID 
			$imp_action    = 'NEW-NONUID';    

			$vuid = null;
			if($uidval = $vtodo->getAttribute('UID'))
			{
				// ad hoc hack: egw hates slashes in a uid so we replace these anyhow with -
				$vuid = strtr($uidval,'/','-');
				// InfoLog support uid from 1.5.001 on!
				$task['info_uid'] = $vuid;
			}

			switch ($uid_mapping_import)
			{
				case UMM_UID2ID :
					// try to decode cur_tid from uid
					if(!$vuid)
					{
						$imp_action = 'NEW';
						break;
					}
					if (!($cur_tid = $this->ecu->mke_guid2id($vuid,'infolog')))
					{
						$imp_action = 'NEW';
						break;
					}
					// good cur_tid, so fall through
				case UMM_FIXEDID :
					if($uid_mapping_import == UMM_FIXEDID)
					{
						if($cal_id > 0)
						{
							$cur_tid = $cal_id;
						}
						else
						{
							return VELT_IMPORT_STATUS_NOELT;
						}
					}
					if($cur_task = $this->rsc->read($cur_tid))
					{
						// oke we can read the old task
						$cur_owner_id = $cur_task['info_owner'];
						$imp_action  = 'UPD-READ';
						$task['info_id'] = $cur_tid;
						break;
					}
					//  a pity couldnot read the corresponding cur_task,
					if($reimport_missing_tasks)
					{
						// maybe it was deleted in egw already..
						$imp_action = 'UPD-MISSING'; 
						unset($task['info_id']); // import as a new one
						$imp_action = 'NEW';
						break;
					} 
					// no reimport allowed and task for id not found
					return VELT_IMPORT_STATUS_NOELT;
					break;
				case UMM_UID2UID :
					if((!empty($vuid)) && ($uidmatch_task = $this->rsc->read($vuid)))
					{
						// go do uidmatching, search for a egw task with the vuid as uid field 
						// is this uid-search really implemented in bocal ??
						$cur_tid      = $uidmatch_task['info_id'];
						$cur_owner_id = $uidmatch_task['info_owner'];
						$imp_action = 'UPD-READ-UID';
						$task['info_id'] = $cur_tid;
					}
					else
					{
						// uidmatch failed, insert as new
						$imp_action = 'NEW';
					}
					break;
				case UMM_NEWID :
					// fall through
				default:
					error_log('boinfolog_vtodos.import_vtodo(): unknow value:' .
						$uid_mapping_import . ' for uid_mapping_import given.');
					$imp_action = 'NEW';
			}

			// lets see what other supported veImportFields we can get from the vtodo
			foreach($vtodo->_attributes as $attr)
			{
				$attrval = $attr['value'];

				// SKIP  UNSUPPORTED VTODO FIELDS
				if(!in_array($attr['name'],$veImportFields))
				{
					continue;
				}
				//			error_log('cnv field:' . $attr['name'] . ' val:' . $attrval);

				switch($attr['name'])
				{
					case 'CLASS':
						$task['info_access'] = (strtolower($attrval) == 'public')
						? 'public' : 'private';
						break;
					case 'DUE':
						// will be reviewed after all fields are collected
						$task['info_enddate'] = $this->ecu->mke_DDT2utime($attrval);
						break;
						// note: DURATION and DTEND are mutually exclusive
					case 'DURATION':
						// duration after taskstart in secs
						$evduration = $attrval;
						break;
					case 'DTSTART':
						// will be reviewed after all fields are collected
						$task['info_startdate'] = $this->ecu->mke_DDT2utime($attrval);
						break;
//					case 'TRANSP':
// 						$task['non_blocking'] = $attrval == 'TRANSPARENT';
// 						break;
					case 'PRIORITY':
						$task['info_priority'] = $this->ecu->mke_prio($attrval);
						break;
					case 'CATEGORIES':
						$catnames = explode(',',$attrval);
						$catidcstr = $this->ecu->cats_names2idscstr($catnames,$user_id,'infolog');
						$task['info_cat'] .= (!empty($task['info_cat']))
							? ',' . $catidcstr : $catidcstr;
						break;
						// map ATTENDEE to info_responsible list
						// when we encounter an new valid cal_address but not yet in egw db
						// should we import it?
					case 'ATTENDEE':
						if ($pid = $this->ecu->mke_CAL_ADDRESS2pid($attrval))
						{
							$task['info_responsible'][] = $pid;
							// egw unknown participant, add to nonegw_info_responsible list
						}
						else
						{
							$nonegw_info_responsible[] =
							$this->ecu->mke_ATTENDEE2cneml($attrval,$attr['params']);
						}
						break;
					case 'LAST-MODIFIED':	// will be written direct to the task
						$task['info_datemodified'] = $attrval;
						break;
					case 'RELATED-TO':	// will be written direct to the task
						$task['info_id_parent'] = $this->ecu->mke_guid2id($attrval,'infolog');
						break;
					case 'STATUS':	// note: custom field in task
						$task['info_status'] = ($task_stat = $this->status_vtodo2task[$attrval])
							? $task_stat : 'not-started';
						// check if we (still) have X-INFOLOG-STATUS set AND it would give an unchanged status (no change by the user)
						foreach($vtodo->_attributes as $xattr)
						{
							if ($xattr['name'] == 'X-INFOLOG-STATUS')
							{
								if (!($x_translated = $this->status_task2vtodo[$xattr['value']])) $x_translated = 'NEEDS-ACTION';
								if ($x_translated == $attrval)
								{
									$task['info_status'] = $xattr['value'];
								}
								break;
							}
						}
						break;
						// this is needed, because empty subject is not allowed by egw
					case 'SUMMARY':
						$task['info_subject'] = ($attrval) ? $attrval : 'Untitled';
						break;
					case 'COMPLETED':
						$task['info_datecompleted'] = $this->ecu->mke_DDT2utime($attrval);
						break;

						// collection of fields that we dont support on input
					case 'RRULE':       // not yet implemented in egw
					case 'EXDATE':      // not yet implemented in egw
					case 'CREATED':     // in egw database, not in task field
					case 'ORGANIZER':   // dont influence the ownership in egw by this
						break;
					default:
						// only use default for level1 VTODO fields
						if(strpos($attr['name'], '/') !== false)
						{
							break;
						}
						// use first related field only for the simple conversion
						$efield = $this->vtodo2taskFields[$attr['name']]['rn'];
						if($efield)
						{
							$task[$efield] = $attrval;
							break;
						}

						error_log('VTODO field:' .$attr['name'] .':'
							. $attrval . 'HAS NO CONVERSION YET');
				}
			} // end of fields loop

			// now all fields are gathered do some checking and combinations

			// build endtime from duration if dtend was not set
			if (!isset($task['info_enddate']) && ($evduration !== false))
			{
				$task['info_enddate'] = $this->ecu->mke_DDT2utime($task['info_startdate']) + $evduration;
			} 

			#		  // a trick for whole day handling or ...??
			#		  if(date('H:i:s',$task['end']) == '00:00:00')
			#			$task['info_enddate']--;

			// handle no status found
			if(!$task['info_status'])
			{
				$task['info_status'] = 'not-started';
			}

			// hack for infolog bug: reset info_datecompleted for a not-done status value
			if($task['info_status'] !== 'done' && $task['info_status'] !== 'billed')
			{
				$task['info_datecompleted'] = null;
			}

			// AD HOC solution: add nonegw info_responsible to the description
			// should be controlable by class member switch
			if (count($nonegw_info_responsible) > 0)
			{
				$this->ecu->upde_nonegwParticipants2description(
					$task['info_desc'],
					$nonegw_info_responsible
				);
			}

			// handle fixed id call (for boical compatibility)
			// @todo test boical compatibility (esp. with $cal_id>0 case) 
			if($cal_id > 0)
			{
				$task['info_id'] = $cal_id;
			}

			// handle the ownersettings for virtual calendars
			// nothing set would do update as current auth user
			if($cur_owner_id)
			{
				// UPD-READ or UPD-READ-UID
				$task['info_owner'] = $cur_owner_id;
			}
			elseif($this->rsc_owner_id > 0)
			{
				// to accomodate NEW in non owned calendars
				$task['info_owner'] = $this->rsc_owner_id;
			}
			else
			{
				$task['info_owner'] = $user_id;
			}

			# error_log('rsc_owner:'. $this_rsc_owner_id . 'curowner:' . $cur_owner_id . 'user:'.$user_id);
			# error_log('<< ok <<<<' . 'task read for import=' . print_r($task,true));

			// -- finally we come to the import into egw ---

		  	// NEW RalfBecker Aug 2007
			// This type of delete handing is no longer necessary - thought it does no harm at the moment.
			// I think it can be removed in furture, as it's hard to explain to any user
			// Deleting tasks is now detected by tracking the requests and submited tasks.
/*
			if (($task['info_subject'] == 'X-DELETE')
			|| ($task['info_subject'] == '_DELETED_'))
			{
				// -------- DELETION --------------------
				//			error_log('delete task=' . print_r($task,true));
				$imp_action = 'DEL-' . $imp_action;
				if(! $cur_tid)
				{
					$this->_errorlog_evupd(
						'task', 'ERROR: ' . $imp_action,
						$user_id, $task, false
					);
					return VELT_IMPORT_STATUS_ERROR;
				}
				else
				{
					// task to delete is found readable
					if($tidOk = $this->rsc->delete($cur_tid))
					{
						// DELETE OK
						return VELT_IMPORT_STATUS_DELOK;
					}
					elseif ($user_id != $cur_owner_id)
					{
						// DELETE BAD  but it wasnt ours anyway so skip it
						if ($this->evdebug)
						{
							$this->_errorlog_evupd(
								'task',
								'SKIPPED: ' . $imp_action . ' (INSUFFICIENT RIGHTS)',
								$user_id, $task, $cur_task
							);
							return VELT_IMPORT_STATUS_NOACC;
						}
					}
					else
					{
						// DELETE BAD and it was ours
						$this->_errorlog_evupd(
							'task',
							'ERROR: ' . $imp_action . '(** INTERNAL ERROR ? **)', 
							$user_id, $task, $cur_task
						);
						return VELT_IMPORT_STATUS_ERROR;
					}
				}
				// -------- UPDATE --------------------
			}
			else*/if ($tidOk = $this->rsc->write($task, true, false))
			{
				// ******** for serious debugging only.. **************
				// 			  if ($this->tsdebug){
					// 				$this->_errorlog_evupd('task', 'OK: ' . $imp_action, 
					// 									   $user_id, $task, $cur_task);
					// 				error_log('task readback dump:' . print_r($updatedTask,true));
					// 			  }
					// ******** eof serious debugging only.. **************

					return $tidOk;

					//  ---UPDATE BAD --------
			}
			elseif ($user_id != $cur_owner_id)
			{
				// UPDATE BAD, but other ones task, so skip
				if ($this->evdebug)
				{
					$this->_errorlog_evupd(
						'task',
						'SKIPPED: ' . $imp_action . ' (INSUFFICIENT RIGHTS)',
						$user_id, $task, $cur_task
					);
				}
				return VELT_IMPORT_STATUS_NOACC;
			}
			else
			{
				// UPDATE BAD and we own it or it was a new one
				$this->_errorlog_evupd(
					'task',
					'ERROR: ' . $imp_action . '(** INTERNAL ERROR ? **)', 
					$user_id, $task, $cur_task
				);
				return VELT_IMPORT_STATUS_ERROR;
			}
			error_log('CODING ERROR: SHOULDNOT GET HERE');

			return $false;
		}

	  /** Wrapper around import_vtodo() with simplified set of call parameters.
	   * @note this function only imports Vtodo elements!
	   *
	   * The value of the member variable $reimport_missing_elements is used to possibly allow to
	   * reimport of gone tasks in the infolog.
	   * 
	   * The value of the member variable $uid_mapping_import is used to control the set
	   * of iCalendar fields that are imported.
	   * @param  VTODO $ncvelt    VTODO object (horde_iCalendar_vtodo) 
	   * @param  int $tid  id for a selected task to be updated by the info from $velt
	   *     If left out or set to -1 then uid_mapping_import is switched back to its standard
	   *  setting as found in the member variable $uid_mapping_import.
	   *
	   * @return TaskId|errorstring the id of the imported(or updated) ege infolog task.
	   * On error: a string indicating the error: ERROR | NOACC | DELOK | NOELT
	   */
		function import_ncvelt(&$velt,$tid=-1)
		{
			$uid_mapping_import_sel = ($tid > 0) ? UMM_FIXEDID : $this->uid_mapping_import;

			return $this->import_vtodo(
				$velt,
				$uid_mapping_import_sel,
				$this->reimport_missing_elements,
				$tid
			);
		}

	/**
	 * Delete a tasks specified by the id
	 * 
	 * There's not yet a way to handle the situation that the user has no right to delete a task, 
	 * eg. because it's delegated to him
	 *
	 * @param int $id info_id
	 * @param int $user account_id
	 * @return boolean true on success, false otherwise
	 */
	function delete_ncvelt($id,$user)
	{
		return $this->rsc->delete($id);
	}

	  /**
	   * Set the list of ical fields that are supported during the next imports and exports.
	   *
	   * The list of iCal fields that should be converted during the following imports and exports
	   * of VTODOS is set. This is done according to a given ProductType as mostly set in the
	   * $deviceType field of the icalsrv_resourcehandler. See there for a further description.
	   *
	   * In a small lookup table the set of currently supported fields is searched for and then
	   * and then these are set accordingly in the class member @ref $supportedFields.
	   *
	   * @note to find the ProductType for a device (like a iCalendar, browser, a syncml client etc.)
	   * the icalsrv_resoucehandler class provides some handy methods, like:
	   *  icalendarProdId2devicetype(), httpUserAgent2deviceType() and product2devicetype()
	   *
	   * @param ProductType $devicetype a string indicating the
	   * communicating client his type of device
	   * @return void
	   */
		function setSupportedFields($devicetype = 'all')
		{
			// parse ProducType label into productManufacturer and productName
			list($_productManufacturer, $_productName) = explode('/',$devicetype);

			$defaultFields =  array('CLASS','SUMMARY','DESCRIPTION','LOCATION','DTSTART',
				'DSTAMP','CREATED','LAST-MODIFIED',
				'DUE','STATUS','COMPLETE','PRIORITY','PERCENT-COMPLETE'
			);
			// not: 'TRANSP','ATTENDEE','ORGANIZER','CATEGORIES','URL','CONTACT'

			switch(strtolower($_productManufacturer))
			{
				case 'nexthaus corporation':
					switch(strtolower($_productName))
					{
						default:
							// info_responsible disabled until working correctly
							// $this->supportedFields = array_merge($defaultFields,array('ATTENDEE'));
							$this->supportedFields = $defaultFields;
							break;
					}
					break;
					// multisync does not provide anymore information then the manufacturer
					// we suppose multisync with evolution
				case 'the multisync project':
					switch(strtolower($_productName))
					{
						case 'd750i':
						default:
							$this->supportedFields = $defaultFields;
							break;
					}
					break;
				case 'sonyericsson':
				case 'sony ericsson':
					switch(strtolower($_productName))
					{
						default:
							$this->supportedFields = $defaultFields;
							break;
					}
					break;
				case 'synthesis ag':
					switch(strtolower($_productName))
					{
						default:
							$this->supportedFields = $defaultFields;
							break;
					}
					break;
					// used outside of SyncML, eg. by the infolog itself ==> all possible fields
				case 'file':
				case 'all':
					$this->supportedFields =
					array_merge($defaultFields,
					array('ORGANIZER','CATEGORIES','COMPLETED','ATTENDEE','CONTACT','RELATED-TO'));
					// error_log('OKE setsupportedFields (all)to:'. print_r($this->supportedFields,true));
					break;

					// the fallback for SyncML
				default:
					error_log("boinfolog_vtodos.setSupportedFields - warning: Devicetype not found:"
						. " $devicetype");
					$this->supportedFields = $defaultFields;
					break;
			}
			// return true;
		}
	}
?>