ÿØÿà 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ÿÙ U 8]9@sdZddlZddlZddlZddlZz,ddlmZddlmZm Z e Z ee fWnDe k rddl mZddlmZddlm Z ddlm Z YnXddlZd d ZGd d d Zdd dZddZGdddeZdS)z"Abstract crash database interface.N) Exception) quote_plusurlopen) cmp_to_key)r)r)URLErrorcCst|tr|ddS|S)z.Convert str to an unicode if it isn't already.UTF-8ignore) isinstancebytesdecode)strr 0/usr/lib/python3/dist-packages/apport/crashdb.py_us  rc@sTeZdZddZddZddZddZdRd d Zd d ZddZ ddZ ddZ ddZ ddZ ddZddZdSddZdd Zd!d"Zd#d$Zed%d&ZdTd'd(Zd)d*Zd+d,Zd-d.ZdUd/d0ZdVd2d3Zd4d5Zd6d7Zd8d9Zd:d;Zdd?Z!d@dAZ"dBdCZ#dDdEZ$dFdGZ%dHdIZ&dJdKZ'dLdMZ(dWdNdOZ)dPdQZ*d S)X CrashDatabasecCs||_||_d|_dS)azInitialize crash database connection. You need to specify an implementation specific file with the authentication credentials for retracing access for download() and update(). For upload() and get_comment_url() you can use None. options is a dictionary with additional settings from crashdb.conf; see get_crashdb() for details. N) auth_fileoptions duplicate_db)selfrrr r r__init__&s zCrashDatabase.__init__cCs |jdS)zReturn the base URL for bug patterns. See apport.report.Report.search_bug_patterns() for details. If this function returns None, bug patterns are disabled. Zbug_pattern_urlrgetrr r rget_bugpattern_baseurl4sz$CrashDatabase.get_bugpattern_baseurlcCs"d|jkr|d|jdkSdS)zCheck if this report can be uploaded to this database. Crash databases might limit the types of reports they get with e. g. the "problem_types" option. Z problem_typesZ ProblemTypeTr)rreportr r raccepts<s zCrashDatabase.acceptsc Cs~ddl}|jdkstdd|_tj| pD|dkpDtj|dk}|j|dd|_ |r|j }| d | d |jg| d | d |j |j }| d | }|dgkrtdt|z| d|}Wn<|j jk r$}zdt|krdg}W5d}~XYnX|d|jkrFtd|d|d|jkrztd|d|jf||ddS)zInitialize duplicate database. path specifies an SQLite database. It will be created if it does not exist yet. rNZqmarkz/this module assumes qmark dbapi parameter stylez:memory:i )Ztimeoutz.CREATE TABLE version (format INTEGER NOT NULL)zINSERT INTO version VALUES (?)aCREATE TABLE crashes ( signature VARCHAR(255) NOT NULL, crash_id INTEGER NOT NULL, fixed_version VARCHAR(50), last_change TIMESTAMP, CONSTRAINT crashes_pk PRIMARY KEY (crash_id))zCREATE TABLE address_signatures ( signature VARCHAR(1000) NOT NULL, crash_id INTEGER NOT NULL, CONSTRAINT address_signatures_pk PRIMARY KEY (signature))zPRAGMA integrity_check)okzCorrupt duplicate db:zSELECT format FROM versionz no such tablez"duplicate DB has unknown format %iz+duplicate db has format %i, upgrading to %i)Zsqlite3Z paramstyleAssertionErrorformat_versionospathexistsgetsizeZconnectrcursorexecutecommitfetchall SystemErrorr fetchoneZOperationalErrorprint_duplicate_db_upgrade)rr!Zdbapi2Zinitcurresulter r rinit_duplicate_dbLsD            zCrashDatabase.init_duplicate_dbNc Cs.|jstd|s||}|||d|kr:|d}n|}g}|r~|||}|r~|D]\}}||q^|||}z|dd}Wntt fk rd}YnXd}d} |D]0\}} | r|rt j || dkr|}| } qq|r| ||dd|} | r|| } | r| |kr|dkr@| }nH|| krf||| ||| |n"|||| ||| | }d} |dk r||kr| r|| ||||||| fS|r|j} | d|g| d}|dkr| d t||df|j| r*|| |dS) aCheck whether a crash is already known. If the crash is new, it will be added to the duplicate database and the function returns None. If the crash is already known, the function returns a pair (crash_id, fixed_version), where fixed_version might be None if the crash is not fixed in the latest version yet. Depending on whether the version in report is smaller than/equal to the fixed version or larger, this calls close_duplicate() or mark_regression(). If the report does not have a valid crash signature, this function does nothing and just returns None. By default, the report gets download()ed, but for performance reasons it can be explicitly passed to this function if it is already available. -init_duplicate_db() needs to be called beforeDuplicateSignatureZPackageNrz0SELECT count(*) FROM crashes WHERE crash_id == ?z7INSERT INTO crashes VALUES (?, ?, ?, CURRENT_TIMESTAMP))rrdownload_mark_dup_checkedcrash_signature_duplicate_search_signature_duplicate_db_sync_statussplitKeyError IndexErrorapport packagingcompare_versionsmark_regressioncrash_signature_addresses#_duplicate_search_address_signatureclose_duplicate_duplicate_db_merge_id#_duplicate_db_add_address_signaturer$r%r)rr&)ridrsigexistingZex_id_Zreport_package_versionZ master_idZ master_verZex_verZaddr_sigZ addr_matchr,Zcount_idr r rcheck_duplicatesn                   zCrashDatabase.check_duplicatec Cs<|jdsdSdD] }|dkr>d|kr4|d}qF|}n|}|sLq||}|s`dStj|jd|t|}z.t |}| d}| d|krWqWnt tfk rYqYnX|D]f}z|dd\} } t| } Wntk rYqYnX| |kr||| } | s(d } | SqqdS) aCheck if the crash db already knows about the crash signature. Check if the report has a DuplicateSignature, crash_signature(), or StacktraceAddressSignature, and ask the database whether the problem is already known. If so, return an URL where the user can check the status or subscribe (if available), or just return True if the report is known but there is no public URL. In that case the report will not be uploaded (i. e. upload() will not be called). Return None if the report does not have any signature or the crash database does not support checking for duplicates on the client side. The default implementation uses a text file format generated by duplicate_db_publish() at an URL specified by the "dupdb_url" option. Subclasses are free to override this with a custom implementation, such as a real database lookup. Z dupdb_urlN)rFaddressrFr1rz404 Not Foundr2���1)r���r���r6���r@���duplicate_sig_hashr ���r!���joinr���r���readr ���closeIOErrorr��� splitlinesr9���int ValueError get_id_url) r���r���ZkindrF���hZurlfcontentslinerE���sr-���r ���r ���r���known���sD����          zCrashDatabase.knownc�����������������C���sD���|�j�std|�j��}|d||f}|jdks6t|�j���dS�)zMark given crash ID as fixed in the duplicate database. version specifies the package version the crash was fixed in (None for 'still unfixed'). r0���zXUPDATE crashes SET fixed_version = ?, last_change = CURRENT_TIMESTAMP WHERE crash_id = ?r2���N)r���r���r$���r%���Zrowcountr&���)r���rE���versionr,���nr ���r ���r���duplicate_db_fixed2��s���� z CrashDatabase.duplicate_db_fixedc�����������������C���sB���|�j�std|�j��}|d|g�|d|g�|�j���dS�)z{Remove crash from the duplicate database. This happens when a report got rejected or manually duplicated. r0���&DELETE FROM crashes WHERE crash_id = ?z1DELETE FROM address_signatures WHERE crash_id = ?Nr���r���r$���r%���r&���)r���rE���r,���r ���r ���r���duplicate_db_remove@��s ���� z!CrashDatabase.duplicate_db_removec�����������������C���sF���|�j�std|�j��}|d||g�|d||g�|�j���dS�)zChange a crash ID.r0���zSUPDATE crashes SET crash_id = ?, last_change = CURRENT_TIMESTAMP WHERE crash_id = ?=UPDATE address_signatures SET crash_id = ? WHERE crash_id = ?Nr_���)r���Zold_idZnew_idr,���r ���r ���r���duplicate_db_change_master_idL��s���� z+CrashDatabase.duplicate_db_change_master_idc����������� ������C���s��|�j�std|d�}t|�tj|d}t|�d}d}|�j��}|d�|�D�]Z\}}|� |} | dkrxq\| |kr| }|r| ��t tj||d}| d||f��q\|r| ��tj|d} t| �d}d}|d �|�D�]f\}}|� |} | dkrq| |krD| }|r0| ��t tj| |d }| d||f� d �q|rl| ��tj|rt||d ��t||�tj|d �rt|d ��dS�) a��Create text files suitable for www publishing. Create a number of text files in the given directory which Apport clients can use to determine whether a problem is already reported to the database, through the known() method. This directory is suitable for publishing to the web. The database is indexed by the first two fields of the duplicate or crash signature, to avoid having to download the entire database every time. If the directory already exists, it will be updated. The new content is built in a new directory which is the given one with ".new" appended, then moved to the given name in an almost atomic way. r0���z.newrJ���Nz3SELECT * from address_signatures ORDER BY signaturewz%i %s rF���z:SELECT signature, crash_id from crashes ORDER BY signaturewbr���z.old)r���r���r ���mkdirr!���rM���r$���r%���r'���rL���rO���openwriteencoder"���renameshutilZrmtree) r���diroutZ addr_baseZcur_hashZcur_filer,���rF���rE���rU���Zsig_baser ���r ���r���duplicate_db_publishX��sV����           z"CrashDatabase.duplicate_db_publishc�����������������C���sD���|dk�rt�d|�j�}|d|f�|�j��||�jks@tdS�)z"Upgrade database to current formatr���z2Cannot upgrade database from format earlier than 3zUPDATE version SET format = ?N)r(���r���r$���r%���r&���r���r���)r���Z cur_formatr,���r ���r ���r���r+�����s ����  z#CrashDatabase._duplicate_db_upgradec�����������������C���s^���|�j��}|dt||g�|�}dd�}tjd�dkrN|jt|d�n |j|d�|S�)a��Look up signature in the duplicate db. Return [(id, fixed_version)] tuple list. There might be several matches if a crash has been reintroduced in a later version. The results are sorted so that the highest fixed version comes first, and "unfixed" being the last result. id is the bug we are looking to find a duplicate for. The result will never contain id, to avoid marking a bug as a duplicate of itself if a bug is reprocessed more than once. zQSELECT crash_id, fixed_version FROM crashes WHERE signature = ? AND crash_id <> ?c�����������������S���sr���|�d�}�|d�}|�|krdS�|�dkr4|d�kr0dS�dS�|dkrL|�d�krHdS�dS�|�d�krXdS�|d�krddS�t�j|�|S�)Nr2���r����r3���)r<���r=���r>���)xyr ���r ���r���cmp��s"����z6CrashDatabase._duplicate_search_signature.<locals>.cmpr���3)key)rq���) r���r$���r%���r���r'���sysr[���sortr���)r���rF���rE���r,���rG���rq���r ���r ���r���r7�����s����  z)CrashDatabase._duplicate_search_signaturec�����������������C���sP���|sdS�|�j��}|d|g�|�}t|dks8t|rH|d�d�S�dS�dS�)z]Return ID for crash address signature. Return None if signature is unknown. Nz<SELECT crash_id FROM address_signatures WHERE signature == ?r2���r���)r���r$���r%���r'���lenr���)r���rF���r,���Z existing_idsr ���r ���r���rA�����s����  z1CrashDatabase._duplicate_search_address_signatureFc�����������������C���s\���|�j�stdi�}|�j��}|d�|D�],\}}}}|rJ|||f||<�q*||f||<�q*|S�)aY��Return the entire duplicate database as a dictionary. The returned dictionary maps "signature" to (crash_id, fixed_version) pairs. If with_timestamps is True, then the map will contain triples (crash_id, fixed_version, last_change) instead. This is mainly useful for debugging and test suites. r0���zSELECT * FROM crashes)r���r���r$���r%���)r���Zwith_timestampsdumpr,���rF���rE���ZverZ last_changer ���r ���r���_duplicate_db_dump��s����   z CrashDatabase._duplicate_db_dumpc�����������������C���s���|�j�std|�j��}|d|g�|�}|s6dS�|d�}|�|}|dkrjtd|��|�|�dS�|s|rtd||f��|�||�dS�|r|std||f��|�||�dS�dS�) a��Update the duplicate db to the reality of the report in the crash db. This uses get_fixed_version() to get the status of the given crash. An invalid ID gets removed from the duplicate db, and a crash which got fixed is marked as such in the database. r0���z4SELECT fixed_version FROM crashes WHERE crash_id = ?Nr���Zinvalidz5DEBUG: bug %i was invalidated, removing from databasez8DEBUG: bug %i got fixed in version %s, updating databasezCDEBUG: bug %i got reopened, dropping fixed version %s from database) r���r���r$���r%���r)���get_fixed_versionr*���r`���r]���)r���rE���r,���Zdb_fixed_versionZreal_fixed_versionr ���r ���r���r8��� ��s(����      z'CrashDatabase._duplicate_db_sync_statusc�����������������C���sV���|��|}|r*||krRtd|||f�n(|�j�}|dt||f�|�j��d�S�)NzIID %i has signature %s, but database already has that signature for ID %iz,INSERT INTO address_signatures VALUES (?, ?))rA���r(���r���r$���r%���r���r&���)r���rF���rE���rG���r,���r ���r ���r���rD���/��s���� ��  z1CrashDatabase._duplicate_db_add_address_signaturec�����������������C���sD���|�j�std|�j��}|d|g�|d||g�|�j���dS�)zMerge two crash IDs. This is necessary when having to mark a bug as a duplicate if it already is in the duplicate DB. r0���r^���ra���Nr_���)r���dupmasterr,���r ���r ���r���rC���;��s���� z$CrashDatabase._duplicate_db_merge_idc�����������������C���s`���d|kr dS�|�ddd�}d|�dddd�}|d d}t|d }|dd �}|S�) z5Create a www/URL proof hash for a duplicate signature N r2���r���rH���:���/r������)r9���rM���replacer���rh���)klassrF���ir ���r ���r���rL���I��s����  z CrashDatabase.duplicate_sig_hashc�����������������C���s ���t�ddS�)a��Upload given problem report return a handle for it. This should happen noninteractively. If the implementation supports it, and a function progress_callback is passed, that is called repeatedly with two arguments: the number of bytes already sent, and the total number of bytes to send. This can be used to provide a proper upload progress indication on frontends. Implementations ought to "assert self.accepts(report)". The UI logic already prevents uploading a report to a database which does not accept it, but for third-party users of the API this should still be checked. This method can raise a NeedsCredentials exception in case of failure. 6this method must be implemented by a concrete subclassNNotImplementedError)r���r���Zprogress_callbackr ���r ���r���uploada��s����zCrashDatabase.uploadc�����������������C���s ���t�ddS�)a8��Return an URL that should be opened after report has been uploaded and upload() returned handle. Should return None if no URL should be opened (anonymous filing without user comments); in that case this function should do whichever interactive steps it wants to perform. r���Nr���)r���r���Zhandler ���r ���r���get_comment_urls��s����zCrashDatabase.get_comment_urlc�����������������C���s ���t�ddS�)zReturn URL for a given report ID. The report is passed in case building the URL needs additional information from it, such as the SourcePackage name. Return None if URL is not available or cannot be determined. r���Nr���)r���r���rE���r ���r ���r���rT���}��s����zCrashDatabase.get_id_urlc�����������������C���s ���t�ddS�)z>Download the problem report from given ID and return a Report.r���Nr���r���rE���r ���r ���r���r4�����s����zCrashDatabase.downloadc�����������������C���s ���t�ddS�)ah��Update the given report ID with all data from report. This creates a text comment with the "short" data (see ProblemReport.write_mime()), and creates attachments for all the bulk/binary data. If change_description is True, and the crash db implementation supports it, the short data will be put into the description instead (like in a new bug). comment will be added to the "short" data. If attachment_comment is given, it will be added to the attachment uploads. If key_filter is a list or set, then only those keys will be added. r���Nr���)r���rE���r���commentZchange_descriptionZattachment_comment key_filterr ���r ���r���update��s����zCrashDatabase.updatern���c�����������������C���s���|�j�|||ddddgd�dS�)zUpdate the given report ID for retracing results. This updates Stacktrace, ThreadStacktrace, StacktraceTop, and StacktraceSource. You can also supply an additional comment. Z StacktraceZThreadStacktraceZStacktraceSourceZ StacktraceTop)r���N)r���)r���rE���r���r���r ���r ���r��� update_traces��s ���� ���zCrashDatabase.update_tracesc�����������������C���s ���t�ddS�)zSet username and password.r���Nr���)r���ZusernameZpasswordr ���r ���r���set_credentials��s����zCrashDatabase.set_credentialsc�����������������C���s ���t�ddS�)z2Get 'DistroRelease: <release>' from the report ID.r���Nr���r���r ���r ���r���get_distro_release��s����z CrashDatabase.get_distro_releasec�����������������C���s ���t�ddS�)zReturn set of crash IDs which have not been retraced yet. This should only include crashes which match the current host architecture. r���Nr���r���r ���r ���r���get_unretraced��s����zCrashDatabase.get_unretracedc�����������������C���s ���t�ddS�)a��Return set of crash IDs which need duplicate checking. This is mainly useful for crashes of scripting languages such as Python, since they do not need to be retraced. It should not return bugs that are covered by get_unretraced(). r���Nr���r���r ���r ���r���get_dup_unchecked��s����zCrashDatabase.get_dup_uncheckedc�����������������C���s ���t�ddS�)aX��Return an ID set of all crashes which are not yet fixed. The list must not contain bugs which were rejected or duplicate. This function should make sure that the returned list is correct. If there are any errors with connecting to the crash database, it should raise an exception (preferably IOError). r���Nr���r���r ���r ���r��� get_unfixed��s���� zCrashDatabase.get_unfixedc�����������������C���s ���t�ddS�)a��Return the package version that fixes a given crash. Return None if the crash is not yet fixed, or an empty string if the crash is fixed, but it cannot be determined by which version. Return 'invalid' if the crash report got invalidated, such as closed a duplicate or rejected. This function should make sure that the returned result is correct. If there are any errors with connecting to the crash database, it should raise an exception (preferably IOError). r���Nr���r���r ���r ���r���ry�����s���� zCrashDatabase.get_fixed_versionc�����������������C���s ���t�ddS�)z5Return list of affected source packages for given ID.r���Nr���r���r ���r ���r���get_affected_packages��s����z#CrashDatabase.get_affected_packagesc�����������������C���s ���t�ddS�)z3Check whether the user is the reporter of given ID.r���Nr���r���r ���r ���r��� is_reporter��s����zCrashDatabase.is_reporterc�����������������C���s ���t�ddS�)aB��Check whether the user is eligible to update a report. A user should add additional information to an existing ID if (s)he is the reporter or subscribed, the bug is open, not a duplicate, etc. The exact policy and checks should be done according to the particular implementation. r���Nr���r���r ���r ���r��� can_update��s����zCrashDatabase.can_updatec�����������������C���s ���t�ddS�)zcReturn master ID for a duplicate bug. If the bug is not a duplicate, return None. r���Nr���r���r ���r ���r��� duplicate_of��s����zCrashDatabase.duplicate_ofc�����������������C���s ���t�ddS�)zlMark a crash id as duplicate of given master ID. If master is None, id gets un-duplicated. r���Nr���)r���r���rE���r{���r ���r ���r���rB�����s����zCrashDatabase.close_duplicatec�����������������C���s ���t�ddS�)zpMark a crash id as reintroducing an earlier crash which is already marked as fixed (having ID 'master').r���Nr���)r���rE���r{���r ���r ���r���r?�����s����zCrashDatabase.mark_regressionc�����������������C���s ���t�ddS�)zMark crash id as retraced.r���Nr���r���r ���r ���r��� mark_retraced��s����zCrashDatabase.mark_retracedc�����������������C���s ���t�ddS�)zMark crash id as 'failed to retrace'. If invalid_msg is given, the bug should be closed as invalid with given message, otherwise just marked as a failed retrace. This can be a no-op if you are not interested in this. r���Nr���)r���rE���Z invalid_msgr ���r ���r���mark_retrace_failed ��s����z!CrashDatabase.mark_retrace_failedc�����������������C���s ���t�ddS�)zMark crash id as checked for being a duplicate This is an internal method that should not be called from outside. r���Nr���)r���rE���r���r ���r ���r���r5�����s����zCrashDatabase._mark_dup_checked)N)F)N)FNN)rn���)N)+__name__ __module__ __qualname__r���r���r���r/���rI���rZ���r]���r`���rb���rm���r+���r7���rA���rx���r8���rD���rC��� classmethodrL���r���r���rT���r4���r���r���r���r���r���r���r���ry���r���r���r���r���rB���r?���r���r���r5���r ���r ���r ���r���r���%���sV���9 fG  N- $     ����      r���c����������� ��� ���C���s��|st�jdd}i�}t|}tt|�|d|�W�5�Q�R�X�|d�}t�j|rt� |D�]}t�j ||}t�j |r^| dr^z2t| }tt|�|d|d��W�5�Q�R�X�W�q^�t k r�}�ztjd|t|f��W�5�d}~X�Y�q^X�q^|s|d �}t|�|d�|�S�) aN��Return a CrashDatabase object for the given crash db name. This reads the configuration file 'conf'. If name is None, it defaults to the 'default' value in conf. If conf is None, it defaults to the environment variable APPORT_CRASHDB_CONF; if that does not exist, the hardcoded default is /etc/apport/crashdb.conf. This Python syntax file needs to specify: - A string variable 'default', giving a default value for 'name' if that is None. - A dictionary 'databases' which maps names to crash db configuration dictionaries. These need to have at least the key 'impl' (Python module in apport.crashdb_impl which contains a concrete 'CrashDatabase' class implementation for that crash db type). Other generally known options are 'bug_pattern_url', 'dupdb_url', and 'problem_types'. ZAPPORT_CRASHDB_CONFz/etc/apport/crashdb.confexecz.dz.confZ databaseszInvalid file %s: %s Ndefault)r ���environr���rf���r���compilerN���r!���isdirlistdirrM���isfileendswithr���rt���stderrrg���r ��� load_crashdb) r���nameconfZsettingsrV���ZconfdDirZcfZcfpathr.���r ���r ���r��� get_crashdb��s&����    (r���c�����������������C���s(���t�d|d��t�t�dg}||�|S�)zReturn a CrashDatabase object for a given DB specification. spec is a crash db configuration dictionary as described in get_crashdb(). zapport.crashdb_impl.implr���) __import__globalslocalsr���)r���specmr ���r ���r���r���M��s����r���c�������������������@���s���e�Zd�ZdZdS�)NeedsCredentialsz8This may be raised when unable to log in to the crashdb.N)r���r���r���__doc__r ���r ���r ���r���r���V��s���r���)NN)r���r ���os.pathrt���rj��� exceptionsr���Zurllibr���r���rP���r��� ImportError functoolsr���Z urllib.parseZurllib.requestZ urllib.errorr<���r���r���r���r���r���r ���r ���r ���r���<module>���s.���      ������� .