ÿØÿà JFIF    ÿÛ „  ( %"1!%)+...383,7(-.+  -+++--++++---+-+-----+---------------+---+-++7-----ÿÀ  ß â" ÿÄ     ÿÄ H    !1AQaq"‘¡2B±ÁÑð#R“Ò Tbr‚²á3csƒ’ÂñDS¢³$CÿÄ   ÿÄ %  !1AQa"23‘ÿÚ   ? ôÿ ¨pŸªáÿ —åYõõ\?àÒü©ŠÄï¨pŸªáÿ —åYõõ\?àÓü©ŠÄá 0Ÿªáÿ Ÿå[úƒ ú®ði~TÁbqÐ8OÕpÿ ƒOò¤Oè`–RÂáœá™êi€ßÉ< FtŸI“öÌ8úDf´°å}“¾œ6  öFá°y¥jñÇh†ˆ¢ã/ÃÐ:ªcÈ "Y¡ðÑl>ÿ ”ÏËte:qž\oäŠe÷󲍷˜HT4&ÿ ÓÐü6ö®¿øþßèô Ÿ•7Ñi’•j|“ñì>b…þS?*Óôÿ ÓÐü*h¥£ír¶ü UãS炟[AÐaè[ûª•õ&õj?†Éö+EzP—WeÒírJFt ‘BŒ†Ï‡%#tE Øz ¥OÛ«!1›üä±Í™%ºÍãö]°î(–:@<‹ŒÊö×òÆt¦ãº+‡¦%ÌÁ²h´OƒJŒtMÜ>ÀÜÊw3Y´•牋4ǍýʏTì>œú=Íwhyë,¾Ôò×õ¿ßÊa»«þˆѪQ|%6ž™A õ%:øj<>É—ÿ Å_ˆCbõ¥š±ý¯Ýƒï…¶|RëócÍf溪“t.СøTÿ *Ä¿-{†çàczůŽ_–^XþŒ±miB[X±d 1,é”zEù»& î9gœf™9Ð'.;—™i}!ôšåîqêÛ٤ёý£½ÆA–àôe"A$˝Úsäÿ ÷Û #°xŸëí(l »ý3—¥5m! rt`†0~'j2(]S¦¦kv,ÚÇ l¦øJA£Šƒ J3E8ÙiŽ:cÉžúeZ°€¯\®kÖ(79«Ž:¯X”¾³Š&¡* ….‰Ž(ÜíŸ2¥ª‡×Hi²TF¤ò[¨íÈRëÉ䢍mgÑ.Ÿ<öäS0í„ǹÁU´f#Vß;Õ–…P@3ío<ä-±»Ž.L|kªÀê›fÂ6@»eu‚|ÓaÞÆŸ…¨ááå>åŠ?cKü6ùTÍÆ”†sĤÚ;H2RÚ†õ\Ö·Ÿn'¾ ñ#ºI¤Å´%çÁ­‚â7›‹qT3Iï¨ÖÚ5I7Ë!ÅOóŸ¶øÝñØôת¦$Tcö‘[«Ö³šÒ';Aþ ¸èíg A2Z"i¸vdÄ÷.iõ®§)¿]¤À†–‡É&ä{V¶iŽ”.Ó×Õÿ û?h¬Mt–íª[ÿ Ñÿ ÌV(í}=ibÔ¡›¥¢±b Lô¥‡piη_Z<‡z§èŒ)iÖwiÇ 2hÙ3·=’d÷8éŽ1¦¸c¤µ€7›7Ø ð\á)} ¹fËí›pAÃL%âc2 í§æQz¿;T8sæ°qø)QFMð‰XŒÂ±N¢aF¨…8¯!U  Z©RÊ ÖPVÄÀÍin™Ì-GˆªÅËŠ›•zË}º±ŽÍFò¹}Uw×#ä5B¤{î}Ð<ÙD é©¤&‡ïDbàÁôMÁ." ¤‡ú*õ'VŽ|¼´Úgllº¼klz[Æüï÷Aób‡Eÿ dÑ»Xx9ÃÜ£ÁT/`¼¸vI±Ýµ·Ë‚“G³þ*Ÿû´r|*}<¨îºœ @¦mÄ’M¹”.œ«Y–|6ÏU¤jç¥ÕÞqO ˜kDÆÁ¨5ÿ š;ÐЦ¦€GÙk \ –Þ=â¼=SͧµªS°ÚÍpÜãQűÀõ¬?ÃÁ1Ñ•õZà?hóœ€ L¦l{Y*K˜Ù›zc˜–ˆâ ø+¾ ­-Ök¥%ùEÜA'}ˆ><ÊIè“bpÍ/qÞâvoX€w,\úªò6Z[XdÒæ­@Ö—€$òJí#é>'°Ú ôª˜<)4ryÙ£|óAÅn5žêŸyÒäMÝ2{"}‰–¤l÷ûWX\l¾Á¸góÉOÔ /óñB¤f¸çñ[.P˜ZsÊË*ßT܈§QN¢’¡¨§V¼(Üù*eÕ“”5T¨‹Âê¥FŒã½Dü[8'Ò¥a…Ú¶k7a *•›¼'Ò·\8¨ª\@\õ¢¦íq+DÙrmÎ…_ªæ»ŠÓœ¡¯’Ré9MÅ×D™lælffc+ŒÑ,ý™ÿ ¯þǤ=Å’Á7µ÷ÚÛ/“Ü€ñýã¼àí¾ÕÑ+ƒ,uµMâÀÄbm:ÒÎPæ{˜Gz[ƒ¯«® KHà`ߨŠéí¯P8Aq.C‰ à€kòpj´kN¶qô€…Õ,ÜNŠª-­{Zö’æû44‰sŽè‰îVíRœÕm" 6?³D9¡ÇTíÅꋇ`4«¸ÝÁô ï’ýorqКÇZ«x4Žâéþuïf¹µö[P ,Q£éaX±`PÉÍZ ¸äYúg üAx ’6Lê‚xÝÓ*äQ  Ï’¨hÍ =²,6ï#rÃ<¯–£»ƒ‹,–ê•€ aÛsñ'%Æ"®ÛüìBᝠHÚ3ß°©$“XnœÖ’î2ËTeûìxîß ¦å¿çÉ ðK§þ{‘t‚Ϋ¬jéîZ[ ”š7L¥4VÚCE×]m¤Øy”ä4-dz£œ§¸x.*ãÊÊ b÷•h:©‡¦s`BTÁRû¾g⻩‹jø sF¢àJøFl‘È•Xᓁà~*j¯ +(ÚÕ6-£¯÷GŠØy‚<Ç’.F‹Hœw(+)ÜÜâÈzÄäT§FߘãÏ;DmVœ3Àu@mÚüXÝü•3B¨òÌÁÛ<·ÃÜ z,Ì@õÅ·d2]ü8s÷IôÞ¯^Ç9¢u„~ëAŸï4«M? K]­ÅàPl@s_ p:°¬ZR”´›JC[CS.h‹ƒïËœ«Æ]–÷ó‚wR×k7X‰k›‘´ù¦=¡«‰¨¨Â')—71ó’c‡Ðúµ `é.{§p¹ój\Ž{1h{o±Ý=áUÊïGÖŒõ–-BÄm+AZX¶¡ ïHðæ¥JmÙ;…䡟ˆ¦ ° äšiÉg«$üMk5¤L“’çÊvïâï ,=f“"íἊ5ô¬x6{ɏžID0e¸vçmi'︧ºð9$ò¹÷*£’9ÿ ²TÔ…×>JV¥}Œ}$p[bÔ®*[jzS*8 ”·T›Í–ñUîƒwo$áè=LT™ç—~ô·¤ÈÚ$榍q‰„+´kFm)ž‹©i–ËqÞŠ‰à¶ü( ‚•§ •°ò·‡#5ª•µÊ﯅¡X¨šÁ*F#TXJÊ ušJVÍ&=iÄs1‚3•'fý§5Ñ<=[íÞ­ PÚ;ѱÌ_~Ä££8rÞ ²w;’hDT°>ÈG¬8Á²ÚzŽ®ò®qZcqJêäÞ-ö[ܘbň±çb“ж31²n×iƒðÕ;1¶þÉ ªX‰,ßqÏ$>•î íZ¥Z 1{ç൵+ƒÕµ¥°T$§K]á»Ûï*·¤tMI’ÂZbŽÕiÒ˜}bÓ0£ª5›¨ [5Ž^ÝœWøÂÝh° ¢OWun£¤5 a2Z.G2³YL]jåtì”ä ÁÓ‘%"©<Ôúʰsº UZvä‡ÄiÆÒM .÷V·™ø#kèýiíÌ–ª)µT[)BˆõÑ xB¾B€ÖT¨.¥~ð@VĶr#¸ü*åZNDŽH;âi ],©£öØpù(šºãö¼T.uCê•4@ÿ GÕÛ)Cx›®0ø#:ÏðFÒbR\(€€Ä®fã4Þ‰Fä¯HXƒÅ,†öEÑÔÜ]Öv²?tLÃvBY£ú6Êu5ÅAQ³1‘’¬x–HŒÐ‡ ^ ¸KwJôÖŽ5×CÚ¨vÜ«/B0$×k°=ðbÇ(Ï)w±A†Á† 11Í=èQšµ626ŒÜ/`G«µ<}—-Ö7KEHÈÉðóȤmݱû±·ø«Snmá=“䫚mݱŸ¡¶~ó·“äUóJæúòB|E LêŽy´jDÔ$G¢þÐñ7óR8ýÒ…Ç› WVe#·Ÿ p·Fx~•ݤF÷0Èÿ K¯æS<6’¡WШ; ´ÿ ¥Êø\Òuî†åÝ–VNœkÒ7oòX¨Á­Ø÷FÎÑä±g÷ÿ M~Çî=p,X´ ÝÌÚÅ‹’ÃjÖ.ØöÏñ qïQ¤ÓZE†° =6·]܈ s¸>v•Ž^Ý\wq9r‰Î\¸¡kURÒ$­*‹Nq?Þª*!sŠÆ:TU_u±T+øX¡ ®¹¡,ÄâÃBTsÜ$Ø›4m椴zÜK]’’›Pƒ @€#â˜`é¹=I‡fiV•Ôî“nRm+µFPOhÍ0B£ €+¬5c v•:P'ÒyÎ ‰V~‚Ó†ÖuókDoh$å\*ö%Ю=£«…aȼ½÷Û.-½VŒŠ¼'lyî±1¬3ó#ÞE¿ÔS¤gV£m›=§\û"—WU¤ÚǼÿ ÂnÁGŒÃ ‚õN D³õNÚíŒÕ;HôyÄÈ©P¹Ä{:?R‘Ô¨âF÷ø£bÅó® JS|‚R÷ivýáâ€Æé¡è³´IئÑT!§˜•ت‚¬â@q€wnïCWÄ@JU€ê¯m6]Ï:£âx'+ÒðXvÓ¦Úm=–´7œ $ì“B£~p%ÕŸUþ« N@¼üï~w˜ñø5®—'Ôe»¤5ã//€ž~‰Tþ›Å7•#¤× Íö pÄ$ùeåì*«ÓŠEØWEÈsßg ¦ûvžSsLpºÊW–âµEWöˬH; ™!CYõZ ÃÄf æ#1W. \uWâ\,\Çf j’<qTbên›Î[vxx£ë 'ö¨1›˜ÀM¼Pÿ H)ƒêêŒA7s,|F“ 꺸k³9Ìö*ç®;Ö!Ö$Eiž•¹ÒÚ†ýóéÝû¾ÕS®ó$’NÝäŸz¤5r¦ãÄÃD÷Üø!°ø‡Ô&@m™Ì^Ãä­d q5Lnÿ N;.6½·N|#ä"1Nƒx“ã<3('&ñßt  ~ªu”1Tb㫨9ê–›–bìd$ߣ=#ÕãÒmU¯eí$EFù5ýYô櫨æì™Ç—±ssM]·á¿0ÕåJRÓªîiƒ+O58ÖñªŠÒx" \µâá¨i’¤i —Ö ” M+M¤ë9‚‰A¦°Qõ¾ßøK~¼Ã‘g…Ö´~÷Ï[3GUœÒ½#…kàÔ®Ò”‰³·dWV‰IP‰Ú8u¹”E ÖqLj¾êÕCBš{A^Âß;–¨`¯¬ìö ˼ ×tìø.tƐm*n¨y4o&Àx¥n¦×î‡aupáÛj8¿m›è¶ã!o½;ß0y^ý×^EÑ¿ÒjzŒ­)vÚÑnÄL …^ªô× ‡—‚3k Îý­hï]içå–îÏ*÷ñþ»Ô CÒjøjÍznˆ´ ¹#b'Fô‹ ‰v¥'’à'T´ƒHýÍ%M‰ ƒ&ÆÇŒï1 ‘ –Þ ‰i¬s žR-Ÿ kЬá¬7:þ 0ŒÅÒÕ/aÙ¬ÃÝ#Úøœ ©aiVc‰. ¹¦ãµ” ›Yg¦›ÆÎýº°f³7ƒhá·¸­}&D9¡ÂsÉÙÞèŠõØàC™¨ñbFC|´Ü(ŸƒÚÒ-%»'a Ì¿)ËÇn¿úÿ ÞŽX…4ÊÅH^ôΑí@ù¹Eh¶“L8Çjù ¼ÎåVªóR©Ï5uà V4lZß®=€xÖŸ–ÑÈ ÷”¨°¾__yM1tÉ?uÆþIkÄgæ@þ[¢†°XÃJ£j·:nkÅ¢u ‘}âGzö­/IµèЬ¼48q¦F°ŽR¼=ûì{´¯RýicS ÕÛ íNtÍÙï£,w4rêì®»~x(©Uñ§#Ñ&œÕ¤>ÎåÍÓ9’Ö{9eV­[Öjâ²ãu]˜å2›qÑšÕJç0€sÄ|Êëè0튔bÁ>“{×_F`Ø©ºê:µä,v¤ðfc1±"«ÔÍän1#=· Âøv~H½ÐßA¾¿Ü€Óš]Õ; I¾÷ç‚Qi†î¹9ywÔKG˜áñ zQY—§ÃÕZ07§X‚ Áh;ÁM)iÌCH-¯T‘ë|A0{Ò½LÚ–TâÖkÜ’dÀ“rmm»”جPF³ÖcbE§T€ÒxKºû’Ó®7±²(\4ŽÃ¸Uu@j™yĵ;³µ!Á¢b.W¤=mõ´êµK k ¸K^ÜÛ#p*Ü14qkZç5ïë †°5Ï%ÍÛ<Õ¤×Ô¥ê†C Õ´¼ú$ƒÖ“”]Ù¬qÞÚ[4©ý!ûÏ—Áb쳐XµA¬â~`›Çr¸8ìùÝ䫦<>ä÷«?xs´ÇÑ /á;¹øüÊÈÙà{"@Žïzâ¬[âß‚ U_<ÇŸ½4èN˜ú61®qŠu ¦þF£»äJ_ˆÙÎ~ ÞAã–݄ϗrŠD;xTž‘ô`É«…suãO`?³à™ô Lý#Íc5öoæØ‚y´´÷«ZR§<&JÇ+éâô´€i!Àˆ0æAoàðLèÖ-2ŸõW.’t^–(KÁmHµV@xÜÇy®Ñø­â^:Ú3w· 7½¹°ñ¸â¹®:',«Mœ—n­Á+Ãbš LÈ‘ÄnRÓÅœ%¦²‰¨ùQ:¤f‚ "PÕtô¸…cæl…&˜Ú˜Ôkv‹ž+vŠ,=¢v­6—Xy*¥t£«<™:“aîϲ=¦6rO]XI¿Œ÷¤zÚ­›¶ 6÷”w\d ü~v®ˆÌk«^m<ÿ ¢‰Õ\)ùºŽ;… lîÙÅEŠ®cѾ@vnMÏ,¼“ñ•ŽBxðÃzãÇç%3ˆ"}Ù•Åî> BÉú;Ò]V+P˜F_´ßé> Øše|ï‡ÄOmFæÇ ãqÞ$/xÐx­z`ï9"œÜij‚!7.\Td…9M‡•iŽ‹¾‘50ÞŽn¥ß4ÉôO ¹*í^QêËÜÇÌ8=ާs‰'ÂëÙ«á%Pú[O †ÅP¯Vsް.‰,kc¶ ¬A9n˜XÎ-ÞšN["¹QÕ‰ƒMýÁߺXJæÍaLj¾×Ãmã¾ãÚ uñÒþåQô¦¥ /ÄUx:‚ÍÜ’ Đ©ØÝ3V¨‰ÕnÐ6ó*óúK­«…c ¯U òhsý­jóÔj#,ímŒRµ«lbïUTŒÑ8†Ä0œÏr`ð¡¬É Ї ë"À² ™ 6¥ f¶ ¢ÚoܱԷ-<Àî)†a¶ž'Ú»¨TXqØæ¶÷YÄHy˜9ÈIW­YÀuMFë ºÏ’AqÌ4·/Ú †ô'i$øä­=Ä Ý|öK×40è|È6p‘0§)o¥ctî§H+CA-“ xØ|ÐXАç l8íºð3Ø:³¤¬KX¯UÿÙ#!/usr/bin/perl -w # podebconf-report-po, Send outdated debconf PO files to the last translator # Copyright (C) 2004-2006 Fabio Tranchitella # Denis Barbier # Copyright (C) 2007-2008 Nicolas François # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Library General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA # ## Release information my $PROGRAM = "podebconf-report-po"; my $VERSION = "0.14"; ## Loaded modules, require libmail-sendmail-perl use strict; my $no_zlib = 0; eval q{use Compress::Zlib;}; if ($@) { $no_zlib = 1; eval q{ sub Compress::Zlib::memGzip { return shift; } }; } my $no_encode = 0; eval q{use Encode;}; if ($@) { $no_encode = 1; } use MIME::Base64; use MIME::QuotedPrint; use Getopt::Long; use POSIX; use File::Temp 'tempfile'; use Cwd 'abs_path'; ## Global variables my $CONF_ARG; if (-e $ENV{'HOME'}."/.podebconf-report-po.conf") { $CONF_ARG = $ENV{'HOME'}."/.podebconf-report-po.conf"; } my $NO_CONF; my $HELP_ARG = 0; my $VERSION_ARG = 0; my $VERBOSE_ARG; my $NO_VERBOSE; my $SUBMIT_ARG = 0; my $FORCE_ARG; my $NO_FORCE; my $CALL; my $CALL_WITH_TRANSLATORS; my $CALL_WITHOUT_TRANSLATORS; my $POTFILE = ""; my $LANGS = ""; my $LANGUAGETEAM_ARG; my $NO_LANGUAGETEAM; my $SMTP_ARG; my $TEMPLATE_ARG; my $TEMPLATE_CALL; my $TEMPLATE_TRANSLATORS; my $TEMPLATE_SUBMIT; my $NO_TEMPLATE; my $DEFAULT_ARG; my $NO_DEFAULT; my $PACKAGE_ARG = ""; my $SUMMARY_ARG; my $NO_SUMMARY; my $FROM_ARG; my $BTS_ARG = ""; my $DEADLINE_ARG; my $NO_DEADLINE; my $PODIR_ARG = ""; my $GZIP_ARG; my $NO_GZIP; my $UTF8; my $NO_UTF8; my $MBOX = ""; my $MUTT = 0; my @ADDLANGUAGETEAM = (); my $SEND_MESSAGE = 0; my $NOT_DEBCONF = 0; my @TOPDIRS = qw{../.. .. .}; my $PODIR = ''; my $EDITOR = '/usr/bin/sensible-editor'; ## Default subjects (used if the specified template does not contain a ## Subject field). my $SUBJECT_TRANSLATOR; my $SUBJECT_SUBMIT; my $SUBJECT_CALL; my $SUBJECT = ''; my $BODY = ''; # Warnings may be deleted from screen when entering editor, # so display them when it is closed. my $warn = ''; ## Handle options GetOptions ( "conf=s" => \$CONF_ARG, "noconf" => \$NO_CONF, "help" => \$HELP_ARG, "version" => \$VERSION_ARG, "v|verbose" => \$VERBOSE_ARG, "noverbose" => \$NO_VERBOSE, "f|force" => \$FORCE_ARG, "noforce" => \$NO_FORCE, "podir=s" => \$PODIR_ARG, "smtp=s" => \$SMTP_ARG, "template=s" => \$TEMPLATE_ARG, "templatetranslators=s" => \$TEMPLATE_TRANSLATORS, "templatecall=s" => \$TEMPLATE_CALL, "templatesubmit=s" => \$TEMPLATE_SUBMIT, "notemplate" => \$NO_TEMPLATE, "default" => \$DEFAULT_ARG, "nodefault" => \$NO_DEFAULT, "gzip" => \$GZIP_ARG, "nogzip" => \$NO_GZIP, "langs=s" => \$LANGS, "languageteam" => \$LANGUAGETEAM_ARG, "nolanguageteam" => \$NO_LANGUAGETEAM, "addlanguageteam=s"=>\@ADDLANGUAGETEAM, "package=s" => \$PACKAGE_ARG, "deadline=s" => \$DEADLINE_ARG, "nodeadline" => \$NO_DEADLINE, "call:s" => \$CALL, "withtranslators" => \$CALL_WITH_TRANSLATORS, "withouttranslators" => \$CALL_WITHOUT_TRANSLATORS, "potfile=s" => \$POTFILE, "summary" => \$SUMMARY_ARG, "nosummary" => \$NO_SUMMARY, "from=s" => \$FROM_ARG, "bts=s" => \$BTS_ARG, "submit" => \$SUBMIT_ARG, "postpone=s" => \$MBOX, "mutt" => \$MUTT, "utf8" => \$UTF8, "noutf8" => \$NO_UTF8, "notdebconf" => \$NOT_DEBCONF, "sendmessage" => \$SEND_MESSAGE ) or &Help_InvalidOption; &Help_PrintVersion if $VERSION_ARG; &Help_PrintHelp if $HELP_ARG; eval q{use Mail::Sendmail;}; die "$PROGRAM: This program requires the libmail-sendmail-perl package.\n". "$PROGRAM: Aborting!\n" if $@; # Check invalid set of options if ($LANGUAGETEAM_ARG && defined $CALL && not $CALL_WITH_TRANSLATORS) { die "In the --call mode, the --languageteam option is only valid if --withtranslators is specified.\n"; } ## Try to locate the PO directory if ($PODIR_ARG eq "") { my $dir = getcwd; if ($NOT_DEBCONF) { if ($dir =~ m/\/po$/) { $PODIR = "."; } elsif (-d "$dir/po") { $PODIR = "po"; } } else { if ($dir =~ m/\/po$/) { $PODIR = "."; } elsif (-d "$dir/debian/po") { $PODIR = "debian/po"; } elsif (-d "$dir/po") { $PODIR = "po"; } } } else { $PODIR = $PODIR_ARG; } die "Directory po not found, exiting!\n" if $PODIR eq ""; die "Wrong argument: $PODIR is not a directory!\n" unless -d $PODIR; ## Try to detect if it is a debconf template translation unless ($NOT_DEBCONF) { my $dir = abs_path($PODIR); if ($dir =~ m/\/po$/ and $dir !~ m/\/debian\/po$/) { $NOT_DEBCONF = 1; } } ## Define the default subjects (if not set in the template) if ($NOT_DEBCONF) { $SUBJECT_TRANSLATOR = ": Please update the PO translation for the package "; $SUBJECT_SUBMIT = "PO translations for the package are outdated"; $SUBJECT_CALL = ": Please translate the package "; } else { $SUBJECT_TRANSLATOR = ": Please update debconf PO translation for the package "; $SUBJECT_SUBMIT = "debconf PO translations for the package are outdated"; $SUBJECT_CALL = ": Please translate debconf PO for the package "; } my $conf = ""; unless ($NO_CONF or !defined $CONF_ARG) { open (CNF, "< $CONF_ARG") or die ("Couldn't read $CONF_ARG: $!\nExiting!\n"); while () { $conf .= $_; } close(CNF) or die ("Couldn't close $CONF_ARG: $!\nExiting!\n"); $conf =~ s/^\s*#.*$//m; $conf =~ s/\s*$//m; } if ($conf =~ m/^smtp\s*(?:\s|=)\s*(.*)$/m) { $SMTP_ARG = $1; } elsif (!defined $SMTP_ARG) { $SMTP_ARG = ""; } if (defined $FROM_ARG) { # Use the from parameter from the command line } elsif ($conf =~ m/^from\s*(?:\s|=)\s*(.*)$/m) { $FROM_ARG = $1; } elsif (!defined $FROM_ARG) { # This part comes from devscripts' bts if ($ENV{'DEBEMAIL'} || $ENV{'EMAIL'}) { my ($email, $name); if (exists $ENV{'DEBFULLNAME'}) { $name = $ENV{'DEBFULLNAME'}; } if (exists $ENV{'DEBEMAIL'}) { $email = $ENV{'DEBEMAIL'}; if ($email =~ /^(.*?)\s+<(.*)>\s*$/) { $name ||= $1; $email = $2; } } if (exists $ENV{'EMAIL'}) { if ($ENV{'EMAIL'} =~ /^(.*?)\s+<(.*)>\s*$/) { $name ||= $1; $email ||= $2; } else { $email ||= $ENV{'EMAIL'}; } } if (! $name) { # Perhaps not ideal, but it will have to do $name = (getpwuid($<))[6]; $name =~ s/,.*//; } $FROM_ARG = $name ? "$name <$email>" : $email; } else { # We will try below to use the Maintainer: control field $FROM_ARG = ""; } } if (defined $NO_VERBOSE) { $VERBOSE_ARG = 0; } elsif ($conf =~ m/^verbose$/m) { $VERBOSE_ARG = 1; } elsif (!defined $VERBOSE_ARG) { $VERBOSE_ARG = 0; } if (defined $NO_FORCE) { $FORCE_ARG = 0; } elsif ($conf =~ m/^force$/m) { $FORCE_ARG = 1; } elsif (!defined $FORCE_ARG) { $FORCE_ARG = 0; } if (defined $NO_TEMPLATE) { $TEMPLATE_ARG = ""; } elsif ($conf =~ m/^template\s*(?:\s|=)\s*(.*)$/m) { $TEMPLATE_ARG = $1; } elsif (!defined $TEMPLATE_ARG) { $TEMPLATE_ARG = ""; } if (defined $TEMPLATE_TRANSLATORS) { # Command line has the highest priority } elsif ($conf =~ m/^templatetranslators\s*(?:\s|=)\s*(.*)$/m) { $TEMPLATE_TRANSLATORS = $1; } else { if ($NOT_DEBCONF) { $TEMPLATE_TRANSLATORS ="/usr/share/po-debconf/templates/translators-po"; } else { $TEMPLATE_TRANSLATORS ="/usr/share/po-debconf/templates/translators"; } } if (defined $TEMPLATE_SUBMIT) { # Command line has the highest priority } elsif ($conf =~ m/^templatesubmit\s*(?:\s|=)\s*(.*)$/m) { $TEMPLATE_SUBMIT = $1; } else { $TEMPLATE_SUBMIT ="/usr/share/po-debconf/templates/submit"; } if (defined $TEMPLATE_CALL) { # Command line has the highest priority } elsif ($conf =~ m/^templatecall\s*(?:\s|=)\s*(.*)$/m) { $TEMPLATE_CALL = $1; } else { if ($NOT_DEBCONF) { $TEMPLATE_CALL ="/usr/share/po-debconf/templates/call-po"; } else { $TEMPLATE_CALL ="/usr/share/po-debconf/templates/call"; } } if ($TEMPLATE_ARG ne "") { $TEMPLATE_TRANSLATORS = $TEMPLATE_ARG; $TEMPLATE_SUBMIT = $TEMPLATE_ARG; $TEMPLATE_CALL = $TEMPLATE_ARG; } if (defined $NO_DEFAULT) { $DEFAULT_ARG = 0; } elsif ($conf =~ m/^default$/m) { $DEFAULT_ARG = 1; } elsif (!defined $DEFAULT_ARG) { $DEFAULT_ARG = 0; } if (defined $NO_GZIP) { $GZIP_ARG = 0; } elsif ($conf =~ m/^gzip$/m) { $GZIP_ARG = 1; } elsif (!defined $GZIP_ARG) { $GZIP_ARG = 0; } if (defined $NO_DEADLINE) { undef $DEADLINE_ARG; } elsif (defined $DEADLINE_ARG) { # Use the specified deadline } elsif ($conf =~ m/^nodeadline$/m) { undef $DEADLINE_ARG; } elsif ($conf =~ m/^deadline\s*(?:\s|=)\s*(.*)$/m) { $DEADLINE_ARG = $1; } else { print " You should specify a deadline to help translators organize their work. This deadline is usually the date you are planning to make the next release (or the day before). Deadline? [+10days] "; chomp($DEADLINE_ARG = ); # The default deadline is +10days if ($DEADLINE_ARG eq "") { $DEADLINE_ARG = "+10days"; } } if (defined $NO_LANGUAGETEAM) { $LANGUAGETEAM_ARG = 0; } elsif (defined $LANGUAGETEAM_ARG) { $LANGUAGETEAM_ARG = 1; } elsif ($conf =~ m/^languageteam$/m) { $LANGUAGETEAM_ARG = 1; } elsif ($conf =~ m/^nolanguageteam$/m) { $LANGUAGETEAM_ARG = 0; } else { $LANGUAGETEAM_ARG = 1; } while ($conf =~ m/^addlanguageteam\s*(?:\s|=)\s*(.*)$/gm) { push @ADDLANGUAGETEAM, $1; } if (defined $NO_SUMMARY) { $SUMMARY_ARG = 0; } elsif ($conf =~ m/^summary$/m) { $SUMMARY_ARG = 1; } elsif (!defined $SUMMARY_ARG) { $SUMMARY_ARG = 0; } if (defined $NO_UTF8) { $UTF8 = 0; } elsif ($conf =~ m/^utf8$/m) { $UTF8 = 1; } elsif (!defined $UTF8) { $UTF8 = 0; } if (defined $CALL_WITHOUT_TRANSLATORS) { $CALL_WITH_TRANSLATORS = 0; } elsif (defined $CALL_WITH_TRANSLATORS) { $CALL_WITH_TRANSLATORS = 1; } elsif ($conf =~ m/^withtranslators$/m) { $CALL_WITH_TRANSLATORS = 1; } elsif ($conf =~ m/^withouttranslators$/m) { $CALL_WITH_TRANSLATORS = 0; } else { # The default. (it will be removed when not in --call mode) $CALL_WITH_TRANSLATORS = 1; } # Disable --withtranslators if no call for translations are requested with # --call. $CALL_WITH_TRANSLATORS = 0 unless defined $CALL; if ($no_encode and $UTF8) { $warn .= "--utf8 requires the Encode perl module. ". "Turning this option off.\n"; $UTF8 = 0; } if ($MUTT) { $MBOX = qx/mutt -Q postponed/; if ($MBOX =~ m/^postponed="(.*)"$/) { $MBOX = $1; } else { $MBOX = $ENV{'HOME'}."/postponed"; warn "Could not find mutt's postpone mailbox with ". " 'mutt -Q postponed'. Using $MBOX."; } } ## Try to find default editor $EDITOR = $ENV{'EDITOR'} if exists($ENV{'EDITOR'}); $EDITOR = $ENV{'VISUAL'} if exists($ENV{'VISUAL'}); if ($no_zlib && $GZIP_ARG) { $warn .= "Warning: This program requires the libcompress-zlib-perl package in order\n". " to support the --gzip flag, but it is not installed.\n". " PO files will not be compressed!\n\n"; $GZIP_ARG = 0; } if ($POTFILE eq "") { opendir(DIR, $PODIR); foreach my $potFile (grep(/\.pot$/, readdir(DIR))) { if (length $POTFILE) { die "Too many pot file found.\n". "Please specify one with the --potfile option.\n"; } $POTFILE = $potFile; } closedir(DIR); opendir(DIR, $PODIR); if (length $POTFILE) { print "Using $POTFILE for the call for translation\n"; } else { warn "No POT file found. You should specify one with the ". "--potfile option, or specify in the mail how to ". "retrieve it." } closedir(DIR); } ## Try to find the maintainer e-mail address and the package name # Package version my $PKG_VERSION = "N/A"; # Expanded into " " if version is found, otherwise my $PACKAGE_AND_VERSION = ""; if ($PACKAGE_ARG =~ s/_(.*)//) { $PKG_VERSION = $1; } if ($PACKAGE_ARG eq "" or $FROM_ARG eq "") { my $CONTROL = ''; foreach my $d (@TOPDIRS) { $CONTROL = "$d/debian/control" if (-f "$d/debian/control"); } if ($CONTROL eq '') { foreach my $d (@TOPDIRS) { $CONTROL = "$d/debian/control.in" if (-f "$d/debian/control.in"); } } if (-f $CONTROL) { ## Only read the first stanza local $/ = "\n\n"; open (CNTRL, "< $CONTROL") or die "Unable to read $CONTROL: $!\n"; my $text = ; close (CNTRL) or die "Unable to close $CONTROL: $!\n"; if ($PACKAGE_ARG eq "" && $text =~ m/^Source: (.*)/m) { $PACKAGE_ARG = $1; } if ($FROM_ARG eq "" && $text =~ m/^Maintainer: (.*)/m) { $FROM_ARG = $1; } } } if ($PKG_VERSION eq "N/A") { my $CHANGELOG = ''; foreach my $d (@TOPDIRS) { $CHANGELOG = "$d/debian/changelog" if (-f "$d/debian/changelog"); } if (-f $CHANGELOG) { # Version information is not vital, do not abort # if it cannot be retrieved. if (open (CHG, "< $CHANGELOG")) { while () { if (m/^$PACKAGE_ARG\s+\((.*)\)\s/) { $PKG_VERSION = $1; } last if m/^ --/; } } close (CHG); } } if ($PKG_VERSION eq 'N/A' and $PACKAGE_ARG eq '') { # Try to read the PACKAGEand VERSION from the .pot file Verbose("PODIR: $PODIR"); Verbose("POTFILE: $POTFILE"); my $content = &ReadFile($PODIR . "/" . $POTFILE); $content =~ m/\n"Project-Id-Version:\s*([^"]*)\s*\\n"\n/i; my $package_and_version = $1; if ($package_and_version =~ m/^(.+)\s+(.+?)$/i) { $PACKAGE_ARG = $1; $PKG_VERSION = $2; } else { $PACKAGE_ARG = $package_and_version; } } $PACKAGE_AND_VERSION = $PACKAGE_ARG . ($PKG_VERSION ne 'N/A' ? " ".$PKG_VERSION : ""); Verbose("Package: $PACKAGE_ARG"); Verbose("Version: $PKG_VERSION"); Verbose("Maintainer: $FROM_ARG"); # If the specified deadline starts with a '+', it is an offset from now. if ($DEADLINE_ARG =~ m/^\+/) { my $cmd = "LC_ALL=C date -R -d \"$DEADLINE_ARG\""; $DEADLINE_ARG = qx/$cmd/; if ($? != 0) { die "podebconf-report-po: failed to execute '$cmd': $!.\n"; } chomp $DEADLINE_ARG; } if ($DEADLINE_ARG ne "") { $DEADLINE_ARG = "\n\nThe deadline for receiving the updated translation is\n$DEADLINE_ARG."; } my $REPLY = ''; if ($BTS_ARG =~ m/^\d+$/) { $BTS_ARG .= "\@bugs.debian.org"; $REPLY = "Please respect the Reply-To: field and send your updated translation to\n$BTS_ARG."; } else { $REPLY = "Please send the updated file to me, or submit it as a wishlist bug\nagainst ."; } PREPARE_MAIL: if ($SUBMIT_ARG) { $BODY = &ReadFile($TEMPLATE_SUBMIT); $SUBJECT = $SUBJECT_SUBMIT; } elsif (defined $CALL) { $CALL="Debian Internationalization " unless length $CALL; $BODY = &ReadFile($TEMPLATE_CALL); $SUBJECT = $SUBJECT_CALL; } else { $CALL=""; $BODY = &ReadFile($TEMPLATE_TRANSLATORS); $SUBJECT = $SUBJECT_TRANSLATOR; } ## Apply the values to the subject and to the body of the message $SUBJECT =~ s//$PACKAGE_ARG/g; $SUBJECT =~ s//$PKG_VERSION/g; $SUBJECT =~ s//$PACKAGE_AND_VERSION/g; ## Check every file with .po extension in $PODIR ... Verbose("Checking for PO files in $PODIR"); opendir(DIR, $PODIR); my $poFiles = {}; my $statistics = "language translated fuzzy untranslated\n". "-----------------------------------------------------\n"; if (defined $CALL and length $CALL) { foreach my $poFile (grep(/\.po$/, sort readdir(DIR))) { $poFiles->{$poFile} = {}; my $cmd = "LC_ALL=C /usr/bin/msgfmt -o /dev/null --stat $PODIR/$poFile 2>&1"; my $stats = qx/$cmd/; chomp $stats; my ($t, $f, $u) = ("", "", ""); my $lang = $poFile; $lang =~ s/\.po$//; if ($stats =~ s/^([0-9]+) translated message[s ,]*//) { $t = $1; } if ($stats =~ s/^([0-9]+) fuzzy translation[s ,]*//) { $f = $1; } if ($stats =~ s/^([0-9]+) untranslated message[s ,]*//) { $u = $1; } $statistics .= sprintf(" %-10s%10s %10s %10s\n", $lang, $t, $f, $u); } } else { foreach my $poFile (grep(/\.po$/, readdir(DIR))) { local $/ = "\n\n"; $poFiles->{$poFile} = {}; my $outdated = 0; my $found_header = 0; open (PO, "< $PODIR/$poFile") or die "Unable to read $PODIR/$poFile: $!\n"; while () { if ($found_header == 0 && m/msgid ""\nmsgstr/s) { $found_header = 1; # Concatenate lines s/"\n"//g; if (m/\\nLast-Translator: (.*?)\\n/ && $1 ne 'FULL NAME ') { $poFiles->{$poFile}->{translator} = $1; } else { $warn .= "Warning: $poFile: Unable to determine last translator. Skipping file!\n"; last; } if (m/\\nContent-Type: [^;]*; charset=(.*?)\\n/) { $poFiles->{$poFile}->{charset} = $1; } else { $warn .= "Warning: $poFile: Unable to determine charset. Skipping file!\n"; last; } if ($LANGUAGETEAM_ARG && m/\\nLanguage-Team: (.*?)\\n/) { $poFiles->{$poFile}->{team} = $1 if $1 ne 'LANGUAGE '; } my $lang = $poFile; $lang =~ s/\.po$//; if ($LANGUAGETEAM_ARG) { foreach my $lang_list (@ADDLANGUAGETEAM) { next unless ($lang_list =~ m/^$lang:(.*)$/); my $list = $1; my $list_addr = $1; $list_addr =~ s/^.*?<([^<>]*)>.*?$/$1/; $poFiles->{$poFile}->{team} = "" unless (defined $poFiles->{$poFile}->{team}); next if ($poFiles->{$poFile}->{team} =~ m/(^|<)\Q$list_addr\E(>|$)/); if (length $poFiles->{$poFile}->{team}) { $poFiles->{$poFile}->{team} .= ", "; } $poFiles->{$poFile}->{team} .= $list; } } next; } # Ignore outdated msgids next unless m/^msgid /m; # Check for fuzzy or missing translations s/\n+$//s; if (m/^#, .*fuzzy/m or m/\nmsgstr ""$/s) { $outdated = 1; last; } } if ($UTF8) { Encode::from_to($poFiles->{$poFile}->{translator}, $poFiles->{$poFile}->{charset}, "UTF-8"); Encode::from_to($poFiles->{$poFile}->{team}, $poFiles->{$poFile}->{charset}, "UTF-8"); } close (PO) or die "Unable to close $PODIR/$poFile: $!\n"; delete $poFiles->{$poFile} unless $outdated; } closedir(DIR); if (keys %$poFiles) { print "Outdated files: ".join(' ', keys %$poFiles)."\n"; } else { print "No outdated files\n"; exit(0); } } my %langs=(); foreach (split(",", $LANGS)) { $langs{$_.".po"} = 1; } my $filelist = ''; if ($SUBMIT_ARG or length $CALL) { $filelist = join(' ', sort keys %$poFiles)."\n"; } else { # Try to detect invalid emails. # This is very frequent for language teams. my $warn_invalid_email = 0; foreach my $poFile (sort keys %$poFiles) { if ($poFiles->{$poFile}->{translator} !~ /^(.*<)?[^@]+@[^@]+\.[A-Za-z]{2,4}>?$/) { $warn_invalid_email = 1; last; } if (defined($poFiles->{$poFile}->{team}) and $poFiles->{$poFile}->{team} !~ /^(.*<)?[^@]+@[^@]+\.[A-Za-z]{2,4}>?$/) { $warn_invalid_email = 1; last; } } if ($warn_invalid_email) { $filelist .= "#\n" ."# WARNING: Some email addresses seem to be invalid.\n" ."# You should remove them and inform the translators separately.\n" ."#\n"; } # Add the list of PO files. foreach my $poFile (sort keys %$poFiles) { $filelist .= '### '; $filelist .= '[' .((!%langs or $langs{$poFile})?'*':' '). '] '; $filelist .= $poFile . ': ' . $poFiles->{$poFile}->{translator}; $filelist .= ', ' . $poFiles->{$poFile}->{team} if defined($poFiles->{$poFile}->{team}); $filelist .= "\n"; } # Remove non-ASCII characters $filelist = DropNonASCII($filelist) unless ($UTF8); } $filelist =~ s/\n$//s; my %headers = (); OPEN_EDITOR: ReplaceTags(); $BODY = &OpenEditor($EDITOR, $BODY) if not $DEFAULT_ARG; ReplaceTags(); %headers = &ParseHeaders($BODY); my %To = &ParseTo($BODY); print STDERR $warn if $warn ne ''; my @mails = (); if ($SUBMIT_ARG) { my %mail = ( From => $FROM_ARG, To => "maintonly\@bugs.debian.org", Subject => $SUBJECT, 'X-Mail-Originator' => "$PROGRAM $VERSION" ); $mail{body} = encode_qp(&RemoveHeaders($BODY)); @mails = (\%mail); } elsif (length $CALL) { my %mail = ( From => $FROM_ARG, To => $CALL, Subject => $SUBJECT, 'X-Mail-Originator' => "$PROGRAM $VERSION" ); my $ext = ($GZIP_ARG ? '.gz' : ''); my $file = $POTFILE; my $content = &ReadFile($PODIR . "/" . $file); $content = Compress::Zlib::memGzip($content) if $GZIP_ARG; my $file_encoded = encode_base64($content); my $contentType = ($GZIP_ARG ? "application/octet-stream": "text/x-gettext; name=\"$file\"; charset=\"US-ASCII\""); my $boundary = "=" . time() . "="; $mail{'content-type'} = "multipart/mixed; boundary=\"$boundary\""; my $charset = $UTF8?"utf-8":"us-ascii"; my $body = &RemoveHeaders($BODY); $mail{body} = <<_EOF_; --$boundary Content-Type: text/plain; charset="$charset" Content-Transfer-Encoding: quoted-printable $body _EOF_ if ($SEND_MESSAGE) { $mail{body} .= <<_EOF_; --$boundary-- _EOF_ } else { $mail{body} .= <<_EOF_; --$boundary Content-Type: $contentType Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="$file$ext" $file_encoded --$boundary-- _EOF_ } @mails = (\%mail); } else { my $body = encode_qp(&RemoveHeaders($BODY)); my $ext = ($GZIP_ARG ? '.gz' : ''); foreach my $file (keys %$poFiles) { if (defined $To{$file}) { my $content = &ReadFile($PODIR . "/" . $file); $content = Compress::Zlib::memGzip($content) if $GZIP_ARG; my $file_encoded = encode_base64($content); my $contentType = ($GZIP_ARG ? "application/octet-stream" : "text/x-gettext; name=\"$file\"; charset=\"$poFiles->{$file}->{charset}\""); my %mail = ( From => $FROM_ARG, To => $To{$file}, Subject => $SUBJECT, 'X-Mail-Originator' => "$PROGRAM $VERSION" ); my $boundary = "=" . time() . "="; $mail{'content-type'} = "multipart/mixed; boundary=\"$boundary\""; my $charset = $UTF8?"utf-8":"us-ascii"; $mail{body} = <<_EOF_; --$boundary Content-Type: text/plain; charset="$charset" Content-Transfer-Encoding: quoted-printable $body _EOF_ if ($SEND_MESSAGE) { $mail{body} .= <<_EOF_; --$boundary-- _EOF_ } else { $mail{body} .= <<_EOF_; --$boundary Content-Type: $contentType Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="$file$ext" $file_encoded --$boundary-- _EOF_ } push(@mails, \%mail); } } } # Add mail headers and remove non-ASCII characters foreach my $refmail (@mails) { foreach my $h (keys(%headers)) { if ($UTF8) { $refmail->{$h} = encode_qp($headers{$h}, ""); $refmail->{$h} =~ s/=$//m; $refmail->{$h} =~ s/(\S*=\S*)/=?utf-8?Q?$1?=/g; } else { $refmail->{$h} = &DropNonASCII($headers{$h}); } } foreach my $h (qw(From To Subject)) { if ($UTF8) { unless ($refmail->{$h} =~ m/=\?utf-8\?Q\?/) { $refmail->{$h} = encode_qp($refmail->{$h}, ""); $refmail->{$h} =~ s/=$//m; $refmail->{$h} =~ s/(\S*=\S*)/=?utf-8?Q?$1?=/g; } } else { $refmail->{$h} = &DropNonASCII($refmail->{$h}); } } $refmail->{smtp} = $SMTP_ARG if ($SMTP_ARG ne ''); } if (!$FORCE_ARG) { my $answers = ($DEFAULT_ARG)?"[y/N/?]":"[y/N/e/?]"; my $with_mutt = ""; $with_mutt = " (with mutt)" if $MUTT; QUESTION: print "The following files have been selected:\n"; foreach my $poFile (sort keys %$poFiles) { next unless defined $To{$poFile}; print " $poFile To: $To{$poFile}\n"; } print "End of files\n"; if ($SUBMIT_ARG) { print "Ready to send$with_mutt the bug report against the package $PACKAGE_ARG, are you sure? $answers "; } elsif (length $CALL) { print "Ready to send$with_mutt the call for translation to $CALL, are you sure? $answers "; } else { print "Ready to send$with_mutt the emails, are you sure? $answers "; } my $line = <>; chop $line; if ($line eq "e" or $line eq "E") { goto OPEN_EDITOR unless ($DEFAULT_ARG); } elsif ($line eq "?") { print "y send the mail(s).\n". "? display this help message.\n". ($DEFAULT_ARG?"":"e reopen the editor.\n"). "N exit, without sending mails.\n"; goto QUESTION; } exit(0) if ($line ne "Y" and $line ne "y"); } # Make Perl compiler quiet print $Mail::Sendmail::error . $Mail::Sendmail::error if 0; foreach my $mail (@mails) { if (defined $MBOX and length $MBOX) { Postpone($mail); } else { sendmail(%{$mail}) or print "Couldn't send the email: $Mail::Sendmail::error\n"; } } if ($SUMMARY_ARG and not $CALL) { my %summary = ( From => $FROM_ARG, To => $FROM_ARG, Subject => $SUBJECT, 'X-Mail-Originator' => "$PROGRAM $VERSION" ); $summary{body} = "List of outdated files:\n"; foreach my $poFile (sort keys %$poFiles) { $summary{body} .= ' ' . $poFile . ': ' . $poFiles->{$poFile}->{translator}; $summary{body} .= ', ' . $poFiles->{$poFile}->{team} if defined($poFiles->{$poFile}->{team}); $summary{body} .= "\n"; } $summary{body} .= "Translators received the mail below.\n\n"; $summary{body} .= encode_qp(&RemoveHeaders($BODY)); if (defined $MBOX and length $MBOX) { Postpone(\%summary); } else { sendmail(%summary) or print "Couldn't send the email: $Mail::Sendmail::error\n"; } } if ($MUTT) { if (system("mutt -p") >> 8 != 0) { die "Problem running mutt -p: $!\n"; } } if ($CALL_WITH_TRANSLATORS) { print "Now, prepare the mail for translators..."; undef $CALL; undef $CALL_WITH_TRANSLATORS; goto PREPARE_MAIL; } exit(0); ############################################################################### sub ReplaceTags { $BODY =~ s//$REPLY/g; $BODY =~ s//$BTS_ARG/g; $BODY =~ s/\n# Reply-To: \n/\n/; $BODY =~ s//$SUBJECT/g; $BODY =~ s//$PACKAGE_ARG/g if ($PACKAGE_ARG ne ''); $BODY =~ s//$PKG_VERSION/g if ($PKG_VERSION ne ''); $BODY =~ s//$PACKAGE_AND_VERSION/g if ($PACKAGE_AND_VERSION ne ''); $BODY =~ s//$FROM_ARG/g; $BODY =~ s/\n/$DEADLINE_ARG/g; $BODY =~ s/\n/$statistics/g; $BODY =~ s//$filelist/g; } sub OpenEditor { my $editor = shift; my $body = shift; my $opts = ""; my ($fh, $tmpnam) = tempfile("podebconf-report-po.mail.tmp.XXXXXX", UNLINK => 0, TMPDIR => 1); print $fh $body; close($fh) or die ("Couldn't close $tmpnam: $!\nExiting!\n"); $opts = "-f" if ($editor eq "vim"); system("$editor $opts $tmpnam"); $body = &ReadFile($tmpnam) if (-f $tmpnam); unlink($tmpnam); return $body; } sub ParseHeaders { my $body = shift; my %headers = (); while ($body =~ s/^#[ \t]*([^\n]*)\n//s) { my $comment = $1; if ($comment =~ m/^([a-zA-Z0-9_-]+):\s*([^\n]+)$/) { $headers{$1} = $2; } } return %headers; } sub ParseTo { my $body = shift; my %To = (); while ($body =~ s/^#[ \t]*([^\n]*)\n//s) { my $comment = $1; if ($comment =~ s/^##[ \t]*\[(?:\*|x|X)\][ \t]*([^:]*):[ \t]*([^\n]*)$//s) { $To{$1} = $2; } } return %To; } sub RemoveHeaders { my $body = shift; # First remove comments 1 while $body =~ s/^#[^\n]*\n//s; # Optional empty lines $body =~ s/^\s+//s; return $body; } sub DropNonASCII { my $text = shift; $text =~ s/[\x80-\xff]/?/g; return $text; } sub ReadFile { my $file = shift; local $/ = undef; open(FILE, "< $file") or die ("Couldn't read $file: $!\nExiting!\n"); my $body = ; close(FILE) or die ("Couldn't close $file: $!\nExiting!\n"); return $body; } ## Handle invalid arguments sub Help_InvalidOption { print STDERR "Try `${PROGRAM} --help' for more information.\n"; exit 1; } ## Print the usage message and exit sub Help_PrintHelp { print <<_EOF_; Usage: ${PROGRAM} [OPTIONS] Send outdated debconf PO files to the last translators. Options: --addlanguageteam=LANG:LIST Send a copy of the messages for language LANG also to the LIST (unless it is already the language team). --bts=BUGNUMBER specify the Debian bug number to set as reply-to --call[=LIST] send a call for translations to the LIST (or to the Debian I18N mailing list by default --conf --noconf --deadline=DEADLINE specify the deadline for receiving the updated translations --default don't open the editor and use the template as is --nodefault -f, --force send the email without confirmation --noforce --from=MAINTAINER specify the name and the email address of the sender --gzip compress PO files with gzip --nogzip --help display this help and exit --langs=LANGUAGES restrict sending emails only to these languages --languageteam send the email also to the Language Team --nolanguageteam --mutt send the mails with mutt. This set the --postpone argument to the mutt's postponed parameter or \$HOME/postponed --notdebconf this is not for debconf translation. Do not mention debconf in the subject and message --package=PACKAGE specify the name of the package --podir=DIRECTORY specify where are located the PO files --postpone=MBOX do not send emails, append them in MBOX. This file can be used as a postponed mailbox with mutt -p. --potfile=FILE when used with --call, specifies the POT file to attach to the call for translations --sendmessage only send a message, without any attachment --smtp=SERVER specify SMTP server for mailing (default localhost) --submit send a bug report against the package with a report of the outdated debconf translations --summary send a status report to the maintainer with the list of emails sent to translators --nosummary --utf8 send the mail in UTF-8 --noutf8 --version display version information and exit -v, --verbose display additional information --noverbose --templatecall=TEMPLATE specify file to use it as template for the emails --templatesubmit=TEMPLATE specify file to use it as template for the emails --templatetranslators=TEMPLATE specify file to use it as template for the emails --template=TEMPLATE specify file to use it as template for the emails --notemplate --withtranslators when used with --call, specifies that request for translation updates must be sent to the translators --withouttranslators _EOF_ exit 0; } ## Print the version text and exit sub Help_PrintVersion { print <<_EOF_; ${PROGRAM} $VERSION Copyright (C) 2004-2006 Fabio Tranchitella and Denis Barbier. Copyright (C) 2007 Nicolas François This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. _EOF_ exit 0; } sub Verbose { my $msg = shift; return unless $VERBOSE_ARG; $msg =~ s/^/**${PROGRAM}: /mg; print STDERR $msg."\n"; } sub Postpone { my $mail = shift; if (eval { require Mail::Box::Manager }) { import Mail::Box::Manager; my $mgr = new Mail::Box::Manager; my $folder = $mgr->open(folder => $MBOX, access => 'a', create => 1); my $msg = Mail::Message->build ( From => ${$mail}{'From'} , To => ${$mail}{'To'} , Subject => ${$mail}{'Subject'} , 'X-Mail-Originator' => ${$mail}{'X-Mail-Originator'} , 'Content-Type' => ${$mail}{'content-type'} , data => ${$mail}{body} ); $mgr->appendMessage($folder, $msg); $folder->write(); $mgr->close(); } else { die "The --postpone and --mutt options require the ". "perl Mail::Box package. Please install the Debian ". "libmail-box-perl package if you want to use these ". "options. No mail written or sent."; } }