Flickr-Upload-1.32/0000755000175000017500000000000011064317102012160 5ustar cpbcpbFlickr-Upload-1.32/t/0000755000175000017500000000000011064317102012423 5ustar cpbcpbFlickr-Upload-1.32/t/failupload.t0000644000175000017500000000107311026041454014733 0ustar cpbcpbuse Test::More qw(no_plan); BEGIN { use_ok('Flickr::Upload') }; my $api_key = '8dcf37880da64acfe8e30bb1091376b7'; my $not_so_secret = '2f3695d0562cdac7'; my $ua = Flickr::Upload->new({'key'=>$api_key, 'secret'=>$not_so_secret}); ok(defined $ua); $ua->agent( "$0/1.0" ); my $rc = $ua->upload( 'photo' => 't/testimage.jpg', 'auth_token' => 'bad_pass', # we're supposed to fail gracefully 'tags' => "test kernel perl cat dog", 'description' => "Flickr::Upload test for $0", 'is_public' => 1, 'is_friend' => 1, 'is_family' => 1 ); ok( not defined $rc ); exit 0; Flickr-Upload-1.32/t/progress.t0000644000175000017500000000224311026051566014464 0ustar cpbcpbuse Test::More qw(no_plan); BEGIN { use_ok('Flickr::Upload') }; use_ok('LWP::UserAgent'); $HTTP::Request::Common::DYNAMIC_FILE_UPLOAD = 1; my $api_key = '8dcf37880da64acfe8e30bb1091376b7'; my $not_so_secret = '2f3695d0562cdac7'; # grab auth token. If none, fail nicely. my $pw = '******'; open( F, '<', 't/password' ) || (print STDERR "No password file\n" && exit 0); $pw = ; chomp $pw; close F; my $ua = Flickr::Upload->new({'key'=>$api_key, 'secret'=>$not_so_secret}); ok(defined $ua); my $req = $ua->make_upload_request( 'description' => "Flickr Upload test for $0", 'auth_token' => $pw, 'photo' => 't/testimage.jpg', 'tags' => "test kernel perl cat dog", 'is_public' => 0, 'is_friend' => 0, 'is_family' => 0, ); # all we want to do is replace the default content generator with something # that will spit out a '.' for each kilobyte and pass the data back. my $gen = $req->content(); die unless ref($gen) eq "CODE"; $req->content( sub { my $chunk = &$gen(); print "." x (length($chunk)/1024) if defined $chunk; return $chunk; } ); $ua->agent( "$0/1.0" ); print "# "; my $photoid = $ua->upload_request( $req ); print "\n"; ok( defined $photoid ); exit 0; Flickr-Upload-1.32/t/testimage.jpg0000644000175000017500000016644011026041454015124 0ustar cpbcpbC  !"$"$CPhotoshop 3.08BIM703/15/04Kernel & perl.jpgnChristophe Beauregard<15:55:4408/04/04#17:57:49PetsiKernel & perl.jpgPets" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?\*OB8Ġv`s)v0k&vf?A(fc;łԁz}4;Q{QQR}ڟ#Z2 E9+1Bw2r!V%C(\O6>Z#,zmXR]c}rx@Wx#֒i:GpI8<p[jӥ+UU&ݖ*NEfP>^iJH?QJ3Q 0ޔͥ%2S0$ρ9VwNyj6SQd\dc'=̧,Hm<{j>! 8Z5ÀqFMN!RHUPq UH?yc4r&y5xéAnAc}+66nPGq5 [lRSMm=(YEllA%+і[(h[{bzx-I ͹xc=OJP/*e{8Xx _Qٮ W:l3IZ>S<+T+n`njҵ_ЙyBp#V:s(W_ٟ7|~uO6u⛵t);r}aVsVP%dp^f-i*8zԫ[=\cc.x Xd.~cg+c9d+TˡxƁ.IK Q"+v1{*bCR ?ʘ3N@ۀ>bLTy qE\`q4$(pW<8 JNۂ1<$p5G4bNWa; &OxjMVK!O*&ISEzLJulC1+\:\vKKVŴKj8F6ǵye3[7I<#9$"~l/]mYrDrӊ断sGԲ8:~VcO8|Ѽ!_edҷ[pF7n-v:zԏCץL#96:栖xh>lt?,{XƏ`YfK-[Nː;!@|?t #G*zLWAsO 3j{{JPg]:زXݳYutdb!_ٶ@q}0|tKYEÝJV28r֫IR q>i$xȣg80GU%U|i 9ߥmien%f(?_nk腳ۀP-mwIYSz3Ibc}ռ!w2h1KO+g5" mɷ*v5nF1R,|? Rm 5gKaۘO5>q_DyP}FGyvΔaV/rX4csy~H zѪ|.RdfS&܍zHͰQ.sSϟS$cDz=պfgb{03gK8ɏ4)DI46}|>$#\LZe 0k H: ?R)9^ƪuუܒxɤ]d$'ڽԌ4\S]ޣٶlmH?|S;^=*iiK<'$^FT wf5~vlk}2ocB2>Jܧ>!y^vyZЧ-՞ߚeqB%{U|8e<*- L>$mvkj* -3rO80; zV姄cPu$송dP9:8X=zZmsnO4siׄ ?O k}(dF5j'e91)]ñ9W@=,dN03PVA1"G*p?iYw1c?E q~i&[Wi*/@>Z esݍG.W .n>;Pmz gc Uv#ͫsX|9yT*7 gQl<~]*䚴B)$q3Bn%wЃܨ܋@:h ws2%'j?y"d3asyV%DHvBWw(@d)-…#֩SfsY;s!E"zzLqX[1ƼrMV>&B9QZm6`5R1^%~L zn-91 BgFR7q\{ӧh A08I増C)`ݍd(L.>jɽwE[CT@k>W_Zx 9ϯZG_J/uj5W #xvw/Rxz$cKWmyΩ$VN?u> Yl'+dsT*rr oj.#0A9W9az΢Pij{ 9֣q` d@_j OZ'm,n, !@?oGVigU$>UMޗ/#bF1rjUo6#ҨBꪣ'' N9{ԥeq|4-»vxYb+ГW&p F={WE/#=zVg%taI>nzB́*Hkɻ'^G^r\ 0y 뾚;oųa?LSx0>ďC_;X%#66ɼ%9n)K{s;葩ڥ=F 2Fr_;_\bl-׿ν-mnMnBvϤFs-өnw|ɃsX";o\彽|KrX79oօ$q>uIDV@?ׯ oy>+xOvSKV UOdg:?nI2ڃKh 1xϵRJN*13mJEepmƾ`+@=}Pftb>M( V>7m%8'{PfL\N1PΣ_*^> Np=~݊* >kaˆ7!B;ɯ3F3vaq8 }p> ہۃ_;Ũ7w, $Hc ci;5lܚI/&x\$F1ҙ~v͎'<} F}r)ϩ^HE@u5@ wn(+/^.rLc$|5Fq<k[iot}Lu)omjO| ]+*1NG?k(U[|G3*WfI-?L׃Ii*fɤ͒׮i*k] w%LmdJt: @? K*#?ҦRya6fv;_- ~]ڜQ^$|݀pi]|Vn=."3QOLqs^mgm<'9*ӧ 8*N=j]ozhQI;T/-0 ܆ }6msƥ8uxN2`[;xOw+NxsH,&`鎾QwѝW$yc~[+@G=8'&,;pR, g8 Ak) WspF?JA+Ff$7-0a֠6s.88N54vJ)/yL$ssg3Ue5 \r\ZII^KGnGRB4^ez+ĕ^j=):P$ C{pmcDuEd% 1*reR}\4qt Vf-3uJ;[c DwifRF qڞV=0S؎ىګ]orB,Xz6~ڟ4J0\qOEp8Bpr3I%Wps Ӷ +V*$_H rN=28QR84)kxLMp^Cv֨9`U 8jЯ ºB]]>t5o3}^^8#'_~HyN>mA'N^z\Sg xm(ʟ~Gߛj'Sգ8U4[1~6if[t c>29 WӾ5mG^@|ݭ@m\Lw8>Y86eNᚹƲ K0ĘT!l qZzqIR}=7ŞjZꑴLY 7zRʸ܀R 5XF*rc[4 <|^r1ZMb[f,j^-|sK6'P@96Hp>S⡴/nZ.|rUG52Ge"9RTIv{&+3M4ӷ5;ß:3$"]d0q6cot?“znli_[v^m.tC9À~(.>~iS``;;p95J9Uͻy̅AaYF-bg18\ɦcc?)*K>g *Tm#*b 7\5MoLxv cjxK#yϯzuu35:r CkceNVlOXgZd&@$c\%/O8AqE/dvI7*Iu;]Z%LF+(?)$gɞo(3\'3_ZO:*%$or8j~ltCq`ژ?[v~i1.݌g~?&v*[XV]yǽKac,'\wnA$9tV/C`?fOI0Z(fQ ZZ8FP}f3 d#C[[,d<'ٙuZ$ vԄ95qI>&2y~wb28sz}2=M>MB%qZ-9$.qJ˩WO:ȪPf8F8C+b\ft5ϛG.sOB/ q lJKP tG;aʱҘ̈SRVf6N@a\`v; `*ry8\_G4x㞕;Wx{QH嗂88J-y!xloϾ1)w=8֫scޗ3qvjG}9봓]6'5Q[ g}Jr:Vi ff_nut5+2ftʃڱ[GY7Ȫ@=?:P`Fs[kwn k& U:`sX,jZwcEsӃH$d_jzg z +A@ Œ~=p'"NV 9@#=TޥUp͸+ڐ HǶ(spxqv4 Gٽ$F|nN@a/i[|s^sI霎Z|'p^bLsRZǡDD$X!idw\?iJcoTzg'lHArKB)mL+7)#ޔm旜k.@JNj*`$4N*yRz1A af#J2*H-2PWs ?)&ۚe!5 ( t7>lZLmfMc=GC*wq^RQlG8 g5[LB&Q|JKo2+xuY Ie;B*Fnt? 5 =\W7nQ\# 1=ю5n_ CBz~KZN& r?^+[Kk!agmxX=W6*&Մ>a8cI )#E\DFc%AOƚKmܫ!IǷPiQ+GPGJ։``<Qxꦡa.&WdyU!Mv&U#ʼ@>rG>O.'mI $L';;YC6:~UR/A {Z`PyQx!󶛬JiYxn:w?ٳf*:לۀ +`ʕm^ú0t\Om |cW.[p Ιϩ5uƉA`+·jڒn`6UP| f~%x~'m'9O] g9ȬzM7:Ndhmʐ22{)xXr3]Si׷8!,8T- ivv]6{~{s+s: Q>Q۵TuVlz$Q$ r*M1lZ29G3c=9RYKt کރW'bl~^*e"Z#5Cc<FqQަ*@S̴LSKMdհð;o%QYEXǶ 9slg+?p1R4¬@fBsG F2>up#Z -V ZJiUpi#lodc8SN],<ԇp9Q#ϽGM]Ba;LG7,OOzt6WRw/I9VO5d,ѼLa [!OֺkOPJ]d8+<=xL8n[ ¤G<6H$BEp0$QO}b$],qFb,CR 6zG44۸{t<1<2 ^KoxJcSm3[F8J[_R%Z4|9ӥ)q8X[IhHd֙)H|lד~%e&;g G_zA&ey DS~oEC*q Z'öu̳Al5ik,[/+BX֡(Spj9kvYg/ BY_Ғ0涮mUWpK7s1ЖrG>I/'l7 *z*@osW-Nvf9 Ygzɚ& 5wrG|T`rxϥOh>bq5P{RwN\QR^;r@'C[F$;1?~d  iUO#ל&rVDIWB[|9^ ꤦ$aqչO8}?"hg9}+|- ]X+G0's]h%IZZ#3?_b|BF>@-3-e~U֓S%6qsUpj 4N[»7~Cg$}vgE221VuJ"O]l%u<-Pǡӎ4^x JkƸ#v/r/IϔIK*gT-=Ùs3 "~Q 9=+ьiiRR]7RhR@_^pN=A^Q1]׎&JLn}3L!19C)߂,IGE(n}>?AHFΘ(W|pzm4XMb9 lWg]>?'/텣K!s#o@Oc]ەbrLm5iMnM$+rr:(n8+ SRsi8 ]j1$vEf$SJ^Ԛ&B՚mWhҴR'8ڰ#t: yyH>b?${\?:\%̨8b;ײ-F?vW1$|2@2n|oOwNgUn1N4QUrOQ6`_],w\ΞsɎ9رV$c\c}yY4R6_*~Tu[ Й/!d =Zǿo#4 $e,xWk#uwZ{3Vɘ};vkOf/׃k^%5_)n@v¹֞lgASJXUh+t2T|E =X]mU# *,Z}C/OZ滾4cdFAQV'T 6DbFcuzقh T ӥEՎY 8Tk&ݕqǐр?Cuf "ےФ8 ]|7t5\mjk3}V ͝tc ֯W09X^dl`V#Y!*2#>*֝s Hde C.3Uqڻ'dLupMdoNFS"N**h^2NN@^&u\vSU\pjn&rqkxGpTV沂:⤲]*Սz&c:)d"A+pTcLK]Pd1$坙VAb:?NlUgtMv*34pNy\ޕ~lesM  ΫX|Azo  p*sΥJpbd088WH-;MEQn>i >p4I%\TJ\m{T<2ǹ)7aH* $S8=r:Tэ>px2<{Ĉj킴p|T# Y-].d{MFX^%`I T:}ҋsN{WjrYsZV+jx0.1T>X~kC[޷-"qڱؒr'޸սERՄu鎵B:eSrvZ0ި#ڡE]"9>ƣ,v7~\JK(7lVtd8EjM(O7W 8sMI%vSNxfja-8ƛeGw2rIQ޷!2FzuW$<֯X𫄚~K—!Ш溈 כx XT$C8=dܬ yi<+*+sM;jF dƍlVsO摔23$I'#ʜVC-H9\0ӚSi^zsڣy JE4E!qZ!^~XL㟥TnrW8ғC 9=M:VwuT$ڜJ sMg hݷӭiÔH:SK'x9!s(c˷Wյ NX9'S@s@rsm5sGKH}h֗ #ږ0@j( `0:RAv Re>\@w95Ӫہ$b9n@ޕiI$BI%|#_j.J8KffxU Wª6TI^cgp,G9aE|; Ǹ3sZ6R6;|ZڍL1r$vSeGng9>&VUh0rǦyHTQАs*Uvs-(qH'yz=ZgF #iQٗiD'YԦڹ"8׊Y LXwNFPʜ#Z*q5rKG=WoR~ʠsQU?5ᷓ~؂Q='Տ:Z3>K[6 UԴف>%jmu,?6=+K=r[Ln|z%m"88!}i8Y!UsNs@eEY%}Nv2lMfwVFȮRhǘH p* #FX$s,9&aj#fa 9z!ᛣ*Mi9tg@ <~G6O*@}b>{#8>m9bD U]͕\2FEԐgVqЊivrTiԩ"|#ÓթSjG5(8mQ{j[} y]G5p>`nb5pQO#% .#Qרq<NՓ ASeM6x_6!dMdFԓڭO Qg!THKh%kWpnHQysvEW$c8.^SA5Oy1{TJ.NzSM;t苍2-6Zmë7 [xvx[[iTy7Oj|Ku{#uW}ߙy_uv&47uuw\a8.ٲ%aJݎG\t"5Q=`>+$?-0*z nH䌩~*3}K\UgW_>áڡWsq8IIoCJo&#GJOKmR18{Ӝ ͐yy5vՓ"%D[4Ʋ)!vE5&,6ӄ-GHxC g+w?)n#P|i{TTGryj&Eʹ~EEߩ+s>:2l?.}yN$Z3`R݂3s^?uC<+#W!H>KzQU w0'E8'3աqؓY 6ܳ*9v$ϭ']tWռ˒Fs cX&ۈWJйf9G[5G ݒ1`yR.>kFnxMXP|g/maRG~je{  5@dtB8rwTwDcA8nP26$VqIV.7`)׀ P `񜃅 1])R q*emJX;.\pHm4CRxf6]̳6^LdR"E!K '4#%qAI3#A)\﷮)EYZV%{z2|7(b#&@P?: ǭ*ݰOo9ʢvs=E? q֡y93g⒓޶^Fmz֖WL3I~iI(> $(?Ƃ3ۥ-B'j)x 5g>ޔqE 9)h="%O o#86m:͙gn:>ZAit9 J4Kxr#MSc\ u8 /`X:Z4,s>@N1V>2qNpEt03mHZA5f"N8j \(Vs2+c*}}ɴ?b+ IUW&=5qFHS$>3TjHԒ>@?J )fM,bG-85zÿ?>DNZ'~v2.c?ֽoᶮ.ccOW%aZGo$xȐ=*Gm**rHlcN1gvZ_i,mu0J܃<>HNz?i>#xbD݃ cޫM9Z#>wfY񶞐+&׌~T֑W M:]i VenK_ojkYYIq2ȫlQ.A''9$_v;r{bn!e?^K+ X6ӈ?: [cV`y;z ׋w#^A:׵\`! PǬ y탞F5&oI+/ֈvߚ! s<.'Sttv,fz=:Էа>M$8fGoS,Lh^15Wfr[s<**6##W)wVp?Қm E6s2QRkA2EO<Yr%3XE-R1; gn:IV@[$dU;@8#I7%Z1pwnqQ8$RI@S?E,2IUlх\H ӻ9P9$4"dmjU 7 CP&ٖ`S XK}d:u1ӎ:~`V<Tbte!Svg8SYNGCPʑ0=z@.tW[AN+'4,H\Μ~fZ8I`>E? }:jzb+0l@P˖$7oLc*=3i\Wjm u*w`L9=HߧzVƵfG^$.ҤII':*;0vH^ b6ͻw9# "}Τ*nq)_ө7Ut2RU<斓PxVPqF{R JVh?ҌR$w-Pviflo'q[v4]&쮋9yh5A'8X1< T+V/e>4vz4 Ms|g_e]n)FZO+9Ѹr+kH)U4`1]^C8~ZeKuнxzU}cHpB= Uax [#lq]:TQi2PW[m"q_vj*8` g;u;(8<TR[y`{V6yshXpW*åjE°#i4Z}t} S"pm.0=Nj#1A[hRyu m+ I'WE—ܸ~归F`*^ӂ9|˝FrztϵS{ 6K]%B19$$sG%8Im,p'c(gB@UһDc70Oxqև=teJZ8o8Tpd\42Zn-o9;td3DgԸK;n(sx@S2'0?)Oo͋48,=Zh|HOC;D+_ VXè^QbK+njJמ|WpCHֳcz\#ѬaI# uN\+qe?#9Wo @Xuc6ǡF)=ɅlマjBsR;-V"IF: 5ʐF~c=x)vw t-@}n)DnΠO֣_+ $qSEXs* -!b s`jo\h@wbPOM־{5ZSm˥rޫ/h"ޏŠ%d-!ҁBw{9SEhCh2LW Jv|`G$u=Η{6zsJC[8jӭJnwT9=5)]6M(F''5lJJwc+, Mm!0{SUɝTeefuM(\l 2>o\\K5(?)`$r4KkݖuJks k"`*=\I(N=OJX8f 2sZŴ.u*<7x5~@(ݎee% cgUѷ 5"d @*EfpӚeҪf3 е+ zTE]pyzɹYbR^=+fLNqNi& $ |KWN~ ҩ:VMхu6*b۩E {bC#\1I-Cm Gs8$pszUkrU%7nWR{bOLQ_۫3#8^ySa\+vԐHwsklَ6ϱӱK$n}?J"1׫po1V{xߺ3UI.$f$9U{+iuaGfVl/fo* ͜㏥iX_J"*a#¿a>lepgӵv:r3Ip OS)G[|+IH98lS$i.7g?Omb)!>QMjDhR{x́ݲ3Ӛy ;.xqY:η =k1\:]@.~q6Kn/#8t# u8BDV=-ZfFdNk cdJ6OL>c =i2d29Vb8+PV]#8Dl0199T7&UȑBda-.@>;Ui%dvEFqrj2;Xzu}LoMgdQ!E%̌#ܮĨ?Ta8Pɸ68(&++s j-VR7W11Y3]Lg&b&o)r*rjsƏvW v>n8hh|I;ޜfv wxmpԶkKPk.-BXc$F#I 4&NqEoK>xMp)ϥ`z4nHtX .?JVإ%-y6"dV!u,>w\b;GmoukWTKkRdw'Utʤaf[ZbJ yuepEEZf[줆=t9oړkir}JΦ31FykextMP`tQVVUTj9#e*+)X~a䎕},w ˼H @Fw-̮r1ոtv85z0$zUfAUӵ-,615VK3ԯl<|h ޻;f3xM4pݍM6C-rasd$WUY-IK"Ƿ?7Rw"}-óQ֤[m?!j޼ӐY\c5{"̮c9PFzvv\ ʨ`AL6"6xUv^#% Vvs"/bٕBsoHR2:Wi%$kï[o]K5GR9\謴=6٢pQמ8fّ]C@)qbzsBq|3..TQ0@\Ǻ6/Z(0?3JOm Dʯ1*THq SHmۃM @dU ӲFIX=PmBD8$sUՀ?Ψ6Fu+R7vL{`nv\ ƢOWqϽ4MGNnl&d sGWq?mH™[1ҼidS$sN.VuķR'Ex4HP}t̒M5a ɤ֪39di<5#CNȣ žl-#uLے}Η#zP"BE1xo‹VHl y !mRx >LPi 6by0=;xJ^jOef>HɮBȭ .rNFqZ]fEeܧ霹kEл@Ƿ\yF Hֳᔆ؞lRLaUr"9]ޥi/FG9$ ^ǚ"W9>zzd~Ojٷ@8ϯ֪Dz7b,챂juk! 9y^zi9=]ޤf [xs=뙿ե SXv}h4NRFf{t$Wzƚob\"Wc&cw5_RUha~s|+CS-'+۴±AZ$ΝYZ{܃EJ ,ՌBcVl9zC>cBzd3揑8>J JDE'$o+ixpgN,$"3[Z*235[d#8˹a+/͊\<40&2%{~=cF\^ȩ+ SeH*f?%*A `jZ)XB=d+|͟º:<ڳB)bۀ&ܤ~bqj8i#@bӑGv+XӤ%T;Y#I?t a/Yc9#Qn+G. RX+;U`_n J:nkj|4#^veXGt^tc~"f/"ݓV6,jCnS :oki5%c_p*8''EeZM"#W6JʙB7qҫ}oK~jr%[ƐnB";KR[s3z f[!xjW2YQ}vӇ-V9 A>A ䷖zₜ GAҠ{鶞FTݴx=s%~cp8#3I)DdGFG WzC#\ ݰ#CZu*gK`c硭T@AOJ&e;օY@r8SuԞ3@8ZKvǏʲ1S>`JU9GJ }9=1PlA9p?:T<ÜzKqqJm`G4^VOBF0y 1W!,@jrj &T*AtsG,޽A ܿDoN:h#;JTR.Lg]B!07/ZQm: v,)]R2UqԊ3̰ S~7c;yWazU_Z=LlLRE899T?!n3IH[Ě?,Tg Y;NIXQ$2urZLh7I۞2]KϹ@帺鞸К3ڂ/>HgY5(3=1MKi!Bg5ŵ;udQ\I+68赒Rjz;Wd];sr]d$ {RUT7=g@#jJB%+m}nwHdAS˶ 1K(z?|*)ٖ"ClU=B30P<þ|C h"l1%L>|6] $<;ZI)_ֽ.J;_)9V޿JKqnP1ՇU LU-!d>8GT=:^O]vhIqWVw`v @XTmq<%tUAuj^Hʣ?{=8ǽTy~nJeHsgmi{ v(RGzr uZDa'~(1vRљޒ |WL9䟺~#$n__JH岣z7{+j|*39'vCWsVJ=1֫'pʎ?Z]GaEird ;וxZTNkԵ jt`W bkJ1ĻkmPC SM}c95Vʑ{5uQ:96GSSA!݃3AE*He(eoFvWRCH,61xi$=OjOznG ڕ\]OBxP['a]r==pqN ?_zVQZ=P,hnr>1֮X( Yv_z7tuMf#-r;w_PoB8D,/>[ZTEN~,I6$Ek.nWئ֭VGR7*k\ޗ(\ٴ-cv'_oDKAϛdqk9luM:Q+J*zs-#\O^;*n/(PHKebe1S:\/}̱[q=?7z2dmO|zWUmvuj]2QDҴln"7Iƒ$l@PNFjKx*PZukkI[d֫e86fp~cmلbsc<=zeǙt /59YR> >#-UP/>d8YM{w8 ml#c1։[ zSA˹kur'1Ubk4bvf ]Oֺ]:\DA{UK1D\W8Tes滝R3`W3 +9Crm$ |c8tO=GPF~f*2AVklxnDAə!7rzRdkJFҼb {Nsf! J1ʇrbk@2^3zA|c}+|>u4U^}Ҭ:zQQ{s\ 8KcvpI'*5nyGZQvI7d}x[sN6M p@\֕WҦ_-@gN0:I&BcԬ^h FBH]ݰPȠ79|$cr׸QQY\ޓl vF|WQ*]GUqfa[<{#{ב\O[-T:4-bB @9&H۲(^U.oZYgbsrJ5ΧjРcZ[H0瞙C*բ/$5GxlMOإBU2(cWt`Uv*  T}+YTkpOrN˩m~բhe[ ڼ[u meRE}wyiEdsWxQo1 ;2gآNnw<*&.OA5d7~dc>*i֡9f`ޢo<=)34m p03Zv2'v0tydOfqSmKG= Z\DjQ֒2 0=1ִC(]@$pCNc%Y $Z$K#ҏſ̱9aDӭp ?{f xjݣVtXzMrMzZ-K8=r288$t&ܳ;1,O= #OQ*5Ԋ1qwZz)qNG8=psǦztӚQW*@jM_;H%,CՖ &P}ZoV5@3j0Y&$d}( 1Q̦u-Xtbx-Tl $c{kY],y )j܅U篽e`,09&vFsٲ@qN?5wzzmags~'> \^|Bp#g:ܪVyo-~1n2:v^/wh|@9-{]+I-&b*G΢1$L9FBoz|Mf/ >tx0GU:+gD%dHaV"Ne!69ϭ&{iALM a_> GI UV']EXY']X#֪I$o9O=봎4 (%V\ʂێ:={k&9.qޭt1qQ*REESU Ӎd՞9⺽<ё8'Tbޡ.7GN٪̪.I!@A4A޺lD|ڙ Ɉꢥ[8V]ɐcf9liCBU ?njLUb VTL2;'iR\:ԚmII {dwI#(ӥ H<1kW[6L#VFq\dJ돭)nV(!-ՊZqr:עjb1bb$K󑞸Kr?mv'5_b;ʣVlbX$u2bJVsJ&ћ nX#AEkI7s*}Ӯݯ<xh;xqzzx0Ϝ䫃VYz1PDQi5bVXcK0%Yqht%A8c|Ɂt}dݜg<U]+J:4Ti =ֹ?^3€>K6UARx©^ē[ `AvҊR`Һ^HTɬX JH0Rr5JK["C-ui8\̗.ј$A#}x%8Z5-w7ͼuPpO3gQB6z(̫ {T0YzUrfZC{Inz{sQ|3ܚ=o", z&)B:9N*GD9 5:19psMPr21O+|ry5;J5m@ HBcW8J=`d#^jRIG[5MwjW%G#;tEs֒Hsz/_e&g]9U$dI<  o\K:"#in22Ni9rOl&(U =WxWKNV1&Xn.vr>$D^W]OqIقN{KbkTPOQݘLIO8oy xF)颎?>  'ooJ"I^9d$?UYh(snI>bBViin`;v^QWŽd֛~Ex_TlH wT7\4L>g9p5ǺM_5V-gڋ+ۥyDѽӤPHB8q\N Ɏ(*P =G+m6a$bB^\G>~մcXV8 6I [Ũ`i-Cn*x#..d#zj9.vMĨT ]@n~F"qYcIJw8c:qjm-~GKxp5mNCnR|3ǘS={Tym@$xN6Huj~v$e#gEJ+^GfS.4`t=Ygz³)I" Tjʣí)\1P@8٣LFRGSv̷vBB=B-v9g"tSmj[]Fe{!85b\l)N5uDgiCXP2OT6q8)WW--qRlFYPZFC08qCbĜ/piQTPN85jCjdzMŞYbo9a#>ntLsWż]Fzv+lvu8G&Qٷ r8#jLSzLKV#K_#_318ԩd#E]մm#K 68lêerGdΈQcBi6YHw5֪j1`d.M_꫶azi(7)2 'cc~tN qS^vn߳WS5i3rqS<6 B'_J~ P"#4s)9KG>f:3$F;ă6.d>~l楝åܴҰ B3ɭevLZ@VcNZOR^H| {Xퟔ* f;I/>R3T41~_xȼUSñoAF&y2p/TבK5k4|cJuK0۬Үm~ }?Px9$z,WfA,֟"Fco1p9?zY]Z+lO ds\u4k/%X8 }V229Jyv:Xӭ7 ޷ TB9zuFrAl VL5_# g] I2@%chhrz8W $Z)"!9;pFSqz3K&0t r=*Ys8íVxā@q*lQM#I[jd}Gy#s8|?JtƇ 9߾*3 *r ^˓RW7GlێEebj6f#ҷPl;;gH>sU{LZO Ou3\6>n9NKǵ("؀mJz#{8#eXxz1w:X͊72$"L.L0~b91f[y&%OP\{R91ݬI|XzQk]1}ơ̷V w=R,m".Y{++$i +K;{T#2\³b1w IK_ w_ιڰ'Գ)GVXj]@ H[|_j,I3A.14WEwL:cPDi4v;ԓv늦rO@kc?JtVZi7zL$QRj>G\NpH=ǚ|ϟ QDSG]$g:TL" ߓSf;&:SWhϽl3)QLV4l:}֦e2UA9sOk!##ZZ~%Ge@Bj:^`w o3jS 4qLŦH&iMБ*vnk*v -Zc<ӑV5>TA3G$O%V,yMu%{Xe -ϻ' !ۆ2X3-Bd3Ȳ9?(iŶekٗv*q)GlqϷ5#˹JWt8\~?RJNOvƯ<[^[a5 l܁":ݑNR[إI3ldoN޶<= #[I(W'N@<+嶏qq^f%9KGE!0 ?zA8k5xNYtqrdV;d}zvV&,VhToSk#$o|`Hղejh%!{wv%sXr,F}88]^}eD[his[%PMAȝ ނ=*m68[1/*Nw%S_1 S.F#|7ۃޝmd7"K5ف"m}-\FIiHϿGMuh$r)n,UI:yo^[0z ?:L0M^`(>RGSOLv/%ĭ#y3j%綎ZT\TIm28o>X6ηm4hrpsޒ~dm; k޻FF̖X-d $ػ2g`M#e[8T Ƒ[\HMH ئ^Œ"-ɑ#RvA? rY`iYf`So#( eޞO"yR)tsHO "xS͵نyAN0nD!E❬IJ{We@2޸=@dVVeuŞ26*@+H# {BKRn rW8MZ_{s"rvmg9b19VޓpM%u"K$Knёu4>&y,"T{R<3C-aF} $Pۼ"C;Zr[C,, ʔZ?_ni򢉶~&mh](x)7jYTCRyݙRTRSMy~bJ#C)g368Kw^HgI&682M,;+J#{Y +}Ar]BBH-*}饖"dTqXGGOzkJK8MQs҉AܛtFmvq'4 ,qS֛ yC5uD~BQq/.vy`1Rj)Ĉ#n7qAp͙:BPM Hyy>n{7UMlμoOrJ?egJ).TZŕօmm,G{J֎$q#:8r.YTPgr@1V!L98#Z@@e=;Qf r[e1=?)۔WW%ש1PpIz5dJn]ihY]sׯҹ< YZC;Fp$i)?vqeQs4M9hTmb%%@$땷(T S{G;[WЂzz[[lv7쐤oVmo$~Od}O ]N''lvv~|7t]Qr'֖R=H ݇uIʲK$kЮ1X;@LČNFuvS]v!ez}iHΝ@#? q9̒TV8f+&@?5=y{mRdN΢PI46ŋYb[k}$pQԳLoe*=:W`M%\ q*i?wzU6ԭĕk+gũY0Sn^ $sL[aX \݅Ck;c V׶>?X;gO٥YKHi$ Vi>P 3"/?>VTm4%ͪVvVґ稭@ ZW# D|+ԵXtwQQz3eRG f:⠺D<2g'5Yd FGBjY J"jL䌕lc"5ɇ<_9W#8hM*A:֢%0Tryۻ6xJJ了0D)3ޛ _eV 5x=727qqcP NxXuW6msgIsDNUN0kIhzL*Tn; b4S+30"{7fdhKQEt+BHJlVɐ#8Z>eiYQ?+u=xF˚ {&d)8 a} $}d)(|6֦إBi]t9jrCa#@]3VIWj0j],k\)_zpZњaQIS6W*lPU$L~ջ-Fs nbN෽/DA. )drſC_ڮW@&}3qӓ\;Y <j!G # Y}-sj[#US\ѯlW3>sMsQ>0?xW%SjM,{qY8j]fwr47aQ =ƬP;#K¹'o4;* XjH݃Ȼ~qOОWesbIJnol^M(\:V vig5$HN߻ey)&+:-P. IqiX /svdEJqǥ,7Ĥ$)9Եh.^; 1Q oĆ&Ge@2TjJeY0G=>ʍ9qlw:FB(>rc8^]Yb-uSiW<#/85mȵ{Ф&-"tZZ"v:}+QI{Ju`?늉Kvtg pmo*i\qq=@TmWvRs m*' 2;ZspWq8}ȘůWk_qǢ@lPXڴM$>zVܘ &g-@'Yb b@Wo%HHM4EG~VY.QK 9su9ʞ i/H\[#([/"(w6H _/P@x⢷ۢ0g5BҼ;՜: Mu}6;ȶhOOƼɝV@9s2qo=xfDm@Gjݔ;pEv>rqֺ{}R8ʎWLu7|DZ'kM4xJIvV!&F?*6y$wVg$/Nڟ6M%@֜4NpMC0 Q5 Y $ޅJN堅A@3NHv&yR3Fpޮ5|oSs !}nOꭙB# R%y9U좡fD<:ME:j0cĺ|I1“:kXry'Tk"HIzzUx‘rkkli(ŒZxCwbŖ:qJMDna ʾp+_BbTK'b$ u &T9O:c3湹^.:hm*u]=*Y6% RzX*NtqSlAV1{*{U.*!lg9~TyG'-!20+~xT!ݎ98w'v?švv)i0ʸp1UJ 2s+~5IHΡcb@wӮqsgH`ޚ3mWI -r;( jsE>T9670յ&0[cq`4JOWG{vҲiG~n~|ʣ1*$4dȯR *׬cH$|^A$jlCF݄*(=zUieE[CERۘЇ;-25pn'5m2" 㜎R||~zlwLKe&gZ2ۖ\^-Aw2V*I {~ B0gN?*siQ1< l 8Riw5qb ,ۑ;84YhHpppj'(F KlY@\mΔ9uרrE#y 'r|151lEH8BByDe-*QZu;c%OYG$$ցV5sj#%)c9/eTEu]iEaiD,x,KOXݔH9𤶺e-5hѰ.R:WKmM*( b6z=JEwOz«6^<x#0 Dž'-StqR@&7zdcֻ~$[XAbqcV7OAV-򁃞==rA v0ΪUE^r@?_ƪ*-8'מrGi+1ږa!sVmEVSjYQh{3RbTBT ;N]̊sZc汵l6"LgZط@TqY6@ݴ88^r9.HV qJȝ[絎&mk*q!9 F>ϗRMM X`ukoQ([F0ĺ?ƥ]dp1⪫BT`{>jڴ"q:#r3nlap sU# `5`Uݐ`dj%tX2fksV8`߰nnOS/VYZG [AcTrĊ]4K}̙XsztL9 A-9_̜.G8ճLGpH}ʩPFN1Kib"r\SԪO!q` 9sPmT׀&$2烊@qInʀ GzT,2*KTL$vv0rйr}i(ܜi˒ēB8RƙPgk DB08޶ajh>敥EX?0:df\[Z}븂r!NsLC1P:gOa[[*8$m=* Fy:Tj7ǕlŗE 09FdkL8'=T\⧓Jl憆UFE$uPZ2QʌY448?.*1 FJ@+}H"cSr>'sT CE9H}qŽ?5>_ NϥSU"g6r[ s]q]#qURN ;D$4ĐQ_@ͤ\CAVO smhn4 #֟T1|gHusFNBPrzc42sm ʣ]m6kIШ9˨d楸\fm?WLm݃ߌSwA:ua1cR=52ww#:#r`8O\OLXPcZk YrObW0ȹV2k`"sr:zqUnؙ0_T+Is;2ϙ OP͐13]I' Ǡ)h0 08?[wФzw# |T>[gҭ\[1R1Uſ@sֱܨnx[6۫'< `R6=:U AFy%M7m(?֕ǘdiޥ;ڢRqW[Y0'V8aU`ʀW';sչ1ۧM%{w:rZPBnW}Bjjs:KGmRyR )g'*JC+ry+)c?Jٷ!!$zw+.7uxj䎘!y]8>C_:[%=1S)>[ N#ZeRO9jhsҳm] &bt)mR4ѲF0(';ې}ɭt1ƉdXxUn&VA0A?Rg{h]R" ңA~aLua)R9{S@r*d< wۙR?Ωԫؙ~UaךLm8C zwG>hW#CѾ=XFJlcHJI4=Vq;܂1ܕ;w{UfI< UB'ȭ~+3*}1UGW, PFN95'mG'2%Y#ڡIcNgmw1֪MP8ϭKՉhk#˜qڴhsZB#F} I95wVGAl:!V%ϨJw,G;jF[uEAg"ߩPܒ4V`xR*.@$#ӽ!XYX+ d#FwέE/xRoc2c|Z8pJ2IbQ-ۖ+ߌ4Gaa=TvD%c|'+?LYbiمi2zօ0drHUY;ccz$k+F=xKo"\t<{,6e*p>a#!qk L2;`Zq}^iX0#?zm  G5z7jĢ&Ps e⤘.zsTZ+؃O_ҥ;;%t5B7m.iIU y֓ :$' v-"j; 6cYPdֹW+IhBPIdIcb*ON{QO08E.ń_4p ; Lӆ@ ([RYST1܀|oWp8PM2OLVqJH2E(VD*6=;sKtH<yc N zUnd3ߓTk-v oSeK Bj]mRuqL3p}X*MҚp-)*:ǵ[ \Q`ԅ^RD꣉1WewG{ *]nZn PGi$^ Mkn]0@SҖvOSsv4FW9>A]\iр-zԱPôrFzSdpIWB].<ZQ@XË}v=zWkdR?ϽJ.Bu~p0!RHήx8V5)Z8*:+a >OH Ȧ #9ʣ89 =GzFy9H]ܔ$r: {w(RwOyQ J唹xLB[د*'ab dl*FG׽O;ZpZvNJ6e ?ZxN2Ĝ9'=)mkYD\':ʳN?!Flickr-Upload-1.32/t/async.t0000644000175000017500000000204311026270441013726 0ustar cpbcpbuse Test::More qw(no_plan); BEGIN { use_ok('Flickr::Upload') }; my $api_key = '8dcf37880da64acfe8e30bb1091376b7'; my $not_so_secret = '2f3695d0562cdac7'; # grab auth token. If none, fail nicely. my $pw = '******'; open( F, '<', 't/password' ) || (print STDERR "No password file\n" && exit 0); $pw = ; chomp $pw; close F; my $ua = Flickr::Upload->new({'key'=>$api_key, 'secret'=>$not_so_secret}); ok(defined $ua); $ua->agent( "$0/1.0" ); my $rc = $ua->upload( 'async' => 1, 'photo' => 't/testimage.jpg', 'auth_token' => $pw, 'tags' => "test kernel perl cat dog", 'description' => "Flickr Upload test for $0", 'is_public' => 0, 'is_friend' => 0, 'is_family' => 0, ); ok( defined $rc ); print STDERR "Got ticket id '$rc'\n"; do { sleep 1; my @checked = $ua->check_upload( $rc ); for( @checked ) { if( $_->{id} eq $rc and $_->{complete} ) { ok( $_->{complete} == 1 ); # completed ok( defined $_->{photoid} and $_->{photoid} ); print STDERR "Got photoid '$_->{photoid}'\n"; $rc = undef; } } } while( defined $rc ); exit 0; Flickr-Upload-1.32/t/request.t0000644000175000017500000000267211026041454014311 0ustar cpbcpbuse Test::More qw(no_plan); BEGIN { use_ok('Flickr::Upload') }; my $api_key = '8dcf37880da64acfe8e30bb1091376b7'; my $not_so_secret = '2f3695d0562cdac7'; # grab auth token. If none, fail nicely. my $pw = '******'; open( F, '<', 't/password' ) || (print STDERR "No password file\n" && exit 0); $pw = ; chomp $pw; close F; my $ua = Flickr::Upload->new({'key'=>$api_key, 'secret'=>$not_so_secret}); ok(defined $ua); # slurp in the photo my $photo = 't/testimage.jpg'; my $photobuf = ''; open( F, '<', $photo ) or die $!; while() { $photobuf .= $_; } close F; ok( $photobuf ne '' ); my $req = $ua->make_upload_request( 'description' => "Flickr Upload test for $0", 'auth_token' => $pw, 'tags' => "test kernel perl cat dog", 'is_public' => 0, 'is_friend' => 0, 'is_family' => 0, ); # HACK: this will be recalculated when the content is regenerated, but # if we leave it as it is we get a nasty warning because the added part # will invalidate the existing value. $req->remove_header( 'Content-Length' ); # we didn't provide a photo when we made the message because we're # trying to generate the message from a data buffer, not a file. # Now that we have a request, add in the actual image. my $p = new HTTP::Message( [ 'Content-Disposition' => qq(form-data; name="photo"; filename="$photo"), 'Content-Type' => 'image/jpeg', ], $photobuf, ); $req->add_part( $p ); my $photoid = $ua->upload_request( $req ); ok( defined $photoid ); exit 0; Flickr-Upload-1.32/t/upload.t0000644000175000017500000000123611026041454014100 0ustar cpbcpbuse Test::More qw(no_plan); BEGIN { use_ok('Flickr::Upload') }; my $api_key = '8dcf37880da64acfe8e30bb1091376b7'; my $not_so_secret = '2f3695d0562cdac7'; # grab auth token. If none, fail nicely. my $pw = '******'; open( F, '<', 't/password' ) || (print STDERR "No password file\n" && exit 0); $pw = ; chomp $pw; close F; my $ua = Flickr::Upload->new({'key'=>$api_key, 'secret'=>$not_so_secret}); ok(defined $ua); my $rc = $ua->upload( 'photo' => 't/testimage.jpg', 'auth_token' => $pw, 'tags' => "test kernel perl cat dog", 'description' => "Flickr Upload test for $0", 'is_public' => 0, 'is_friend' => 0, 'is_family' => 0, ); ok( defined $rc ); exit 0; Flickr-Upload-1.32/t/progress_request.t0000644000175000017500000000435611026051207016233 0ustar cpbcpbuse strict; use Test::More; use List::Util qw(shuffle); use Flickr::Upload; # The $HTTP::Request::Common::DYNAMIC_FILE_UPLOAD facility allows us # to supply a callback that'll get the contents of each chunk in the # multipart POST request to flickr. By inspecting the whole multipart # request we can determine how far along the upload is and display an # accurate progres meter via Term::ProgressBar. # Ideally there would be a callaback that would be called with the # contents of each logical form field in the multipart chunk, since # that isn't the case we'll have to build an ad-hoc parser that gets # called with each chunk in the multipart request and returns the # number of bytes of the file that has been uploaded. my $NUM_TESTS = 9001; my @IMAGE_SIZE_RANGE = ( 500, 1000 ); plan tests => $NUM_TESTS; my @PARTS = ( q[--%ID% Content-Disposition: form-data; name="photo"; filename="%IMAGE_NAME%" Content-Type: %IMAGE_TYPE% %IMAGE_DATA%], q[--%ID% Content-Disposition: form-data; name="async" 1], q[--%ID% Content-Disposition: form-data; name="api_sig" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX], q[--%ID% Content-Disposition: form-data; name="auth_token" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX], q[--%ID% Content-Disposition: form-data; name="title" Test], q[--%ID% Content-Disposition: form-data; name="api_key" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX], q[--%ID% Content-Disposition: form-data; name="description" Test picture], ); for my $num_test (1 .. $NUM_TESTS) { my $image_name = "Testimage.png"; my $image_type = "image/png"; my $image_size = 512 + int rand 1024; my $image_data = ('x' x $image_size); my $chunk_size = 128 + int rand 256; my $id = 'qBXwGcnVvxg14vk2iUnT8v2YB3FilB3b3rmAmVeq'; my @parts = shuffle @PARTS; my @mod_parts = map { s/\n/\r\n/g; s/%ID%/$id/g; s/%IMAGE_NAME%/$image_name/g; s/%IMAGE_TYPE%/$image_type/g; s/%IMAGE_DATA%/$image_data/g; $_; } @parts; my $whole_message = join("\r\n", @mod_parts) . "\r\n" . "--$id\r\n"; my @split_message = unpack "(Z$chunk_size)*", $whole_message; my ($state, $size); for my $part (@split_message) { $size += Flickr::Upload::file_length_in_encoded_chunk(\$part, \$state, $image_size); } cmp_ok $size, '==', $image_size, "Correct size (img_size: $image_size) (chunk_size: $chunk_size)"; } Flickr-Upload-1.32/META.yml0000644000175000017500000000121011064317102013423 0ustar cpbcpb--- #YAML:1.0 name: Flickr-Upload version: 1.32 abstract: Module for uploading images to flickr.com license: ~ author: - Christophe Beauregard generated_by: ExtUtils::MakeMaker version 6.42 distribution_type: module requires: Flickr::API: 0.07 Getopt::Long: 1 HTTP::Request::Common: 1 LWP::UserAgent: 1 Pod::Usage: 1 XML::Parser::Lite::Tree: 0.03 meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.3.html version: 1.3 Flickr-Upload-1.32/flickr_upload0000755000175000017500000003010311064315617014732 0ustar cpbcpb#!/usr/bin/perl use strict; use warnings; use Flickr::Upload; use Getopt::Long; use Pod::Usage; # get your own key and secret from http://www.flickr.com/services/api/key.gne my $api_key = '8dcf37880da64acfe8e30bb1091376b7'; my $not_so_secret = '2f3695d0562cdac7'; my %args; my @tags = (); my $help = 0; my $man = 0; my $auth = 0; my $progress = 0; my $check = 0; if( open CONFIG, "< $ENV{HOME}/.flickrrc" ) { while( ) { chomp; s/#.*$//; # strip comments next unless m/^\s*([a-z_]+)=(.+)\s*$/io; if( $1 eq "key" ) { $api_key = $2; } elsif( $1 eq "secret" ) { $not_so_secret = $2; } else { $args{$1} = $2; } } close CONFIG; } GetOptions( 'help|?' => \$help, 'man' => \$man, 'tag=s' => \@tags, 'uri=s' => sub { $args{$_[0]} = $_[1] }, 'auth_token=s' => sub { $args{$_[0]} = $_[1] }, 'public=i' => sub { $args{is_public} = $_[1] }, 'friend=i' => sub { $args{is_friend} = $_[1] }, 'family=i' => sub { $args{is_family} = $_[1] }, 'title=s' => sub { $args{$_[0]} = $_[1] }, 'description=s' => sub { $args{$_[0]} = $_[1] }, 'key=s' => \$api_key, 'secret=s' => \$not_so_secret, 'auth' => \$auth, 'progress' => \$progress, 'check' => \$check, 'option=s' => \%args, ) or pod2usage(2); pod2usage(1) if $help; pod2usage(-exitstatus => 0, -verbose => 2) if $man; my $version = $Flickr::Upload::VERSION; my $ua = Flickr::Upload->new( {'key' => $api_key, 'secret' => $not_so_secret} ); $ua->agent( "flickr_upload/$version" ); $ua->env_proxy(); if( $progress ) { eval { require Term::ProgressBar; Term::ProgressBar->import(2.00); }; if( $@ ) { # Remove duplicate newline from error, and no need for two 'at line' messages chomp(my $err = $@); $err =~ s/\) at .*? line.*/)/; die "Term::ProgressBar needs to be installed for `--progress' to work: (error from perl: $err)"; } } if( $auth ) { # The user wants to authenticate. There's really no nice way to handle this. # So we have to spit out a URL, then hang around or something until # the user hits enter, then exchange the frob for a token, then tell the user what # the token is and hope they care enough to stick it into .flickrrc so they # only have to go through this crap once. # 1. get a frob my $frob = getFrob( $ua ); # 2. get a url for the frob my $url = $ua->request_auth_url('write', $frob); # 3. tell the user what to do with it print "1. Enter the following URL into your browser\n\n", "$url\n\n", "2. Follow the instructions on the web page\n", "3. Hit when finished.\n\n"; # 4. wait for enter. ; # 5. Get the token from the frob my $auth_token = getToken( $ua, $frob ); die "Failed to get authentication token!" unless defined $auth_token; # 6. Tell the user what they won. print "Your authentication token for this application is\n\t\t", $auth_token, "\n"; exit 0; } pod2usage(1) unless exists $args{'auth_token'}; if( $check ) { exit( checkToken( $ua, $args{api_key}, $args{auth_token} ) ); } pod2usage(1) unless @ARGV; $args{'tags'} = join( " ", @tags ) if @tags; # pipeline things by uploading first, waiting for photo ids second. $args{'async'} = 1; my %tickets; $| = 1; while( my $photo = shift @ARGV ) { my $rc; if ($progress) { $HTTP::Request::Common::DYNAMIC_FILE_UPLOAD = 1; my $photo_size = (stat($photo))[7]; my $req = $ua->make_upload_request( 'photo' => $photo, %args ); my $gen = $req->content(); die unless ref($gen) eq "CODE"; my $progress = Term::ProgressBar->new({ name => $photo, count => $photo_size, ETA => 'linear', }); $progress->minor(0); my $state; my $size; $req->content( sub { my $chunk = &$gen(); $size += Flickr::Upload::file_length_in_encoded_chunk(\$chunk, \$state, $photo_size); $progress->update($size); return $chunk; } ); $rc = $ua->upload_request( $req ); } else { print 'Uploading ', $photo, '...'; $rc = $ua->upload( 'photo' => $photo, %args ); } # let the caller know how many images weren't uploaded exit (1+@ARGV) unless defined $rc; # check those later $tickets{$rc} = $photo; print "\n"; } # check print "Waiting for upload results (ctrl-C if you don't care)...\n"; do { sleep 1; my @checked = $ua->check_upload( keys %tickets ); for( @checked ) { if( $_->{complete} == 0 ) { # not done yet, don't do anythig } elsif( $_->{complete} == 1 ) { # uploaded, got photoid print "$tickets{$_->{id}} is at " . "http://www.flickr.com/tools/uploader_edit.gne?ids=$_->{photoid}\n"; delete $tickets{$_->{id}}; } else { print "$tickets{$_->{id}} failed to get photoid\n"; delete $tickets{$_->{id}}; } } } while( %tickets ); exit 0; sub response_tag { my $t = shift; my $name = shift; my $tag = shift; return undef unless defined $t and exists $t->{'children'}; for my $n ( @{$t->{'children'}} ) { next unless $n->{'name'} eq $name; next unless exists $n->{'children'}; for my $m (@{$n->{'children'}} ) { next unless exists $m->{'name'} and $m->{'name'} eq $tag and exists $m->{'children'}; return $m->{'children'}->[0]->{'content'}; } } return undef; } sub getFrob { my $ua = shift; my $res = $ua->execute_method("flickr.auth.getFrob"); return undef unless defined $res and $res->{success}; # FIXME: error checking, please. At least look for the node named 'frob'. return $res->{tree}->{children}->[1]->{children}->[0]->{content}; } sub getToken { my $ua = shift; my $frob = shift; my $res = $ua->execute_method("flickr.auth.getToken", { 'frob' => $frob } ); return undef unless defined $res and $res->{success}; # FIXME: error checking, please. return $res->{tree}->{children}->[1]->{children}->[1]->{children}->[0]->{content}; } sub checkToken { my $ua = shift; my $key = shift; my $token = shift; my $res = $ua->execute_method("flickr.auth.checkToken", { 'auth_token' => $token, 'api_key' => $key, } ); # FIXME: this could be parsed, but I'm not going to get too fancy print $res->decoded_content(); return 0; } __END__ =head1 NAME flickr_upload - Upload photos to C =head1 SYNOPSIS flickr_upload [--auth] --auth_token [--title ] [--description description] [--public <0|1>] [--friend <0|1>] [--family <0|1>] [--tag <tag>] [--option key=value] [--progress] <photos...> =head1 DESCRIPTION Batch image uploader for the L<Flickr.com> service. L<flickr_upload> may also be useful for generating authentication tokens against other API keys/secrets (i.e. for embedding in scripts). =head1 OPTIONS =over 4 =item --auth The C<--auth> flag will cause L<flickr_upload> to generate an authentication token against it's API key and secret (or, if you want, your own specific key and secret). This process requires the caller to have a browser handy so they can cut and paste a url. The resulting token should be kept somewhere like C<~/.flickrrc> since it's necessary for actually uploading images. =item --auth_token <auth_token> Authentication token. You B<must> get an authentication token using C<--auth> before you can upload images. See the L<EXAMPLES> section. =item --title <title> Title to use on all the images. Optional. =item --description <description> Description to use on all the images. Optional. =item --public <0|1> Override the default C<is_public> access control. Optional. =item --friend <0|1> Override the default C<is_friend> access control. Optional. =item --family <0|1> Override the default C<is_family> access control. Optional. =item --tag <tag> Images are tagged with C<tag>. Multiple C<--tag> options can be given, or you can just put them all into a single space-separated list. If you want to define a tag with spaces, the quotes have to be part of the tag itself. The following works in L<bash>: flickr_upload --tag='"tag one"' --tag='"tag two"' image.jpg =item --option key=value Flickr periodically adds new features to the uploading API, and these are almost always implemented as new key/value pairs. Rather than waiting for a new L<Flickr::Upload> release, you can specify any of the upload API's optional arguments using C<--option>. flick_upload --option content_type=1 --tag='cats' two_cats.jpg You may also use C<--option> rather than L<flickr_upload>'s command-line options: flickr_upload --option is_public=1 --option title='cats' two_cats.jpg While Flickr may add new options at any time (see L<http://flickr.com/services/api/upload.api.html> for the most up-to-date list), currently known options include: =over 4 =item --option safety_level=<1|2|3> Override the default C<safety_level> notation. Set to 1 for Safe, 2 for Moderate, or 3 for Restricted. Refer to L<http://www.flickr.com/help/filters/>. =item --option content_type=<1|2|3> Override the default C<content_type> notation. Set to 1 for Photo, 2 for Screenshot, or 3 for Art/Illustration. Refer to L<http://www.flickr.com/help/filters/>. =item --option hidden=<1|2> Override the default C<hidden> notation. Set to 1 to keep the photo in global search results, 2 to hide from public earches. =item --check Checks the authentication token via the flickr.auth.checkToken API call. This can be used to verify API keys and credentials without trying to upload an image. The output is the raw results of the API call. =item --progress Display a progress bar for each upload with L<Term::ProgressBar>. That optional module will have to be installed on the system. =back 4 Note that options unknown to Flickr will result in undefined behaviour. =item --key <api_key> =item --secret <secret> Your own API key and secret. This is useful if you want to use L<flickr_upload> in auth mode as a token generator. You need both C<key> and C<secret>. Both C<key> and C<secret> can be placed in C<~/.flickrrc>, allowing to mix L<flickr_upload> with your own scripts using the same API key and authentication token. Getting your own API key and secret is encouraged if you're tying L<flickr_upload> to some automated process. Note that if you do get an authentication token against your own API key and secret, you'll need to specify the key and secret along with the token when uploading images. The default L<flickr_upload> API key and token won't work in that case. =item <photos...> List of photos to upload. Uploading stops as soon as a failure is detected during the upload. The script exit code will indicate the number of images on the command line that were not uploaded. For each uploaded image, a Flickr URL will be generated. L<flickr_upload> uses asynchronous uploading so while the image is usually transferred fairly quickly, it might take a while before it's actually available to users. L<flickr_upload> will wait around for that to complete, but be aware that delays of upwards of thirty minutes have (rarely) been know to occur. =head1 EXAMPLES First, you need to get an authentication token. This is a requirement driven by how Flickr manages third-party applications: cpb@earth:~$ flickr_upload --auth 1. Enter the following URL into your browser http://flickr.com/services/auth?api_sig=<...>&frob=<...>&perms=write&api_key=<...> 2. Follow the instructions on the web page 3. Hit <Enter> when finished. Your authentication token for this application is <token> Unless you like typing long numbers on the command-line, you should keep the C<<token>> somewhere handy, like a configuration file: echo auth_token=<token> >~/.flickrrc Uploading a bunch of images is then as easy as: flickr_upload --tag 'dog' 'kernel in a window.jpg' 'sad in sunbeam.jpg' =head1 CONFIGURATION To avoid having to remember authentication tokens and such (or have them show up in the process table listings), default values will be read from C<$HOME/.flickrrc> if it exists. Any field defined there can, of course, be overridden on the command line. For example: # my config at $HOME/.flickrrc auth_token=334455 is_public=0 is_friend=1 is_family=1 Note, however, that these defaults override the defaults you've assigned in your Flickr profile. You may want to do all that stuff in one place. =head1 BUGS Error handling could be better. =head1 AUTHOR Christophe Beauregard, L<cpb@cpan.org>. =head1 SEE ALSO L<flickr.com> L<Flickr::Upload> L<http://flickr.com/services/api/> L<http://www.flickr.com/help/filters/> =cut �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Flickr-Upload-1.32/MANIFEST�������������������������������������������������������������������������0000644�0001750�0001750�00000000321�11026051261�013304� 0����������������������������������������������������������������������������������������������������ustar �cpb�����������������������������cpb��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ChangeLog flickr_upload Makefile.PL MANIFEST META.yml Module meta-data (added by MakeMaker) README t/async.t t/failupload.t t/progress.t t/progress_request.t t/request.t t/testimage.jpg t/upload.t Upload.pm ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Flickr-Upload-1.32/ChangeLog������������������������������������������������������������������������0000644�0001750�0001750�00000075316�11064317102�013746� 0����������������������������������������������������������������������������������������������������ustar �cpb�����������������������������cpb��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������commit 25738657dcf4623445f69433ae63973d1e24d4cb (refs/heads/master) Author: Christophe Beauregard <cpb@cpan.org> AuthorDate: Wed Sep 17 20:17:52 2008 -0400 Commit: Christophe Beauregard <cpb@cpan.org> CommitDate: Wed Sep 17 20:17:52 2008 -0400 Bump version to 1.32 commit df1eccffdc2b67943a7d5cf9660ad8a677bc729b Author: Christophe Beauregard <cpb@cpan.org> AuthorDate: Wed Sep 17 20:06:52 2008 -0400 Commit: Christophe Beauregard <cpb@cpan.org> CommitDate: Wed Sep 17 20:06:52 2008 -0400 Call env_proxy() on the user agent. Fixes http://rt.cpan.org/Ticket/Display.html?id=37725 commit fbee13a2b51531a6d61013b7416265af88f2e1e5 Author: Christophe Beauregard <cpb@cpan.org> AuthorDate: Wed Sep 17 20:05:45 2008 -0400 Commit: Christophe Beauregard <cpb@cpan.org> CommitDate: Wed Sep 17 20:05:45 2008 -0400 Minor clarification of the custom key/secret options. http://rt.cpan.org/Ticket/Display.html?id=39370 commit 85117d8c2e553fcef65702dbb7361185508088f4 Author: Christophe Beauregard <cpb@cpan.org> AuthorDate: Wed Sep 17 20:03:35 2008 -0400 Commit: Christophe Beauregard <cpb@cpan.org> CommitDate: Wed Sep 17 20:03:35 2008 -0400 Add a --check option to invoke the flickr.auth.checkToken API call and just generally validate the authentication information. commit 3afc55b07bc0087afe9919563ad0392c8a221c54 (refs/remotes/origin/master, refs/remotes/origin/HEAD, refs/remotes/gitorious/master) Author: Christophe Beauregard <cpb@cpan.org> AuthorDate: Sat Jun 21 18:59:13 2008 -0400 Commit: Christophe Beauregard <cpb@cpan.org> CommitDate: Sat Jun 21 18:59:13 2008 -0400 put more detail in the ChangeLog. Specifically, we'd like to see dates. commit 75d78079f595f2516a5efa4bfdada2961f0c08a3 (refs/tags/1.31) Author: Christophe Beauregard <cpb@cpan.org> AuthorDate: Wed Jun 18 16:39:42 2008 -0400 Commit: Christophe Beauregard <cpb@cpan.org> CommitDate: Wed Jun 18 16:39:42 2008 -0400 indent with tabs commit 76ca5d3bd960eedf21d9fea32fd83815f98816ec Author: Christophe Beauregard <cpb@cpan.org> AuthorDate: Wed Jun 18 16:37:24 2008 -0400 Commit: Christophe Beauregard <cpb@cpan.org> CommitDate: Wed Jun 18 16:37:24 2008 -0400 ticket and photo identifiers aren't necessarily numeric. Fix the async test to use 'eq' and document. commit 8ded78b619ef4696ffa27d6766d797720a0fca4e Author: Christophe Beauregard <cpb@cpan.org> AuthorDate: Tue Jun 17 20:38:36 2008 -0400 Commit: Christophe Beauregard <cpb@cpan.org> CommitDate: Tue Jun 17 20:38:36 2008 -0400 we use the generated META.yml, too commit bac5b6c6487b78622cea79c3b217c5f4f22fbb0d Author: Christophe Beauregard <cpb@cpan.org> AuthorDate: Tue Jun 17 20:19:03 2008 -0400 Commit: Christophe Beauregard <cpb@cpan.org> CommitDate: Tue Jun 17 20:19:03 2008 -0400 oops... we auto generate the ChangeLog, don't commit commit fbe6b5a03c5c6a5df4ca7266f04b89997ff60e92 Author: Christophe Beauregard <cpb@cpan.org> AuthorDate: Tue Jun 17 20:16:37 2008 -0400 Commit: Christophe Beauregard <cpb@cpan.org> CommitDate: Tue Jun 17 20:16:37 2008 -0400 bump version to 1.31 commit 9a7c22dc11e16ff483b01dc491f11e146683e2d4 Merge: b53a716... c87f9be... Author: Christophe Beauregard <cpb@cpan.org> AuthorDate: Tue Jun 17 20:15:14 2008 -0400 Commit: Christophe Beauregard <cpb@cpan.org> CommitDate: Tue Jun 17 20:15:14 2008 -0400 Merge branch 'master' of git://git.nix.is/avar/pm/Flickr-Upload Conflicts: MANIFEST README Upload.pm flickr_upload t/progress.t commit b53a716f24dd0caa43f4837ac9965511e55d364d Author: Christophe Beauregard <cpb@cpan.org> AuthorDate: Tue Jun 17 20:04:16 2008 -0400 Commit: Christophe Beauregard <cpb@cpan.org> CommitDate: Tue Jun 17 20:04:16 2008 -0400 Now that we seem to have a more permanent home... commit 4a27eff4d9f6186e004d0e14ff18c6a30d2bbfb8 Author: Christophe Beauregard <cpb@cpan.org> AuthorDate: Tue Jun 17 19:29:30 2008 -0400 Commit: Christophe Beauregard <cpb@cpan.org> CommitDate: Tue Jun 17 19:29:30 2008 -0400 force an update commit 990747797c6ddcb4e8761005d5afd322111f0642 Author: Christophe Beauregard <cpb@cpan.org> AuthorDate: Tue Jun 17 19:12:24 2008 -0400 Commit: Christophe Beauregard <cpb@cpan.org> CommitDate: Tue Jun 17 19:12:24 2008 -0400 add note about GIT repo commit c87f9be69faff0a337e3f32e46758d97d407308b (refs/remotes/avar/master) Author: Ævar Arnfjörð Bjarmason <avar@cpan.org> AuthorDate: Tue Jun 17 03:49:01 2008 +0000 Commit: Ævar Arnfjörð Bjarmason <avar@cpan.org> CommitDate: Tue Jun 17 03:49:01 2008 +0000 $progress->minor(0). This updates the progress bar a lot less frequently and it looks better since there isn't a '*'character jumping all over the terminal. commit 662868b31eb0b448f0951fa9da3e59ff0f1bf181 Author: Ævar Arnfjörð Bjarmason <avar@f-prot.com> AuthorDate: Mon Jun 16 12:51:53 2008 +0000 Commit: Ævar Arnfjörð Bjarmason <avar@f-prot.com> CommitDate: Mon Jun 16 12:51:53 2008 +0000 POD documentation for file_length_in_encoded_chunk Make the Content-Type regex more inclusive to handle other kinds of uploads. commit 74937457cfeeb6eed25c902191ab086262034f35 Author: Ævar Arnfjörð Bjarmason <avar@f-prot.com> AuthorDate: Mon Jun 16 12:35:06 2008 +0000 Commit: Ævar Arnfjörð Bjarmason <avar@f-prot.com> CommitDate: Mon Jun 16 12:35:06 2008 +0000 Update POD for --progress some more commit eecb5a5bd8c334229ade2cbd69fe73d8284544fe Author: Ævar Arnfjörð Bjarmason <avar@f-prot.com> AuthorDate: Mon Jun 16 12:33:39 2008 +0000 Commit: Ævar Arnfjörð Bjarmason <avar@f-prot.com> CommitDate: Mon Jun 16 12:33:39 2008 +0000 The manifest was way out of date, update it commit 83a78608a398e6310908ec5f19948ff2cd07b7a7 Author: Ævar Arnfjörð Bjarmason <avar@f-prot.com> AuthorDate: Mon Jun 16 12:31:49 2008 +0000 Commit: Ævar Arnfjörð Bjarmason <avar@f-prot.com> CommitDate: Mon Jun 16 12:31:49 2008 +0000 File upload progress stuff now works, with tests commit a60024fe5262528330a518a659982114ed215b9c Author: Ævar Arnfjörð Bjarmason <avar@f-prot.com> AuthorDate: Mon Jun 16 11:42:25 2008 +0000 Commit: Ævar Arnfjörð Bjarmason <avar@f-prot.com> CommitDate: Mon Jun 16 11:42:25 2008 +0000 Fixes these errors: t/progress............ok 1/0Can't decode multipart content at /usr/share/perl5/HTTP/Message.pm line 193. ...propagated at t/progress.t line 33. and added comment & newline preventing this: ok 3 ...........................................................ok 4 which would fail the 4th test commit d7d60c2a9228225c3a455b47457b87c400cf0f21 Author: Ævar Arnfjörð Bjarmason <avar@f-prot.com> AuthorDate: Mon Jun 16 11:25:39 2008 +0000 Commit: Ævar Arnfjörð Bjarmason <avar@f-prot.com> CommitDate: Mon Jun 16 11:25:39 2008 +0000 a working test! commit 184f10e79cb4b5463508487a59d39c306a4bd7e4 Author: Ævar Arnfjörð Bjarmason <avar@cpan.org> AuthorDate: Mon Jun 16 05:39:56 2008 +0000 Commit: Ævar Arnfjörð Bjarmason <avar@cpan.org> CommitDate: Mon Jun 16 05:39:56 2008 +0000 Deleted function prototypes, ->upload is a method and there's no need to call scalar on the arguments given to upload_request commit 9c509b24e425143c24f30a143b7daf72f16eb4a2 Author: Ævar Arnfjörð Bjarmason <avar@cpan.org> AuthorDate: Mon Jun 16 05:38:15 2008 +0000 Commit: Ævar Arnfjörð Bjarmason <avar@cpan.org> CommitDate: Mon Jun 16 05:38:15 2008 +0000 Deleted unused template code which was loading Exporter and AutoLoader without exporting anything or using autoload commit b194bd979e46c8a77f6f2cb4e667ee79ad456fed Author: Ævar Arnfjörð Bjarmason <avar@cpan.org> AuthorDate: Mon Jun 16 05:26:26 2008 +0000 Commit: Ævar Arnfjörð Bjarmason <avar@cpan.org> CommitDate: Mon Jun 16 05:26:26 2008 +0000 a version of my flickr upload patch on RT, currently broken while in development commit c5f6f1fd66c01bb76bbd897acf92be76e9a8d783 Author: Ævar Arnfjörð Bjarmason <avar@cpan.org> AuthorDate: Mon Jun 16 05:25:04 2008 +0000 Commit: Ævar Arnfjörð Bjarmason <avar@cpan.org> CommitDate: Mon Jun 16 05:25:04 2008 +0000 The beginnings of a test for the file upload parser, does nothing yet commit c5ef9a68944ed82b379f516c63c950545a8f9def Author: Ævar Arnfjörð Bjarmason <avar@cpan.org> AuthorDate: Mon Jun 16 03:40:18 2008 +0000 Commit: Ævar Arnfjörð Bjarmason <avar@cpan.org> CommitDate: Mon Jun 16 03:40:18 2008 +0000 Fix grammar in POD: "rarely be know to occur" "rarely been know to occur" commit 8edebaaaa7b4e420483ac287011f3eb7fcb8c75a Author: Ævar Arnfjörð Bjarmason <avar@cpan.org> AuthorDate: Mon Jun 16 03:21:09 2008 +0000 Commit: Ævar Arnfjörð Bjarmason <avar@cpan.org> CommitDate: Mon Jun 16 03:21:09 2008 +0000 1.30 from CPAN commit d469b79ff97d91e4adc9dfbbd79fa321e0b7fe32 Author: cpb <cpb@localhost.localdomain> AuthorDate: Sat Mar 8 08:45:19 2008 -0500 Commit: cpb <cpb@localhost.localdomain> CommitDate: Sat Mar 8 08:45:19 2008 -0500 *: patch from Pascal Terjan to fix http://rt.cpan.org/Ticket/Display.html?id=33750 *: also fix t/progress.t *: bump version to 1.30 commit 5b067d72b0199376eb0fbffc8bc8ad1fda3f0ec4 Author: cpb <cpb@earth.localdomain> AuthorDate: Wed Jun 20 20:11:00 2007 -0400 Commit: cpb <cpb@earth.localdomain> CommitDate: Wed Jun 20 20:11:00 2007 -0400 Minor documentation cleanups commit bacea3a958e964428ac04b631897c33a30209a17 Author: cpb <cpb@earth.localdomain> AuthorDate: Wed Jun 20 20:10:22 2007 -0400 Commit: cpb <cpb@earth.localdomain> CommitDate: Wed Jun 20 20:10:22 2007 -0400 oops, forgot to commit that. Same as last, just some build fixes. commit 93bf309e95366d1c30cee2629435abf4e96b0a6d Author: cpb <cpb@earth.localdomain> AuthorDate: Wed Jun 20 20:03:57 2007 -0400 Commit: cpb <cpb@earth.localdomain> CommitDate: Wed Jun 20 20:03:57 2007 -0400 Clean up the build dependencies so the generated files actually do get generated when we make a dist. commit b8f6a97156f5482508d56988348ba6e1c9cb530e Author: cpb <cpb@earth.localdomain> AuthorDate: Wed Jun 20 19:55:26 2007 -0400 Commit: cpb <cpb@earth.localdomain> CommitDate: Wed Jun 20 19:55:26 2007 -0400 Drop some files we're no longer using/maintaining. We can always get 'em back. commit 71d98dbd8e7284ffaff508160be566d4bdc88b9b Author: cpb <cpb@earth.localdomain> AuthorDate: Wed Jun 20 19:28:27 2007 -0400 Commit: cpb <cpb@earth.localdomain> CommitDate: Wed Jun 20 19:28:27 2007 -0400 Oops, not using CVS anymore. Use $Flickr::Upload::VERSION. commit f1232d66f2acffe69ed763c24e2461e0730c7a83 Author: cpb <cpb@earth.localdomain> AuthorDate: Tue Jun 19 19:34:40 2007 -0400 Commit: cpb <cpb@earth.localdomain> CommitDate: Tue Jun 19 19:34:40 2007 -0400 Add some documentation suggested by Mark Atwood. commit 2a64df91c32d3d6032219810daefc45032b73d5d Author: cpb <cpb@earth.localdomain> AuthorDate: Mon Jun 18 19:28:29 2007 -0400 Commit: cpb <cpb@earth.localdomain> CommitDate: Mon Jun 18 19:28:29 2007 -0400 <sigh> CPAN doesn't like it when you remove the $VERSION from a module. So we'll just revert the whole "move into Makefile.PL" thing. commit 643895a413bfa095aa704b1217aefb2d922a8362 Author: cpb <cpb@earth.localdomain> AuthorDate: Mon Jun 18 19:08:08 2007 -0400 Commit: cpb <cpb@earth.localdomain> CommitDate: Mon Jun 18 19:08:08 2007 -0400 (#23) recent change to ExtUtils::MakeMaker appears to not cope with a missing META.yml... Even though it generates one anyways. commit 0f269b7a0cbdcc0a8f4e7888bd8fdce1a60aa8d5 Author: cpb <cpb@earth.localdomain> AuthorDate: Mon Jun 11 20:41:06 2007 -0400 Commit: cpb <cpb@earth.localdomain> CommitDate: Mon Jun 11 20:41:06 2007 -0400 bump the version commit 1206c237c13cfd371a180624c574e265558ac1ef Author: cpb <cpb@earth.localdomain> AuthorDate: Mon Jun 11 20:40:42 2007 -0400 Commit: cpb <cpb@earth.localdomain> CommitDate: Mon Jun 11 20:40:42 2007 -0400 Added a --option parameter so users can just add arbitrary options (like the new filtering stuff) without waiting for a new Flickr::Upload release. commit c9f103dd0c229756bcd5e6ceaa222a2ac42a5845 Author: cpb <cpb@earth.localdomain> AuthorDate: Sun Jun 3 15:32:38 2007 -0400 Commit: cpb <cpb@earth.localdomain> CommitDate: Sun Jun 3 15:32:38 2007 -0400 Bump revision to 1.26 Update Makefile.PL and Upload.pm to reflect switch to GIT, which means cvs2cl won't generate a ChangeLog and we need to bump the version number manually. commit b3bbd024fb5bcb162dcb782d55171dc276068f59 Author: cpb <cpb@earth.localdomain> AuthorDate: Sat Jun 2 21:06:24 2007 -0400 Commit: cpb <cpb@earth.localdomain> CommitDate: Sat Jun 2 21:06:24 2007 -0400 Refine the authentication documentation just a touch. commit 3f36b37a5d9399260e107a88e4a6f21d015c61fd Author: cpb <cpb> AuthorDate: Wed Mar 21 01:34:04 2007 +0000 Commit: cpb <cpb> CommitDate: Wed Mar 21 01:34:04 2007 +0000 Documentation: add an "EXAMPLE" section to clarify how to get started. Fix some spelling and formatting issues. commit 2d49bf3b2d93f33b481a8c32016acca214f99d58 Author: cpb <cpb> AuthorDate: Mon Mar 19 00:45:15 2007 +0000 Commit: cpb <cpb> CommitDate: Mon Mar 19 00:45:15 2007 +0000 oops, that's Pod::Usage commit 162150419f60a4a06d6214d3809f399575e3b03f Author: cpb <cpb> AuthorDate: Mon Mar 19 00:31:42 2007 +0000 Commit: cpb <cpb> CommitDate: Mon Mar 19 00:31:42 2007 +0000 http://rt.cpan.org/Ticket/Display.html?id=25521 Add Pod::Usage and Getopt::Long to dependencies commit 46a3092db4faf2d88461f0064012e50580bdef89 Author: cpb <cpb> AuthorDate: Tue Dec 19 17:59:47 2006 +0000 Commit: cpb <cpb> CommitDate: Tue Dec 19 17:59:47 2006 +0000 http://rt.cpan.org/Ticket/Display.html?id=23990 =Flickr::Upload::new()= takes a hashref (ala =Flickr::API=). commit 5690adae0ecedc2c4dadc155548d7ade0144197a Author: cpb <cpb> AuthorDate: Fri Sep 22 00:27:23 2006 +0000 Commit: cpb <cpb> CommitDate: Fri Sep 22 00:27:23 2006 +0000 upload URI has changed commit 0ffd3f92ca3c26c13c35b7d5efbd79888fa4f8c4 Author: cpb <cpb> AuthorDate: Sat Jan 21 17:36:23 2006 +0000 Commit: cpb <cpb> CommitDate: Sat Jan 21 17:36:23 2006 +0000 add some notes on generating tags with embedded spaces to the --tag documentation. commit 86beb003aa9ddbae9e8be0080de55088588406c9 Author: cpb <cpb> AuthorDate: Thu Jan 5 23:52:05 2006 +0000 Commit: cpb <cpb> CommitDate: Thu Jan 5 23:52:05 2006 +0000 _is_friend_ should be _is_family_ https://rt.cpan.org/NoAuth/Bug.html?id=16930 commit 95a2af893331e107d5301ba39de1b17863982358 Author: cpb <cpb> AuthorDate: Tue Aug 30 22:43:53 2005 +0000 Commit: cpb <cpb> CommitDate: Tue Aug 30 22:43:53 2005 +0000 change the test image name. Needs to go in MANIFEST... commit 88e3a12d57a3cb64b2fd340d488e0e2eccada27f Author: cpb <cpb> AuthorDate: Sun Aug 28 01:05:06 2005 +0000 Commit: cpb <cpb> CommitDate: Sun Aug 28 01:05:06 2005 +0000 (#11) key and secret can be specified in =~/.flickrrc=. This allows a user to get one API key, authenticate against it, and use =flickr_upload= and a bunch of personal scripts with just =~/.flickrc= for storing the authentication info. commit 4f2ac62f555e4b616518a579894604b1dfb86b88 Author: cpb <cpb> AuthorDate: Sun Aug 28 00:59:17 2005 +0000 Commit: cpb <cpb> CommitDate: Sun Aug 28 00:59:17 2005 +0000 (#11) change of ownership commit d2f691308e289ea9935f2baa5e7cb1f9237f465d Author: cpb <cpb> AuthorDate: Sun Aug 28 00:35:55 2005 +0000 Commit: cpb <cpb> CommitDate: Sun Aug 28 00:35:55 2005 +0000 (#11) some documentation cleanups commit 3783350260f87de11bfe646ac517a5c190e8a15f Author: cpb <cpb> AuthorDate: Wed Aug 24 02:36:56 2005 +0000 Commit: cpb <cpb> CommitDate: Wed Aug 24 02:36:56 2005 +0000 (#8) really remove refs to =thickr_upload=. commit 1dd1d3f64d1a227ea35643df047e4614fcc45722 Author: cpb <cpb> AuthorDate: Wed Aug 24 02:32:58 2005 +0000 Commit: cpb <cpb> CommitDate: Wed Aug 24 02:32:58 2005 +0000 (#8) switched to Debian, =cvs2cl= is called something else commit 666781f4801095233ae417dc28cc863d4af28515 Author: cpb <cpb> AuthorDate: Wed Aug 24 02:31:20 2005 +0000 Commit: cpb <cpb> CommitDate: Wed Aug 24 02:31:20 2005 +0000 (#8) remove some debug code, handle undef photo situation. commit 646e13fad7280da15f39eccbcc78aaf591ac138b Author: cpb <cpb> AuthorDate: Wed Aug 24 02:29:52 2005 +0000 Commit: cpb <cpb> CommitDate: Wed Aug 24 02:29:52 2005 +0000 (#8) first stab at getting =Flickr::Upload= working with the new authentication. *: had to completely gut the interface and inherit from =Flickr::API=. *: straight and async uploading via =flickr_upload= _works_ *: this means =Flickr::Upload::upload()= and =Flickr::Upload::check_upload()= methods are good. *: tests /Flickr-Upload/t/request.t and /Flickr-Upload/t/progress.t are _not_ passing, although the progress test is still uploading the image. commit f7d92b7749f9027fd5af5fa30eb610bc5f02cd10 Author: cpb <cpb> AuthorDate: Wed Aug 24 01:57:42 2005 +0000 Commit: cpb <cpb> CommitDate: Wed Aug 24 01:57:42 2005 +0000 (#8) remove =thickr_upload= for now. commit 9a5190fdf3c1f7b7df9b3378630de7a9705abcc9 Author: cpb <cpb> AuthorDate: Wed Feb 16 03:16:26 2005 +0000 Commit: cpb <cpb> CommitDate: Wed Feb 16 03:16:26 2005 +0000 non-blocking uploading... *: spawn the uploading in a separate process (via fork) and process the results in a pipe using Tk fileevent. *: error handling needs a bit of work *: need to manage the process id of the uploader so that we clean up when we quit. *: really need an upload manager window so we can monitor the entire queue *: also need to check for ticket completions commit db6bf06811a76752f181bd81762649d3acce8aed Author: cpb <cpb> AuthorDate: Sun Feb 6 15:09:48 2005 +0000 Commit: cpb <cpb> CommitDate: Sun Feb 6 15:09:48 2005 +0000 tweak ChangeLog options commit 850e525713067e3587e1ebcbdf4f3f687fcc2ef3 Author: cpb <cpb> AuthorDate: Sat Feb 5 23:40:42 2005 +0000 Commit: cpb <cpb> CommitDate: Sat Feb 5 23:40:42 2005 +0000 add blurb about thickr_upload commit 5bf426d1e01d7ffe456675a19f7eb650154b010b Author: cpb <cpb> AuthorDate: Sat Feb 5 23:38:48 2005 +0000 Commit: cpb <cpb> CommitDate: Sat Feb 5 23:38:48 2005 +0000 rename thkr_upload to thickr_upload. Long story, won't bother explaining. commit f3bd683ac3b7a7b9921484c3f996c61118b67799 Author: cpb <cpb> AuthorDate: Sat Feb 5 23:35:17 2005 +0000 Commit: cpb <cpb> CommitDate: Sat Feb 5 23:35:17 2005 +0000 remove the logo stuff. We'll just show some blankness. commit acb665aed11d78ca9f0dec12a0d191b01ddcd4fc Author: cpb <cpb> AuthorDate: Sat Feb 5 23:16:23 2005 +0000 Commit: cpb <cpb> CommitDate: Sat Feb 5 23:16:23 2005 +0000 *: remove some debug junk *: replace Tk::FileSelect with Tk::getOpenFile() so we can do multiple selection. This really streamlines things. commit 0b53ea9bcc443ec2f84b63222f8aaad92dd7e658 Author: cpb <cpb> AuthorDate: Sat Feb 5 21:11:37 2005 +0000 Commit: cpb <cpb> CommitDate: Sat Feb 5 21:11:37 2005 +0000 fix comment about best way to use LWP from Tk commit 0dd69bb6b25089778b3ebfeea26ac34f5fce3552 Author: cpb <cpb> AuthorDate: Mon Jan 17 04:03:23 2005 +0000 Commit: cpb <cpb> CommitDate: Mon Jan 17 04:03:23 2005 +0000 more churning on the uploading. Nicer cleanup. commit ae0424e12ab02b8677408ff4fa1b7a4d30d7c867 Author: cpb <cpb> AuthorDate: Sun Jan 16 04:50:04 2005 +0000 Commit: cpb <cpb> CommitDate: Sun Jan 16 04:50:04 2005 +0000 *: clean up preview a bit. Now properly scales images to fit, manages memory better, etc. *: make preview area a drag and drop site for photos. DnD code is a little crufty but works *: update menus a touch. Help is actually in the right place *: switch to messageBox for Help|About *: documentation *: use Tk::HTML::IO to, hopefully, do better IO for the upload. Haven't tested this and need to refine the upload process some anyways. We really want something like an "upload manager" view of what's happening. *: new photos are added at the front of the list. Just better feedback. commit 6a7db68d2466ceeacc189b318485fb5998237a8d Author: cpb <cpb> AuthorDate: Sat Jan 15 05:08:53 2005 +0000 Commit: cpb <cpb> CommitDate: Sat Jan 15 05:08:53 2005 +0000 added initial cut at thkr_upload, a Tk-based GUI upload client commit 2a1949baa9d2982225811852cf3de0400e74dff2 Author: cpb <cpb> AuthorDate: Thu Jan 13 14:33:50 2005 +0000 Commit: cpb <cpb> CommitDate: Thu Jan 13 14:33:50 2005 +0000 update documentation a touch. It's a new year, you know. commit 6680641bb776d5faad11401ce30e41c832f78e95 Author: cpb <cpb> AuthorDate: Thu Jan 13 14:31:06 2005 +0000 Commit: cpb <cpb> CommitDate: Thu Jan 13 14:31:06 2005 +0000 use the async option to pipeline the upload process so we wait for photoid assignments after _all_ the uploads are completed. This should reduce the overall time are multi-image batch uploads quite a bit. commit a75905f12f7e9aa148c8e9cc4a5f91596bdd9e8f Author: cpb <cpb> AuthorDate: Thu Jan 13 14:16:29 2005 +0000 Commit: cpb <cpb> CommitDate: Thu Jan 13 14:16:29 2005 +0000 added async.t to MANIFEST commit 609c961fb7ad0f07ddbe179d4f5994cdf79f3221 Author: cpb <cpb> AuthorDate: Thu Jan 13 04:28:22 2005 +0000 Commit: cpb <cpb> CommitDate: Thu Jan 13 04:28:22 2005 +0000 chunk could be undefined. commit efcaac3ad6f917abbf4c533d2c4efbea228f9d31 Author: cpb <cpb> AuthorDate: Thu Jan 13 04:23:53 2005 +0000 Commit: cpb <cpb> CommitDate: Thu Jan 13 04:23:53 2005 +0000 *: modified make_upload_request() to allow async and properly handle returned ticket ids. *: added check_upload() function to check status up async tickets *: added t/async.t to test/demo async functionality commit 1f764265df810e7f9e2aec524de31874d777f857 Author: cpb <cpb> AuthorDate: Sat Jan 8 17:13:06 2005 +0000 Commit: cpb <cpb> CommitDate: Sat Jan 8 17:13:06 2005 +0000 trim down commentary on async uploading. It _might_ be useful to such an API, given recent problems with delays in the uploading process (in something like sync conduits, for example). commit 158ab2c204d108a28a865b0fd980acd637b3d8c5 Author: cpb <cpb> AuthorDate: Sat Jan 8 17:06:56 2005 +0000 Commit: cpb <cpb> CommitDate: Sat Jan 8 17:06:56 2005 +0000 L<> in NAME section gets interpreted as links to a man page, leading to a synopsis like "Flickr::Upload - Upload images to the flickr.com manpage". commit 8552e7ca98801bc5a5c5a819ce60d73c5f360a0d Author: cpb <cpb> AuthorDate: Tue Jan 4 00:36:04 2005 +0000 Commit: cpb <cpb> CommitDate: Tue Jan 4 00:36:04 2005 +0000 Another Michael, another bug report... _Michael Parker says:_ I noticed this in the flickr_upload script distributed with the Flickr::Upload package (at least until 1.10): 'public=i' => sub { $args{is_public} = $_[1] }, 'friend=i' => sub { $args{is_public} = $_[1] }, 'family=i' => sub { $args{is_public} = $_[1] }, It looks like a cut and paste error, using is_public for all 3 rather than is_friend and is_family. commit 596972a78acf76d8fe195aa18a6d4789101777e2 Author: cpb <cpb> AuthorDate: Tue Dec 14 18:03:04 2004 +0000 Commit: cpb <cpb> CommitDate: Tue Dec 14 18:03:04 2004 +0000 Grrr... forgot the perl version dependency in Makefile.PL... commit 41a7415c856630609dd87a110e43d1cce2b1e794 Author: cpb <cpb> AuthorDate: Tue Dec 14 00:38:27 2004 +0000 Commit: cpb <cpb> CommitDate: Tue Dec 14 00:38:27 2004 +0000 Michael Stillwell pointed out that the restriction to perl >= 5.8.3 was silly. 5.6.1+ would be fine, and probably even earlier. commit ae5109e8a1024d61d68ef3c5f177fd4a9cb4f9c3 Author: cpb <cpb> AuthorDate: Wed Dec 8 01:03:07 2004 +0000 Commit: cpb <cpb> CommitDate: Wed Dec 8 01:03:07 2004 +0000 oops, not -no-wrap commit c166485609e204c8911fcc42c6f361965d4f875e Author: cpb <cpb> AuthorDate: Wed Dec 8 01:01:13 2004 +0000 Commit: cpb <cpb> CommitDate: Wed Dec 8 01:01:13 2004 +0000 Fixup the cvs2cl.pl options to something a bit nicer. commit 3d03bc68a1e9cba9ce16ae37b9c6519fdbad60e3 Author: cpb <cpb> AuthorDate: Tue Dec 7 03:45:27 2004 +0000 Commit: cpb <cpb> CommitDate: Tue Dec 7 03:45:27 2004 +0000 add some Makefile.PL magic to ensure that ChangeLog is removed by make clean and generated by make dist. Of course, we're building dist with access to my CVS repository... commit 6fc85f4529c8def8092fda7910dc12a2578095ba Author: cpb <cpb> AuthorDate: Sun Dec 5 17:27:20 2004 +0000 Commit: cpb <cpb> CommitDate: Sun Dec 5 17:27:20 2004 +0000 Add an example/test which uses the DYNAMIC_FILE_UPLOAD functionality to implement some progress feedback. commit a8e3b05d22092eff30fa37cec26e20dab3c8770a Author: cpb <cpb> AuthorDate: Sun Dec 5 17:17:47 2004 +0000 Commit: cpb <cpb> CommitDate: Sun Dec 5 17:17:47 2004 +0000 minor formatting tweak, but I also need to bump the version to do a new release. commit bb04c294d4541d4461f913ccad3bf7b14c62abbf Author: cpb <cpb> AuthorDate: Sun Dec 5 17:17:11 2004 +0000 Commit: cpb <cpb> CommitDate: Sun Dec 5 17:17:11 2004 +0000 *: HACK for the LWP content length warning. Apparently, add_parts() doesn't cause the existing content length to be invalidated and LWP complains when it recalculates it anyways. *: tweak description... sometimes the :: doesn't make it through. commit d75ec119706c7c348fdd95e568a4114f0302919a Author: cpb <cpb> AuthorDate: Sun Dec 5 16:58:51 2004 +0000 Commit: cpb <cpb> CommitDate: Sun Dec 5 16:58:51 2004 +0000 *: oops, chomp the password *: make test image private. We don't really need to spam the tag index with kernel and perl over and over again... commit 1ed55a736387c900016aeb1ea8b953bfa1d9c7bb Author: cpb <cpb> AuthorDate: Sun Dec 5 16:44:35 2004 +0000 Commit: cpb <cpb> CommitDate: Sun Dec 5 16:44:35 2004 +0000 make tests fail gracefully if no password file provided. This way I can do sane testing but cpansmoke won't complain. commit 676aa2bef0f0003530ada8c8cd081ee55db0b884 Author: cpb <cpb> AuthorDate: Sun Dec 5 05:12:24 2004 +0000 Commit: cpb <cpb> CommitDate: Sun Dec 5 05:12:24 2004 +0000 *: added make_upload_request and upload_request functions to allow for more direct manipulation of the HTTP::Request structure. *: added t/request.t to demonstrate how said functionality can be used to upload images directly from memory rather than having to create temporary files. It appears, unfortunately, that LWP doesn't like the way I do things, but it only complains rather than bailing. The end result works. commit d3e1a58be20b6ac07c22ea85fa4d72a12caa1c9f Author: cpb <cpb> AuthorDate: Sun Dec 5 03:36:49 2004 +0000 Commit: cpb <cpb> CommitDate: Sun Dec 5 03:36:49 2004 +0000 strip out the test comments commit cd3a5f617173fe9cfaad2235d63e0210b74b34c1 Author: cpb <cpb> AuthorDate: Sun Sep 5 19:18:57 2004 +0000 Commit: cpb <cpb> CommitDate: Sun Sep 5 19:18:57 2004 +0000 *: don't export upload() by default. *: upload() returns the resulting photo identifier on success (still undef on failure). We're also nicer about the resulting failure message. commit e307647393228d65881fe30826f7a4980af31ddc Author: cpb <cpb> AuthorDate: Sun Sep 5 19:17:31 2004 +0000 Commit: cpb <cpb> CommitDate: Sun Sep 5 19:17:31 2004 +0000 *: output uploaded photoid for each image *: read config from ~/.flickrrc. commit 57e30391fe1e8ba8025750f3e6fde99354819db5 Author: cpb <cpb> AuthorDate: Sun Sep 5 19:16:42 2004 +0000 Commit: cpb <cpb> CommitDate: Sun Sep 5 19:16:42 2004 +0000 in theory, zero might be a valid photoid. Probably not, but... commit fe3d263a2716ba4152e2b9ee2217ccd5d9e85277 Author: cpb <cpb> AuthorDate: Sun Sep 5 19:16:10 2004 +0000 Commit: cpb <cpb> CommitDate: Sun Sep 5 19:16:10 2004 +0000 change how we 'use' the module. commit be1f3f6e2d5b7bd58953d1e11d23b9b5e75413b2 Author: cpb <cpb> AuthorDate: Sat Sep 4 22:33:04 2004 +0000 Commit: cpb <cpb> CommitDate: Sat Sep 4 22:33:04 2004 +0000 assorted documentation niceties. Dunno how I forgot about the README... commit b9f2925c5102e910f43b13ebc770daf73dd10dc7 Author: cpb <cpb> AuthorDate: Sat Sep 4 20:29:50 2004 +0000 Commit: cpb <cpb> CommitDate: Sat Sep 4 20:29:50 2004 +0000 remove META.yml from CVS commit 0d680d109c4cc6d2d16f8f88eeb2da3a7c83e7df Author: cpb <cpb> AuthorDate: Sat Sep 4 20:29:03 2004 +0000 Commit: cpb <cpb> CommitDate: Sat Sep 4 20:29:03 2004 +0000 - assorted pod additions - cleanup failure handling commit 0ed62455cdbcb86e32c4760aabc4f0c84b1c9e30 Author: cpb <cpb> AuthorDate: Sat Sep 4 20:10:18 2004 +0000 Commit: cpb <cpb> CommitDate: Sat Sep 4 20:10:18 2004 +0000 - added flickr_upload script - clean up Makefile.PL (i.e. add prereqs, etc). commit d4eb3346c47d5674eaa36664ef06b0b5fb172c0d Author: cpb <cpb> AuthorDate: Sat Sep 4 20:09:38 2004 +0000 Commit: cpb <cpb> CommitDate: Sat Sep 4 20:09:38 2004 +0000 tags now just a string rather than list ref commit f417c013751e21c99a57d34ec5c8094b6e80c35e Author: cpb <cpb> AuthorDate: Sat Sep 4 20:09:19 2004 +0000 Commit: cpb <cpb> CommitDate: Sat Sep 4 20:09:19 2004 +0000 assorted fixes: - pod fixes - tags now just a string rather than a list ref commit 3796bdc8594aec2955b8ee83d1876b7a5d6e6a92 Author: cpb <cpb> AuthorDate: Sat Sep 4 18:03:36 2004 +0000 Commit: cpb <cpb> CommitDate: Sat Sep 4 18:03:36 2004 +0000 upload() works commit 89f08c0342226a94dcd68635dd65f186e46e1b2a Author: cpb <cpb> AuthorDate: Sat Sep 4 15:49:59 2004 +0000 Commit: cpb <cpb> CommitDate: Sat Sep 4 15:49:59 2004 +0000 change tests commit 6920d3522b4cc331d87944cc418ce83c5b6b9376 Author: cpb <cpb> AuthorDate: Sat Sep 4 15:49:44 2004 +0000 Commit: cpb <cpb> CommitDate: Sat Sep 4 15:49:44 2004 +0000 adjusted testing, added test image commit 13bdf123607bcdba5c7e701585375b1709d98769 Author: cpb <cpb> AuthorDate: Sat Sep 4 15:49:07 2004 +0000 Commit: cpb <cpb> CommitDate: Sat Sep 4 15:49:07 2004 +0000 laid out pod, initial stab at how API will work commit 643cc3e3ee961aa3a2646aa5291ca25d374c920f Author: cpb <cpb> AuthorDate: Thu Sep 2 21:43:07 2004 +0000 Commit: cpb <cpb> CommitDate: Thu Sep 2 21:43:07 2004 +0000 added META.yml commit a845211957e95b6dfb3481fb882475c2cd6cb030 Author: cpb <cpb> AuthorDate: Thu Sep 2 21:34:44 2004 +0000 Commit: cpb <cpb> CommitDate: Thu Sep 2 21:34:44 2004 +0000 Initial revision ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Flickr-Upload-1.32/Upload.pm������������������������������������������������������������������������0000644�0001750�0001750�00000026417�11064317054�013762� 0����������������������������������������������������������������������������������������������������ustar �cpb�����������������������������cpb��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������package Flickr::Upload; use strict; use warnings; use LWP::UserAgent; use HTTP::Request::Common; use Flickr::API; use XML::Parser::Lite::Tree; our $VERSION = '1.32'; our @ISA = qw(Flickr::API); sub response_tag { my $t = shift; my $node = shift; my $tag = shift; return undef unless defined $t and exists $t->{'children'}; for my $n ( @{$t->{'children'}} ) { next unless defined $n and exists $n->{'name'} and exists $n->{'children'}; next unless $n->{'name'} eq $node; for my $m (@{$n->{'children'}} ) { next unless exists $m->{'name'} and $m->{'name'} eq $tag and exists $m->{'children'}; return $m->{'children'}->[0]->{'content'}; } } return undef; } =head1 NAME Flickr::Upload - Upload images to C<flickr.com> =head1 SYNOPSIS use Flickr::Upload; my $ua = Flickr::Upload->new( { 'key' => '90909354', 'secret' => '37465825' }); $ua->upload( 'photo' => '/tmp/image.jpg', 'auth_token' => $auth_token, 'tags' => 'me myself eye', 'is_public' => 1, 'is_friend' => 1, 'is_family' => 1 ) or die "Failed to upload /tmp/image.jpg"; =head1 DESCRIPTION Upload an image to L<flickr.com>. =head1 METHODS =head2 new my $ua = Flickr::Upload->new( { 'key' => '90909354', 'secret' => '37465825' }); Instatiates a L<Flickr::Upload> instance. The C<key> argument is your API key and the C<secret> is the API secret associated with it. To get an API key and secret, go to L<http://www.flickr.com/services/api/key.gne>. The resulting L<Flickr::Upload> instance is a subclass of L<Flickr::API> and can be used for any other Flickr API calls. As such, L<Flickr::Upload> is also a subclass of L<LWP::UserAgent>. =head2 upload my $photoid = $ua->upload( 'photo' => '/tmp/image.jpg', 'auth_token' => $auth_token, 'tags' => 'me myself eye', 'is_public' => 1, 'is_friend' => 1, 'is_family' => 1 'async' => 0, ); Taking a L<Flickr::Upload> instance C<$ua> as an argument, this is basically a direct interface to the Flickr Photo Upload API. Required parameters are C<photo> and C<auth_token>. Note that the C<auth_token> must have been issued against the API key and secret used to instantiate the uploader. Returns the resulting identifier of the uploaded photo on success, C<undef> on failure. According to the API documentation, after an upload the user should be directed to the page L<http://www.flickr.com/tools/uploader_edit.gne?ids=$photoid>. If the C<async> option is non-zero, the photo will be uploaded asynchronously and a successful upload returns a ticket identifier. See L<http://flickr.com/services/api/upload.async.html>. The caller can then periodically poll for a photo id using the C<check_upload> method. Note that photo and ticket identifiers aren't necessarily numeric. =cut sub upload { my $self = shift; die '$self is not a Flickr::Upload' unless $self->isa('Flickr::Upload'); my %args = @_; # these are the only things _required_ by the uploader. die "Can't read photo '$args{'photo'}'" unless $args{'photo'} and -f $args{'photo'}; die "Missing 'auth_token'" unless defined $args{'auth_token'}; # create a request object and execute it my $req = $self->make_upload_request( %args ); return undef unless defined $req; return $self->upload_request( $req ); } =head2 check_upload my %status2txt = (0 => 'not complete', 1 => 'completed', 2 => 'failed'); my @rc = $ua->check_upload( @ticketids ); for( @rc ) { print "Ticket $_->{id} has $status2txt{$_->{complete}}\n"; print "\tPhoto id is $_->{photoid}\n" if exists $_->{photoid}; } This function will check the status of one or more asynchronous uploads. A list of ticket identifiers are provided (C<@ticketids>) and each is checked. This is basically just a wrapper around the Flickr API C<flickr.photos.upload.checkTickets> method. On success, a list of hash references is returned. Each hash contains a C<id> (the ticket id), C<complete> and, if completed, C<photoid> members. C<invalid> may also be returned. Status codes (for C<complete>) are as documented at L<http://flickr.com/services/api/upload.async.html> and, actually, the returned fields are identical to those listed in the C<ticket> tag of the response. The returned list isn't guaranteed to be in any particular order. This function polls a web server, so avoid calling it too frequently. =cut sub check_upload { my $self = shift; die '$self is not a Flickr::API' unless $self->isa('Flickr::API'); return () unless @_; # no tickets my $res = $self->execute_method( 'flickr.photos.upload.checkTickets', { 'tickets' => ((@_ == 1) ? $_[0] : join(',', @_)) } ); return () unless defined $res and $res->{success}; # FIXME: better error feedback my @rc; return undef unless defined $res->{tree} and exists $res->{tree}->{'children'}; for my $n ( @{$res->{tree}->{'children'}} ) { next unless defined $n and exists $n->{'name'} and $n->{'children'}; next unless $n->{'name'} eq "uploader"; for my $m (@{$n->{'children'}} ) { next unless exists $m->{'name'} and $m->{'name'} eq 'ticket' and exists $m->{'attributes'}; # okay, this is maybe a little lazy... push @rc, $m->{'attributes'}; } } return @rc; } =head2 make_upload_request my $req = $uploader->make_upload_request( 'auth_token' => '82374523', 'tags' => 'me myself eye', 'is_public' => 1, 'is_friend' => 1, 'is_family' => 1 ); $req->header( 'X-Greetz' => 'hi cal' ); my $resp = $ua->request( $req ); Creates an L<HTTP::Request> object loaded with all the flick upload parameters. This will also sign the request, which means you won't be able to mess any further with the upload request parameters. Takes all the same parameters as L<upload>, except that the photo argument isn't required. This in intended so that the caller can include it by messing directly with the HTTP content (via C<$DYNAMIC_FILE_UPLOAD> or the L<HTTP::Message> class, among other things). See C<t/> directory from the source distribution for examples. Returns a standard L<HTTP::Response> POST object. The caller can manually do the upload or just call the L<upload_request> function. =cut sub make_upload_request { my $self = shift; die '$self is not a Flickr::Upload' unless $self->isa('Flickr::Upload'); my %args = @_; # _required_ by the uploader. die "Missing 'auth_token' argument" unless $args{'auth_token'}; my $uri = $args{'uri'} || 'http://api.flickr.com/services/upload/'; # passed in separately, so remove from the hash delete $args{uri}; # Flickr::API includes this with normal requests, but we're building a custom # message. $args{'api_key'} = $self->{'api_key'}; # photo is _not_ included in the sig my $photo = $args{photo}; delete $args{photo}; # HACK: sign_args() is an internal Flickr::API method $args{'api_sig'} = $self->sign_args(\%args); # unlikely that the caller would set up the photo as an array, # but... if( defined $photo ) { $photo = [ $photo ] if ref $photo ne "ARRAY"; $args{photo} = $photo; } my $req = POST $uri, 'Content_Type' => 'form-data', 'Content' => \%args; return $req; } =head2 upload_request my $photoid = upload_request( $ua, $request ); Taking (at least) L<LWP::UserAgent> and L<HTTP::Request> objects as arguments, this executes the request and processes the result as a flickr upload. It's assumed that the request looks a lot like something created with L<make_upload_request>. Note that the request must be signed according to the Flickr API authentication rules. Returns the resulting identifier of the uploaded photo (or ticket for asynchronous uploads) on success, C<undef> on failure. According to the API documentation, after an upload the user should be directed to the page L<http://www.flickr.com/tools/uploader_edit.gne?ids=$photoid>. =cut sub upload_request { my $self = shift; die "$self is not a LWP::UserAgent" unless $self->isa('LWP::UserAgent'); my $req = shift; die "expecting a HTTP::Request" unless $req->isa('HTTP::Request'); my $res = $self->request( $req ); my $tree = XML::Parser::Lite::Tree::instance()->parse($res->decoded_content()); return () unless defined $tree; my $photoid = response_tag($tree, 'rsp', 'photoid'); my $ticketid = response_tag($tree, 'rsp', 'ticketid'); unless( defined $photoid or defined $ticketid ) { print STDERR "upload failed:\n", $res->decoded_content(), "\n"; return undef; } return (defined $photoid) ? $photoid : $ticketid; } =head2 file_length_in_encoded_chunk $HTTP::Request::Common::DYNAMIC_FILE_UPLOAD = 1; my $photo = 'image.jpeg'; my $photo_size = (stat($photo))[7]; my $req = $ua->make_upload_request( ... ); my $gen = $req->content(); die unless ref($gen) eq "CODE"; my $state; my $size; $req->content( sub { my $chunk = &$gen(); $size += Flickr::Upload::file_length_in_encoded_chunk(\$chunk, \$state, $photo_size); warn "$size bytes have now been uploaded"; return $chunk; } ); $rc = $ua->upload_request( $req ); This subroutine is tells you how much of a chunk in a series of variable size multipart HTTP chunks contains a single file being uploaded given a reference to the current chunk, a reference to a state variable that lives between calls, and the size of the file being uploaded. It can be used used along with L<HTTP::Request::Common>'s $HTTP::Request::Common::DYNAMIC_FILE_UPLOAD facility to implement upload progress bars or other upload monitors, see L<flickr_upload> for a practical example and F<t/progress_request.t> for tests. =cut sub file_length_in_encoded_chunk { my ($chunk, $s, $img_size) = @_; $$s = {} unless ref $$s eq 'HASH'; # If we've run past the end of the image there's nothing to do but # report no image content in this sector. return 0 if $$s->{done}; unless ($$s->{in}) { # Since we haven't found the image yet append this chunk to # our internal data store, we do this because we have to do a # regex match on m[Content-Type...] which might be split # across multiple chunks $$s->{data} .= defined $$chunk ? $$chunk : ''; if ($$s->{data} =~ m[Content-Type: .*?\r\n\r\n]g) { # We've found the image inside the stream, record this, # delete ->{data} since we don't need it, and see how much # of the image this particular chunk gives us. $$s->{in} = 1; my $size = length substr($$s->{data}, pos($$s->{data}), -1); delete $$s->{data}; $$s->{size} = $size; if ($$s->{size} >= $img_size) { # The image could be so small that we've already run # through it in chunk it starts in, mark as done and # return the total image size $$s->{done} = 1; return $img_size; } else { return $$s->{size}; } } else { # Are we inside the image yet? No! return 0; } } else { my $size = length $$chunk; if (($$s->{size} + $size) >= $img_size) { # This chunk finishes the image $$s->{done} = 1; # Return what we had left return $img_size - $$s->{size}; } else { # This chunk isn't the last one $$s->{size} += $size; return $size; } } } 1; __END__ =head1 SEE ALSO L<http://flickr.com/services/api/> L<Flickr::API> =head1 AUTHOR Christophe Beauregard, L<cpb@cpan.org> =head1 COPYRIGHT AND LICENSE This module is not an official Flickr.com (or Ludicorp, or Yahoo) service. Copyright (C) 2004,2005 by Christophe Beauregard This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.3 or, at your option, any later version of Perl 5 you may have available. �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Flickr-Upload-1.32/Makefile.PL����������������������������������������������������������������������0000644�0001750�0001750�00000001331�11027303600�014125� 0����������������������������������������������������������������������������������������������������ustar �cpb�����������������������������cpb��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������use ExtUtils::MakeMaker; sub MY::postamble { return <<END; ChangeLog: Makefile git-log --pretty=fuller --decorate . >ChangeLog META.yml: Makefile touch META.yml END } WriteMakefile( NAME => 'Flickr::Upload', VERSION_FROM => 'Upload.pm', ABSTRACT => 'Module for uploading images to flickr.com', AUTHOR => 'Christophe Beauregard <cpb@cpan.org>', PREREQ_PM => { 'LWP::UserAgent' => 1, 'HTTP::Request::Common' => 1, 'XML::Parser::Lite::Tree' => 0.03, 'Flickr::API' => 0.07, 'Pod::Usage' => 1, 'Getopt::Long' => 1, }, 'EXE_FILES' => [ 'flickr_upload' ], 'clean' => { FILES => 'ChangeLog META.yml' }, 'depend' => {'create_distdir' => 'ChangeLog META.yml'}, ); �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Flickr-Upload-1.32/README���������������������������������������������������������������������������0000644�0001750�0001750�00000001766�11026051276�013057� 0����������������������������������������������������������������������������������������������������ustar �cpb�����������������������������cpb��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Flickr::Upload ============== Uploader for flickr.com INSTALLATION ============ To install this module type the following: perl Makefile.PL make make test make install DEPENDENCIES ============ - LWP - XML::Parser::Lite::Tree - Flickr::API EXAMPLES ======== flickr_upload is a completely functional batch uploading tool. There's also a good amount of examples included as tests in t/ of the source distribution. And you can always ask me how to do something if it's not obvious. I might even know. Git repository at: git://gitorious.org/flickrupload/mainline.git http://git.gitorious.org/flickrupload/mainline.git COPYRIGHT AND LICENCE ===================== Copyright (C) 2004,2005 by Christophe Beauregard This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.3 or, at your option, any later version of Perl 5 you may have available. This module is not an official Flickr.com (or Ludicorp, or Yahoo) service. ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������