m [ Ec@s~dZdZdZdkZdkTdklZlZlZdklZdk l Z dk Z dk Z dk Z dkZdklZlZd klZd klZd klZdkTd Zd ZydklZWnej o dZnXdklZd Z dZ!dZ"dZ#ede$Z%ddddddd ddd d d e&d Z'd e(fdYZ)ee)dS(sExtImage product module.sExtImage product module. The ExtImage-Product works like the Zope Image-product, but stores the uploaded image externally in a repository-direcory. It creates a preview of the image (requires PIL).s1.5.4N(t*(sHTMLFiles MessageDialogsInitializeClass(sClassSecurityInfo(sResourceLockedError(sjoinsisfile(s TemporaryFile(sWriteLockInterface(s IExtImagetExtImagei(sRedirecttRedirect(sREPOSITORY_UMASKiiisdtml/extImageAddtcCsW| o}t|dd d j od|i}|tti|dti|dti|dd}|p|}t |}nt |||| | }|i|||djo,|i|i||d||| | n|tjp |tjo,|i|i||d||| | n| d j o|i|| ddSn|S( s Add an ExtImage to a folder. tfilenamet/s\t:iRit update_menuN(tidtgetattrtfiletNoneRtmaxtstringtrfindttitlet normalize_idRtdescrtpermission_checktredirect_default_viewt tempExtImagetselft _setObjectt_getObtmanage_file_uploadt content_typet create_prevtmaxxtmaxytratiotUPLOAD_NORESIZEt UPLOAD_RESIZEtpreviewtREQUESTt manage_main(RRRRR R RRRRRRRR!R((t0/usr/local/testzope/Products/ExtFile/ExtImage.pytmanage_addExtImageNs"!   ,, c BstZdZeefZeZdZhdd<dd<ddZ0d?Z1ed@Z2ei3dAdBZ4ei3dCdDZ5ei3dEdFZ6dGZ7dHZ8RS(Is The ExtImage-Product works like the Zope Image-product, but stores the uploaded image externally in a repository-direcory. It can create a preview of the image (requires PIL).RtdefaultitminiR iRicCsJtid||||||g|_d|_ d|_ d|_ dS(s' Initialize a new instance of ExtImage t__init__RiiN( RtinheritedAttributeRRRRRRt prev_filenametprev_content_typet prev_ratiot has_preview(RRRRRR((R#R'}s "   cCs |iS(N(Rttag(R((R#t__str__sR-t0c Ks |ip d}n|ip d}n|o|i o d}n|o"|idd}d \} } nZ|o.|idd}|i |i \} } n%|i}|i |i \} } |p| }|p| }|p|}|p|}|o'|d jott||}n|o'|d jott||}n|d jo|ipd}nd|| |f}|od||f}n|od||f}nx6| iD](}| i|}d |||f}qWd |}|S( s= Generate an HTML IMG tag for this image, with customization. Arguments to self.tag() can be any valid attributes of an IMG tag. 'src' will always be an absolute pathname, to prevent redundant downloading of images. Defaults are applied intelligently for 'height', 'width', and 'alt'. If specified, the 'scale', 'xscale', and 'yscale' keyword arguments will be used to automatically adjust the output height and width values of the image tag. Adopted and adapted from OFS/Image.py iticoni R Rs"%sN(i i ( Rtis_webviewableR t_access_permittedR,R0t _static_urlturlt img_widtht img_heightt _getImageSizeR)RtheighttwidthtxscaletscaletxdeltatyscaletydeltaR tstrtinttaltRtbordertstrgtargstkeystkeytgettvalue(RR R0R8R9RAR;R:R=RBR!RDR5R6R<RFR>R4RHRC((R#R-sH              R cCst|idddS(s Return a preview of the image R iN(RRR3(R((R#R st preview_tagcCs|iddS(s2 Generates the HTML IMG tag for the preview image R iN(RR-(R((R#RIst preview_htmlcCs |iS(s Same as preview_tag N(RRI(R((R#RJst is_brokencCsO|io2|i|ijo|i|ipdSq<ntid|S(s@ Check if external file exists and return true (1) or false (0) iRKN(RR,RR)t _get_fsnameRR((R((R#RKs  R1cCsC|i}|djp|djp |djodSndSdS(s< Return 1 for GIF, JPEG, and PNG images, otherwise return 0 tJPEGtGIFtPNGiiN(Rtformat(RRP((R#R1s  't get_prev_sizecCs2|i|i}|oti|dSndS(s& Returns the size of the preview file iiN(RRLR)tfntoststat(RRR((R#RQs t prev_rawsizecCs |iS(s Same as get_prev_size N(RRQ(R((R#RUst prev_sizecCs|i|iS(s= Returns a formatted stringified version of the preview size N(Rt _bytetostringRQ(R((R#RVsR9cCs|i|idS(s Pixel width of the image iN(RR7R(R((R#R9sR8cCs|i|idS(s Pixel height of the image iN(RR7R(R((R#R8st prev_widthcCs|i|idS(s Pixel width of the preview iN(RR7R)(R((R#RXst prev_heightcCs|i|idS(s Pixel height of the preview iN(RR7R)(R((R#RYsRPcCsK|i|i}y'dkl}|i|}|iSWn dSnXdS(s& Get the PIL file format of the image (sImagetunknownN(RRLRtPILtImagetopentimRP(RR^R\R((R#RPs  tget_prev_filenamecCs|i|iS(s+ Returns the preview file name for display N(Rt_fsnameR)(R((R#R_sR"sdtml/extImageEdittmanage_del_prevcCs1|io|i|ijo|i|i}|i|i}t|oYyt i ||dWnt j oqXyt i |Wqt j oqXqt|o2yt i ||dWqt j oqXqnd|_ d|_|i|dj o|i||ddSndS(s Delete the Preview Image s.undoRitmanage_tabs_messagesPreview deleted.N(RR,RR)t _temp_fsnamettmp_fnR`RRtisfileRStrenametOSErrortremoveR*tZCacheable_invalidateR!R R"(RR!RdRR((R#Ras.        tmanage_create_prevcCs|i||\}}|djoa|djoT|iz8|i|idd}|i|i ||||Wd|i Xn|djo |iSnu|io|i||ddSnQ|djo*|djotdd d d d d Sntddd dd d SdS(s Create a preview Image iRs image/jpegNRbsPreview created.R/Rt AttentiontmessagesYou must enter a value > 0tactions ./manage_maintWarnings/An error occurred while generating the preview.(Rt_formatDimensionsRRt _registert_get_ufnR)tnew_fnt_createPreviewRRt _dir__unlockR!R R,R"t MessageDialog(RRRRR!Rr((R#Rj3s(       tmanage_uploadFormsdtml/extImageUploadt manage_uploadc Cs|io tdnt|tijo't} | i || i dn|} |i | |||||||S(s0 Upload image from file handle or string buffer sFile is locked via WebDAViN(Rt wl_isLockedtResourceLockedErrorttypeR ttypest StringTypet TemporaryFilet temp_filetwritetseekRRt is_previewRRRRR!( RR RRRRRRR!R~((R#RwRs    Rc Cs|io tdn|ot|tijo0d} yt |d}Wqg| |qgXn|i ||\}}|tjo|djow|djoj|iz5|i|idd} |i||i| Wd|iX|i| | |||qx|ot||}n|i||id|i|i|_|id|iz8|i|id|i} |i||i| Wd|iX| |_|int i!d ||||t"jo|i ||\}}|djoa|djoT|iz8|i|idd} |i|i#| |||Wd|iXqxn|dj o|i&||d d SndS( s2 Upload image from file handle or local directory sFile is locked via WebDAVs Can't open: trbiRs image/jpegNidRRbsUpload complete.('RRxRyRRzR R{R|t cant_read_excR]RoRRRRRpRqR)Rrt _update_dataRcRtRsRRt HTTPUploadt_get_content_typetreadRR*Rt _initPreviewRR(tGENERATERR!R R"( RR RRRRRRR!RrR((R#RcsX  '          tmanage_http_uploadcCsJ|io tdn|oti|d}d}yti|}Wn||nXt |}|i ||i d|i |i|_|id|iz8|i|id|i}|i||i|Wd|iX||_|intid|||dj o|i||d d SndS( s Upload image from http-server sFile is locked via WebDAVs/:s Can't open: idiRNRRbsUpload complete.(RRxRyRturllibtquoteR4RturlopenR RRRRR*RRpRqR)RrRRcRtRRR(R!R R"(RR4RR!R RRr((R#Rs2         tPUTcCstid|||}|io|i|i|i\}}|i z~y |i Wn)t j o|i|id}nXd}|i|iddd|}|i|i||||iWd|iXn|S(s Handle HTTP PUT requests RiRs image/jpegtpathN(RR(RR!tRESPONSER,Rot prev_maxxt prev_maxyRRRpt aq_parentt AttributErrort_get_zodb_pathtPARENTSRR RqR)RrRsRR+Rt(RR!RRRRrR((R#Rs    #cCsY|i|}y8dkl}|i|}|id|idfSWn dSnXdS(s& Return width, height tuple using PIL (sImageiiN(ii(RRLRR[R\R]R^tsize(RRR^R\((R#R7s c Csydkl} Wntj onqX|i|}|oY| i|} | i djo| i d} n| i }t | do | i}n|o| i||f|n| i||f|} tit}|i|} y| i| dddWnOti|t| o+yti| WqQtj oqQXnnXti|d|_||_||_ ||_!||_"n|i#dS( s Generate a preview using PIL (sImagetRGBt ANTIALIASRMtqualityiUs image/jpegN($R[R\t ImportErrorRRLt from_filenametimfileR]R^tmodetconverttBICUBICtfilterthasattrRRt thumbnailRRtresizeRStumasktREPOSITORY_UMASKRct to_filenametoutfiletsaveReRhRgR*R)RRR+R( RRRRRRRRRRR^R\((R#RssF           cCsV|i|i|i\}}|djp |djo d|_n d|_dS(s Verify the preview iiN(RRiR7R)RXRYR,(RRYRX((R#Rs   cCsVt|tijo7yt|}WqMtj o|id}qMXnt|tijo7yt|}Wqtj o|id}qXn|djo|djo||idjo|id}n&||idjo|id}n||idjo|id}qL||idjo|id}qLn||fS(s+ Make sure, the dimensions are valid int's R%iR&R N( RzRR{R|R@t ValueErrorRt _image_sizeR(RRR((R#Ro s*cCs|iov|i|ijoc|i|i}t| o?t|do.|iti |d|i |iqnt i d|S(s- Restore filename after delete or copy-paste s.undot_undoN( RR,RR)R`RRReRpRSRfRcRR((RRR((R#Rs (c CsXdkl}||\}}}|o |}n"tid|||||}|S(s Determine the mime-type (s getImageInfoRN( t OFS.Imaget getImageInfotbodytcttwthRRR(RR R( RR RRRRRRR((R#R$s  tmanage_afterClonecCs<y |iWntj onXtid||}|iz|id|i }|i oh|i |i joU|i|i }|o&|i||i|||_ qg|_ d|_ nG|i o3|i|i }|pg|_ d|_ qn g|_ Wd|iX|Stid||S(s When a copy of the object is created (zope copy-paste-operation), this function is called by CopySupport.py. A copy of the external file is created and self.filename is changed. RRiN(RRtAttributeErrorRR(titemtresultRpt _get_new_ufnR*t new_prev_fnR,RR)RLt old_prev_fnRRctold_fnRt(RRRRRR((R#R4s4         tmanage_afterAddcCstid|||S(s When a copy of the object is created (zope copy-paste-operation), this function is called by CopySupport.py. A copy of the external file is created and self.filename is changed. RN(RR(RRt container(RRR((R#RXstmanage_beforeDeletecCs|io|i|ijo|i|i}|i|i}t|oYyt i ||dWnt j oqXyt i |Wqt j oqXqt|o2yt i ||dWqt j oqXqnt id|||S(s` This method is called, when the object is deleted. To support undo-functionality and because this happens too, when the object is moved (cut-paste) or renamed, the external file is not deleted. It is just renamed to filename.undo and remains in the repository, until it is deleted manually. s.undoRN(RR,RR)RcRdR`RRReRSRfRgRhRR(RR(RRRRdRR((R#R`s&    cCs|io|i|ijo|i|i}totttd|nt |oltotttd|n|i |i}yt i |Wntj onXt i||qntid|dS(s Commits the temporary file s finishing %ss isfile %st_finishN(RR)RRcRdt_debugtLOGt_SUBSYStINFOReR`RRRSRhRgRfRR((RRdRR((R#Rys cCs|io|i|ijo|i|i}totttd|nt |oJtotttd|nyt i |Wqt j oqXqnt id|dS(s Deletes the temporary file s aborting %ss isfile %st_abortN(RR)RRcRdRRRRReRSRhRgRR((RRd((R#Rs  (9t__name__t __module__t__doc__t IExtImagetWriteLockInterfacet__implements__tClassSecurityInfotsecurityt meta_typeRRRR'R.tdeclareProtectedtViewPermissionR R-R RIRJRKR1RQRURVR9R8RXRYRPtAccessPermissionR_tHTMLFiletglobalsR"tChangePermissionRaRjRvt NO_PREVIEWRwRRRR7RsRRoRRtdeclarePrivateRRRRR(((R#Rfs   !   '0               !!1#  &    #     (*Rt __version__tGlobalstProducts.ExtFile.ExtFileRRutInitializeClasst AccessControlRtwebdav.LockableRyRRSR R{tos.pathtjoinRettempfileR}twebdav.WriteLockInterfaceRtIExtFileRtzLOGRRt zExceptionsRRtConfigRRRRRRtmanage_addExtImageFormR R$tExtFileR(RRRRRRReRRRR{RRRR RyRRRuRR}R$RRRRRRS((R#t?s<)   $     0.