o vf)@sdZddlZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z ddl Z ddl Z ddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlZddlmZddlmZejjdkrddl m Z e dZ!nddl"m Z dZ!d Z#d d Z$ej%&d d Z'dZ(ddZ) d)de*dej+e,dej+e,fddZ-de*de,dej+e,fddZ.de,de/e*e*ffddZ0ddde1e*de2ddfdd Z3d!d"Z4  d*d#d$Z5Gd%d&d&Z6Gd'd(d(Z7dS)+zAbstract Apport user interface. This encapsulates the workflow and common code for any user interface implementation (like GTK, Qt, or CLI). N)unicode_gettext)get_process_user_and_group) ConfigParserFTz2.20.11cCs(tjjdkrt|tdSt|S)z$Return exception message as unicode.rreplace)sys version_infomajorstrdecodelocalegetpreferredencoding) exceptionr+/usr/lib/python3/dist-packages/apport/ui.pyexcstr*s rAPPORT_SYMPTOMS_DIRz/usr/share/apport/symptomsi c Cs>ztd|ddd}t|WSttfyYdSw)Nz Pid: (.*) ProcStatus)researchgetgroupint IndexErrorAttributeError)reportpidrrrget_pid7s  rkeydefaultreturnc Cs,zttj|WSttfy|YSw)zGet an environment variable as integer. Return None if it doesn't exist or failed to convert to integer. The optional second argument can specify an alternate default. )rosenvironKeyError ValueError)r r!rrr _get_env_int?s r'nameuidcCsDtjddddt||gdddd}|jdks|jsdSt|jS) Npgrepz-nz-x-uTF)capture_outputchecktextr) subprocessrunr returncodestdoutrstrip)r(r)processrrr_get_newest_process_for_userMsr5c std|}|dur iStd|tjtjBtjB}z!ztj|Wnt y5iYWt |SwWt |nt |wfdddDS)zFind D-BUS address and XDG_DATA_DIRS for the given user. The D-BUS address and XDG_DATA_DIRS is needed for xdg-open. It is incredibly hard, or alternatively, unsafe to funnel it through pkexec/env/sudo, so grab it from gvfsd. gvfsdNz/proc/csi|] }|vr||qSrr).0r  gvfsd_envrr ns z&_get_users_environ..)DBUS_SESSION_BUS_ADDRESS XDG_DATA_DIRS) r5r#openO_RDONLYO_PATH O_DIRECTORYapport fileutilsget_process_environOSErrorclose)r) gvfsd_pid gvfsd_pid_fdrr8r_get_users_environYs"    rH get_user_envargsrJc Kstdtd}|duststj|fddi|dSt|}td}|dur-|j}ddtj D}|r?|t |O}|j |d <tj|fd|||t |j|d |dS) a`Call subprocess.run as real user if called via sudo/pkexec. If we are called through pkexec/sudo, determine the real user ID and run the command with it to get the user's web browser settings. If get_user_env is set to True, the D-BUS address and XDG_DATA_DIRS is grabbed from a running gvfsd and added to the process environment. SUDO_UID PKEXEC_UIDNr-FSUDO_GIDcSs(i|]\}}|ds|dkr||qS)SUDO_rM) startswith)r7kvrrrr:sz$run_as_real_user..HOME)r-envuserr extra_groups)r'ris_rootr/r0pwdgetpwuidpw_gidr#r$itemsrHpw_dir getgrouplistpw_name)rKrJkwargsr)pwuidgidrTrrrrun_as_real_userus2      rbc CsXz tt|dWdSty+}z|jtjkr WYd}~dSWYd}~dSd}~ww)NrFT)r#killrrDerrnoESRCH)rerrr still_runnings  rgc Cstz|Wn tyYnw||ri}zAt|}tt||d|Wdn1s3wY|d||}|sJtd|WdSt j t j |d|d<Wn%t ygtdYnty~td|ttdYnw|sd|vrtj|d}ntd tj|}|r||z||Wn'ty|sd |vrYnty} z t| |d <WYd} ~ nd} ~ wwd |vr5||rtdzDd |vr d t jvr d|vrd |vrtd|d <n(tj |d!ds tj"|d!ds td|d!d|d <Wnty4|s2d |vr2Ynwd|vrE|#} | rE| |d<|$ddkredt jvre|%} | retdd&| |d <|rz%t|d}t '|d|j(|ddWdn 1swYWnt)y} ztd|| fWYd} ~ nd} ~ wwtj*|t '|ddSdS)ayCollect information about report. Encapsulate calls to add_*_info() and update given report, so that this function is suitable for threading. ui must be a HookUI instance, it gets passed to add_hooks_info(). If reportfile is not None, the file is written back with the new data. If symptom_script is given, it will be run first (for run_symptom()). execNr0z8symptom script %s did not determine the affected packagerSymptomzsymptom script %s crashed:ExecutablePathzAcalled without a package, and report does not have ExecutablePathSnapUnreportableReasonCrashDBAPPORT_DISABLE_DISTRO_CHECKPackagez4This package does not seem to be installed correctlyzThis does not seem to be an official %s package. Please retry after updating the indexes of available packages, if that does not work then remove related third party packages and try again. DistroReleaseTitle ProblemTypeCrashAPPORT_IGNORE_OBSOLETE_PACKAGESzYou have some obsolete package versions installed. Please upgrade the following packages and check if the problem still occurs: %sz, abT)only_newzCannot update %s: %si)+ add_gdb_inforD add_os_infor=rhcompilereadrAerrorr#pathsplitextbasename StopIterationrexit Exception traceback print_excrBfind_file_packager% find_snap add_snap_infoadd_package_infor& SystemErrorradd_hooks_infor$_ packagingis_distro_packagesplitis_native_origin_packagestandard_titlerobsolete_packagesjoinchmodwriteIOErrormark_report_seen) r reportfilepackageuisymptom_scriptignore_uninstalledsymbfsnaprftitleold_pkgsrrrthread_collect_infos                   rc@seZdZdZddZddZd_ddZd d Zd d Zd dZ ddZ d`ddZ ddZ ddZ ddZddZddZddZd d!Zd"d#Zd$d%Zd&d'Zd(d)Zd*d+Zd,d-Zd.d/Z 0 dad1d2Zd3d4Zd5d6Zd7d8Zd9d:Zd;d<Zd=d>Z d?d@Z!dbdAdBZ"dCdDZ#dEdFZ$dGdHZ%dIdJZ&dKdLZ'dMdNZ(dOdPZ)dQdRZ*dSdTZ+dUdVZ,dWdXZ-dYdZZ.d[d\Z/d]d^Z0dS)c UserInterfaceaApport user interface API. This provides an abstract base class for encapsulating the workflow and common code for any user interface implementation (like GTK, Qt, or CLI). A concrete subclass must implement all the abstract ui_* methods. c Csd|_d|_d|_d|_d|_d|_z tjd|_Wn't y5}zt dt |WYd}~nd}~wt yBt dYnwt |j|dS)z8Initialize program state and parse command line options.rANFzDCould not import module, is a package upgrade in progress? Error: %sz8/etc/apport/crashdb.conf is damaged: No default database)gettext_domainr report_file cur_package offer_restartspecified_a_pkgrAcrashdb get_crashdb ImportErrorfatalr r%gettext textdomain parse_argv)selfrfrrr__init__'s    zUserInterface.__init__cCsd}d|_tdkrtj}d}n(tj}ts#tj t }nt dt tj tj BtjB}tjj |d}|D]A}||sEq=|rjd|jvrjd|jvrj|jsWq=|d|jdksi|d |jkrjq=|jd d krw||n||d}q=|S) aPresent all currently pending crash reports. Ask the user what to do about them, and offer to file bugs for them. Crashes that occurred in a different desktop (logind) session than the one that is currently running are not processed. This skips crashes that happened during logout, which are uninteresting and confusing to see at the next login. Return True if at least one crash report was processed, False otherwise. FTrN/proc/%s) proc_pid_fd_LogindSessionDaterrrHang)rr#geteuidrArBget_new_system_reportsget_new_reportsPY3Reportget_logind_sessiongetpidr=r>r?r@ load_reportr get_timestamp finish_hang run_crash)rresultreportslogind_sessionrrrrr run_crashes@s2    "     zUserInterface.run_crashesTc Cs||_zztj|Wn tyYnw|js!||s!WdSd|jvr)WdS|jddkrfd|jvrfd|jvrfd|jvrftj |jdt d }t d |}| t d |d |t d fWdStj }||}|dsx|drd|jvr||jdurWdS|dr|WdS|dr||dr|jz |dr||dWn tyYnw|dsWdSd|jvr|jddkrtj||j|jr|rWdS|rWdS|WdSWdStyT}zT|jtjtjfvr| t dt dt dn,|jtj!kr-| t dt dt dn| t d|j"t dWYd}~dSWYd}~dSWYd}~dSd}~wtyu}z|jtj#krit$dnWYd}~dSd}~ww)zPresent and report a particular crash. If confirm is True, ask the user what to do about it, and offer to file a bug for it. If confirm is False, the user will not be asked, and the crash is reported right away. NIgnorerrrsSignalCoreDump Stacktracerjzunknown programz+Sorry, the program "%s" closed unexpectedly Problem in %s%s %szxYour computer does not have enough free memory to automatically analyze the problem and send a report to the developers.rexamine Dependenciesrestart blacklistremember_MarkForUploadFalseInvalid problem reportz2You are not allowed to access this problem report.rErrorz@There is not enough disk space available to process this report.zOut of memory, aborting)%rrArBrrDrrrr#r|r~rui_error_messageallowed_to_reportui_present_report_details collect_inforr mark_ignoreremember_send_reportr%mark_report_uploadracceptshandle_duplicatecheck_unreportable file_reportrrdEPERMEACCESrrENOSPCstrerrorENOMEMr)rrconfirmsubjectheadingrresponserfrrrrvs   .                zUserInterface.run_crashcCstj|tj|dS)zFinish processing a hanging application after the core pipe handler has handed the report back. This will signal to whoopsie that the report needs to be uploaded. N)rArBrr)rrrrrrs zUserInterface.finish_hangc Cs`td|_|jjs|tdtddSz|j|Wn=ty[}z1t |dkr<|tdtdt dnt |d krQ|td td t dWYd }~nd }~ww|j |j d d}tj||_|jtj}|j||d}|drtj|j|tt|tjn tt|tj|dr|||d Sd S)aReport an application hanging. This will first present a dialog containing the information it can collect from the running application (everything but the trace) with the option of terminating or restarting the application, optionally reporting that this error occurred. A SIGABRT will then be sent to the process and a series of noninteractive processes will collect the remaining information and mark the report for uploading. rzNo PID specifiedz;You need to specify a PID. See --help for more information.Fzinvalid process Invalid PIDz(The specified process ID does not exist.rznot accessiblez Not your PIDz0The specified process ID does not belong to you.Nrjr) modal_forrr)rArroptionsrrr add_proc_infor&r rrrrrBrrrxrrmark_hanging_processr#rcrsignalSIGABRTSIGKILL wait_for_pidr)rrrfr|rrrrrrun_hangsJ             zUserInterface.run_hangc CsX z tt|dWnty%}z|jtjkr WYd}~dSd}~wwtdq)zwaitpid() does not work for non-child processes. Query the process state in a loop, waiting for "no such process." TrNr)r#rcrrDrdretimesleep)rrrfrrrrs  zUserInterface.wait_for_pidcCstt|tjdSN)r#rcrrSIGSEGV)rrrrr kill_segv"szUserInterface.kill_segvNc Cs|jjs|jjs|s|rdS|tdtddStd|_|jjrz[d}t rFt d|jjt j t j Bt jB}t j dt j |d }nd |jj}t |}|}Wdn1sbwYt|d }|t@rvd |j_n |jj|jj|d WnNtttfy}z:t|dr|jtjkrWYd}~dS|jtjkr|tdtdWYd}~dS|tdtdWYd}~dSd}~ww|j|jjr|jj|j_|jjd krtj|_ n|jj|_ z|!|WnAty6}z4dt"|vr1dt"|vr1|j s|tdtd|n |tdtd|j WYd}~dSd}~ww|#r>dS|$|%rIdSz|jd=Wn t&yYYnw|jj'rzWt j()|jj'}|*drt+ |d}|j,|Wdn 1swYn%t t j()|jj'd}|j,|Wdn1swYWdSWdSWdSttfy}z|tdt-|WYd}~dSd}~wwd} |.| } | dr|/dS)a@Report a bug. If a pid is given on the command line, the report will contain runtime debug information. Either a package or a pid must be specified; if none is given, show a list of symptoms. If a symptom script is given, this will be run first (used by run_symptom()). TzNo package specifiedzHYou need to specify a package or a PID. See --help for more information.FBugNrstat)dir_fdz /proc/%s/statlinux)rrrdzPermission deniedzfThe specified process does not belong to you. Please run this program as the process owner or as root.rz6The specified process ID does not belong to a program.rzdoes not existrz7Symptom script %s did not determine an affected packagezPackage %s does not exist ProcCmdlinez.gzwbCannot create reportr)0rrr run_symptomsrrrArrrr#r=r>r?r@iorzrr PF_KTHREADrr&rrDhasattrrdENOENTradd_proc_environr3rget_kernel_packagerrr radd_extra_tagsrr%saver| expanduserendswithgziprrrr) rrr stat_filerrflagsrfsavefilerrrrrrun_report_bug%s   "                          zUserInterface.run_report_bugc Cs|j|jjs|tdtddS|j|jj}|s)|td}|s)dSt d|_ |jj r;|jj g}n|j |jj}d}|D]@}||_||j d<||j d<ztj|Wn ty~tjtjtj jd|s|td |YqGYnw|jd d d }qG|s|tdtd dS|j |j ||j d =z|j d=Wn tyYnwt|j dkr|tdtd dSd }||}|dr|jj |jj|j d|ddd SdS)z:Update an existing bug with locally collected information.zUpdating problem reportzYou are not the reporter or subscriber of this problem report, or the report is a duplicate or already closed. Please create a new report using "apport-bug".FaHYou are not the reporter of this problem report. It is much easier to mark a bug as a duplicate of another than to move your comments and attachments to a new bug. Subsequently, we recommend that you file a new bug report using "apport-bug" and make a comment in this bug about the one you file. Do you really want to proceed?r SourcePackageroz source_%s.pyz8Package %s not installed and no hook available, ignoringT)rz$No additional information collected.rrrzapport information)change_descriptionattachment_comment)!r can_updater update_reportrr is_reporterui_question_yesnorArrrr3get_affected_packagesrr get_versionr&r#r|existsr _hook_dirprintrui_info_message add_user_inforrr%lenrupdate)rrrpkgsinfo_collectedprrrrrrun_update_reportsv              zUserInterface.run_update_reportc Csttjtd}g}g}|D]h}tj|drqi}z!t|}tt | |d|Wdn1s9wYWnt yRt d|tYqwd|vr^t d|q|tjtj|d||d |d q|s}d Sttt||\}}t|}t|}|d|d |td |d }|dur||d}|r|tjt|ddSd SdS)zlReport a bug from a list of available symptoms. Return False if no symptoms are available. z*.pyrrhNzsymptom script %s is invalidr0z0symptom script %s does not define run() functionr descriptionFz Other problemz+What kind of problem do you want to report?.pyT)globr#r|rsymptom_script_dirr~rPr=rhryrzrrAr{rrappendr}rzipsortedlistui_question_choicerr ) rscripts symptom_namessymptom_descriptionsscriptrrchsymptomrrrrsP        zUserInterface.run_symptomscCsPtjt|jjd}tj|s!|tdtd|jjdS| |dS)z#Report a bug with a symptom script.r%zUnknown symptomzThe symptom "%s" is not known.N) r#r|rr'rr2rrrr )rr0rrr run_symptoms  zUserInterface.run_symptomc Cs|jjr |dS|jjr||jjdS|jjr|S|jjdur)| S|jj r3t t dS|jj r`z ||jj dWdSty_}z|tdt|WYd}~dSd}~ww|jjrtddkrw|tdtddS|d td tjd d gtjtjd }|\}}|jdkrzt|d|j_W|Sty|tdtdYdSw|tdtdd|dS|S)zCall appopriate run_* method according to command line arguments. Return True if at least one report has been processed, and False otherwise. TNFrXDG_SESSION_TYPEwaylandra<The window option cannot be used on Wayland. Please find the window's process ID and then run 'ubuntu-bug '. The process ID can be found by running the System Monitor application. In the Processes tab, scroll until you find the correct application. The process ID is the number listed in the ID column.rz^After closing this message please click on an application window to report a problem about it.xprop _NET_WM_PIDr2stderrrr$z2xprop failed to determine process ID of the window ) rr2r3hangingrrfilebugr rr"versionr __version__ crash_filerrDrrrwindowr#getenvrr/PopenPIPE communicater1rrr&r)rrfr6outerrrrrrun_argv!s`        zUserInterface.run_argvcCsttd}|jddtdd|jddgtdd |\|_|_t|jd ks2|jd s<| d t d t |jd |j_ d |j_d|j_d |j_d |j_d|j_g|_d S)zgParse command line options when being invoked in update mode. Return (options, args). z%prog -p --packagezSpecify package name.help--tagr(@Add an extra tag to the report. Can be specified multiple times.actionr!rKrrz-You need to specify a report number to updateNF)optparse OptionParserr add_option parse_argsrrKrisdigitr{rrrrr2r<r?r=r;)r optparserrrrparse_argv_update`s$    zUserInterface.parse_argv_updatecCs,ttjdkr9dtjvr$tjtjtjdtjtjdtjd<tjd}| ds3| dr9| dSt t d}|jddd d d t d d |jddd d t dd|jddddt dd|jdddt dd|jddt dd |jd!d"dt d#d$|jd%d d t d&d|jd'd(d)t d*tjjd|jd+d)t d,d|jd-d.gt d/d|jd0d1d t d2d3ttjdkr| d4rd5D] }t j||_q|\|_|_|jjr|jjs|jjs|jjs|jjs|jjs|jjr|d6ttjdkr dSttjd7kr | d4r d8|j_dSt|jd7kr*dStj tjt!|jdd9rKd8|j_|jd|j_g|_dS|jd d:s]|jd d;ri|jd|j_g|_dS|jd"rd8|j_|jd|j_g|_dSd<|jdvr|jd#d=rtj$|jd%d<d>}|s|d?|jdn'|&d@dAr|dB|jd|dC|d@fn|dD|jd|dCft'd7ntj()|jd}|s|dE|jdt'd7g|_d8|j_||j_*dSd8|j_d8|_+|jd|j_*g|_dS)FzParse command line options. If a single argument is given without any options, this tries to "do what I mean". rAPPORT_INVOKED_ASz -update-bugz-collectNzF%prog [options] [symptom|pid|package|program path|.apport/.crash file]-fz --file-bug store_truer<FzStart in bug filing mode. Requires --package and an optional --pid, or just a --pid. If neither is given, display a list of known symptoms. (Implied if a single argument is given.))rOdestr!rKz-wz--windowz7Click a window as a target for filing a problem report.rNr+z --update-bugrrz;Start in bug updating mode. Can take an optional --package.)typerZrK-sz --symptomSYMPTOMzWFile a bug report about a symptom. (Implied if symptom name is given as only argument.))metavarrKrHrIzSpecify package name in --file-bug mode. This is optional if a --pid is specified. (Implied if package name is given as only argument.)rJ-Pz--pidzSpecify a running program in --file-bug mode. If this is specified, the bug report will contain more information. (Implied if pid is given as only argument.))r[rKz --hangingz*The provided pid is a hanging application.-cz --crash-filePATHzReport the crash from given .apport or .crash file instead of the pending ones in %s. (Implied if file is given as only argument.)z--savezIn bug filing mode, save the collected information into a file instead of reporting it. This file can then be reported later on from a different machine.rLr(rMz-vz --versionz Print the Apport version number.)rOrKz-bug)rXr+r\rHr_r`zL-u/--update-bug option cannot be used together with options for a new reportrTr%z.crashz.apport/z /snap/binr$zx%s is provided by a snap. No contact address has been provided; visit the forum at https://forum.snapcraft.io/ for help.contactrG%s is provided by a snap published by %s. Contact them via %s for help. developer%s is provided by a snap published by %s. No contact address has been provided; visit the forum at https://forum.snapcraft.io/ for help.z %s does not belong to a package.),rrargvr#r$r|rdirnamer~rrVrPrQrrRrArB report_dir SUPPRESS_HELP get_optionrKrSrrKrr<r@r2rr?rr{rr'rTrPrrrrrget_file_packagerr)rcmdrUorpkgrrrrxs             " $  $    zUserInterface.parse_argvcCsP|dkrtd|ddS|dkrtd|ddStd|tddS) zCFormat the given integer as humanly readable and i18n'ed file size.i@Bz%.1fg@@z KBiʚ;g.Az MBz GB)r formatfloat)rsizerrrformat_filesizes zUserInterface.format_filesizec Csdd}|jD]*}|j|r/z|t|j|jdd7}Wqty.|t|j|7}Yqwq|S)z'Return the size of the complete report.rrrr gzipvaluerrrrrQrrrget_complete_sizes    zUserInterface.get_complete_sizec Csld}|jD].}|dkr3|j|r3z|t|j|jdd7}Wqty2|t|j|7}Yqwq|S)z&Return the size of the reduced report.rrrrtrurwrrrget_reduced_sizes    zUserInterface.get_reduced_sizecCsr|jrd|jvr dSztjddgtjtjddkrWdSWn ty'YdSwz|dWSty8YdSw)zCheck whether to offer the "Examine locally" button. This will be true if the report has a core dump, apport-retrace is installed and a terminal is available (see ui_run_terminal()). rFwhichzapport-retracer8rN)rr/callrCSTDOUTrDui_run_terminalNotImplementedErrorrrrrcan_examine_locallys&    z!UserInterface.can_examine_locallyc CsTd|jvsJtdkr(ttddd|jd|jdtddSdS)zReopen the crashed application.rrshr`RespawnCommandrN)rr#forksetsidexeclprrrrrrrr(s   zUserInterface.restartcCs|tdtdtdtd|jgd}|durdSdtjd}d }d |jd d d }|d ||d ||d |d|d}|||ddS)zLocally examine crash report.zJThis will launch apport-retrace in a terminal window to examine the crash.zRun gdb sessionz1Run gdb session without downloading debug symbolsz)Update %s with fully symbolic stack traceFNz"apport-retrace -S system -C %s -v z~/.cache/apport/retracezapport-retrace 'z'\''z--gdb z --output  )rrrr)r,rrr#r|rrr})rrretrace_with_downloadretrace_no_downloadfileargcmdsrrrr2s(    zUserInterface.examinec Cs|rd}nd}ztddddddd d d |g tgd WdSttjfyF}z|td dtdt|fWYd}~dSd}~ww)z"Put whoopsie in auto or never modetruefalse/usr/bin/gdbusr{-y-dcom.ubuntu.WhoopsiePreferences-o/com/ubuntu/WhoopsiePreferences-mz/com.ubuntu.WhoopsiePreferences.SetReportCrashes) rr{rrrrrrz.progress_callbackrrrrzDPlease enter your account information for the %s bug tracking systemzNetwork problemrzHCannot connect to crash database, please check your Internet connection.)"rrrrr%rr+rPui_start_upload_progressrAruploadrrui_set_upload_progressrrrrrNeedsCredentialsrui_question_userpassrset_credentials TypeError SyntaxErrorr&rrrui_stop_upload_progressget_comment_urlr) rrrQupthreadrfrdatarUpasswordticketrrrrrs|            zUserInterface.file_reportc CsXz-t|_t|d}|jj|ddWdn1swYd|jvr,tdWn_tyDd|_|tdtdYd St yb}zd|_|td |j WYd}~d Sd}~wt tt t jfy}zd|_|td d td t|fWYd}~d Sd}~wwd |jvr|jd d|_dStj|jdd|_dS)zLoad report from given path and do some consistency checks. This might issue an error message and return False if the report cannot be processed, otherwise self.report is initialized and True is returned. rb compressed)binaryNrrz+Report does not contain "ProblemType" fieldzMemory exhaustionzEYour system does not have enough memory to process this crash report.FrrrrorrjrT)rArrr=loadr& MemoryErrorrrrrrAssertionErrorrr{rrrrBrr)rr|rrfrrrrsF       zUserInterface.load_reportcCs|j|js dSd|jvrFt|jdtkr"|jdd|jd<d|jvr5td|jdd}nd}||td|jdd SdS) znCheck if the current report is unreportable. If so, display an info message and return True. FrlUTF-8rorrrz#The problem cannot be reported: %sT) rrrr[bytesr rrr)rrrrrrs   z UserInterface.check_unreportablec Csd|jvrtj|jdr|jd}nz tj|j}Wn ty'YdSw|s,dSt r9t ddd}ddi}nt }i}z |j |fi|Wn.t yw}z"dt |jvrrdt |jvrrtjd |t |fWYd}~dSd}~ww|d sdSt|d }d |vrdS|S) zReturn a .desktop info dictionary for the current report. Return None if report cannot be associated to a .desktop file. DesktopFileNF) interpolationstrictencodingronfigarserzWarning! %s is broken: %s z Desktop Entryr()rr#r|rrArBfind_package_desktopfilerr&rrrzrr __class__rr9r has_sectionrr[)r desktop_filecpr_rfrrrrget_desktop_entry s:     zUserInterface.get_desktop_entrycCsp|j|js dSd|jvrdS|jddr,|tdtd||jddS|tdtddS)zCheck if current report matches a bug pattern. If so, tell the user about it, open the existing bug in a browser, and return True. FrhttpzProblem already knownzThis problem was already reported in the bug report displayed in the web browser. Please check if you can add any further information that might be helpful for the developers.z;This problem was already reported to developers. Thank you!T)rrrrPrrrrrrrr2s   zUserInterface.handle_duplicatecCsL|jsJ|jjr$|jdd}|r|d7}|d|jj|jd<dSdS)z6Add extra tags to report specified with --tags on CLI.rrrN)rrtagrr)rtagsrrrrLs zUserInterface.add_extra_tagscCtd)aShow details of the bug report. Return the action and options as a dictionary: - Valid keys are: report the crash ('report'), restart the crashed application ('restart'), or blacklist further crashes ('blacklist'). .this function must be overridden by subclassesr~)rrrrrrrZ z'UserInterface.ui_present_report_detailscCr)z:Show an information message box with given title and text.rrrrr.rrrrezUserInterface.ui_info_messagecCr)z4Show an error message box with given title and text.rrrrrrrjrzUserInterface.ui_error_messagecCr)zOpen a indefinite progress bar for data collection. This tells the user to wait while debug information is being collected. rrrrrrroz/UserInterface.ui_start_info_collection_progresscCr)zaAdvance the data collection progress bar. This function is called every 100 ms. rrrrrrrwz/UserInterface.ui_pulse_info_collection_progresscCr)z,Close debug data collection progress window.rrrrrrr~rz.UserInterface.ui_stop_info_collection_progresscCr)z{Open progress bar for data upload. This tells the user to wait while debug information is being uploaded. rrrrrrrrz&UserInterface.ui_start_upload_progresscCr)zUpdate data upload progress bar. Set the progress bar in the debug data upload progress window to the given ratio (between 0 and 1, or None for indefinite progress). This function is called every 100 ms. rr)rprogressrrrrz$UserInterface.ui_set_upload_progresscCr)z(Close debug data upload progress window.rrrrrrrrz%UserInterface.ui_stop_upload_progresscCsdS)zdCalled right before terminating the program. This can be used for for cleaning up. NrrrrrrszUserInterface.ui_shutdowncCr)aRun command in, or check for a terminal window. If command is given, run command in a terminal window; raise an exception if terminal cannot be opened. If command is None, merely check if a terminal application is available and can be launched. rr)rcommandrrrr}rzUserInterface.ui_run_terminalcCr)Show a yes/no question. Return True if the user selected "Yes", False if selected "No" or "None" on cancel/dialog closing. rrrr.rrrrrzUserInterface.ui_question_yesnocCr)mShow an question with predefined choices. options is a list of strings to present. If multiple is True, they should be check boxes, if multiple is False they should be radio buttons. Return list of selected option indexes, or None if the user cancelled. If multiple == False, the list will always have one element. rrrr.rmultiplerrrr,s z UserInterface.ui_question_choicecCr)mShow a file selector dialog. Return path if the user selected a file, or None if cancelled. rrrrrrui_question_filerzUserInterface.ui_question_filecCr)zRequest username and password from user. message is the text to be presented to the user when requesting for username and password information. Return a tuple (username, password), or None if cancelled. rr)rrrrrrrz"UserInterface.ui_question_userpass)Tr)NFN)TN)1__name__ __module__ __qualname____doc__rrrrrrrr r"rr3rGrVrrsrxryrrrrrrrrrrr rrrrrrrrrrrrr}rr,r rrrrrrsd 6f / nR1 ?r   h%I%%    rc@sJeZdZdZddZddZddZdd d Zd d Zd dZ ddZ dS)ragInteractive functions which can be used in package hooks. This provides an interface for package hooks which need to ask interactive questions. Directly passing the UserInterface instance to the hooks needs to be avoided, since we need to call the UI methods in a different thread, and also don't want hooks to be able to poke in the UI. cCs0||_t|_t|_d|_d|_d|_dS)zSCreate a HookUI object. ui is the UserInterface instance to wrap. N)r threadingEvent_request_event_response_event _request_fn _request_args _response)rrrrrrs    zHookUI.__init__cCs|dd|S)zShow an information with OK/Cancel buttons. This can be used for asking the user to perform a particular action, such as plugging in a device which does not work. rr_trigger_ui_requestrrrr informationszHookUI.informationcC |d|S)rrr,rrrryesnos z HookUI.yesnoFcCs|d|||S)rr,r,rrrrchoices z HookUI.choicecCr/)rr r,rrrrfile s z HookUI.filecGsf|jrJ|jrJ|jdusJd|_||_||_|j|jd|_|j|jS)z5Called by HookUi functions in info collection thread.N) r'is_setr(r)r+r*setrr)rfnrKrrrr-s   zHookUI._trigger_ui_requestcCsV|jd|js dS|jrJ|jt|j|j|j|_ |j dS)z;Called by GUI thread to check and process hook UI requests.rN) r'rr3r(rgetattrrr)r*r+r4rrrrr*s   zHookUI.process_eventN)F) r!r"r#r$rr.r0r1r2r-rrrrrrs   rr)NF)8r$r&ros.pathr#rPrr rrrrdrr rXr/r%rrrrtypingrAapport.fileutilsapport.REThreadapport.crashdbrrapport.user_grouprrr rr configparserr>rr$rr'rrr Optionalrr'r5rrHr+boolrbrgrrrrrrrszH         (  yB