1 from Plugins.Plugin import PluginDescriptor
2 from Components.config import config, getConfigListEntry, ConfigSubsection, ConfigText, ConfigSelection, ConfigYesNo,ConfigText
3 from Components.ConfigList import ConfigListScreen
4 from Components.ActionMap import ActionMap
5 from Components.Label import Label
6 from Components.Pixmap import Pixmap
7 from Screens.Screen import Screen
8 from Screens.VirtualKeyBoard import VirtualKeyBoard
9 from Screens.ChoiceBox import ChoiceBox
10 from Screens.MessageBox import MessageBox
11 from enigma import ePoint
14 from twisted.mail import smtp, relaymanager
15 import MimeWriter, mimetools, StringIO
17 config.plugins.crashlogautosubmit = ConfigSubsection()
18 config.plugins.crashlogautosubmit.sendmail = ConfigSelection(default = "send", choices = [
19 ("send", _("Always ask before sending")), ("send_always", _("Don't ask, just send")), ("send_never", _("Disable crashlog reporting"))])
20 config.plugins.crashlogautosubmit.sendlog = ConfigSelection(default = "rename", choices = [
21 ("delete", _("Delete crashlogs")), ("rename", _("Rename crashlogs"))])
22 config.plugins.crashlogautosubmit.attachemail = ConfigYesNo(default = False)
23 config.plugins.crashlogautosubmit.email = ConfigText(default = "myemail@home.com", fixed_size = False)
24 config.plugins.crashlogautosubmit.name = ConfigText(default = "Dreambox User", fixed_size = False)
25 config.plugins.crashlogautosubmit.sendAnonCrashlog = ConfigYesNo(default = False)
26 config.plugins.crashlogautosubmit.addNetwork = ConfigYesNo(default = False)
27 config.plugins.crashlogautosubmit.addWlan = ConfigYesNo(default = False)
29 class CrashlogAutoSubmitConfiguration(Screen, ConfigListScreen):
31 oldMailEntryValue = config.plugins.crashlogautosubmit.sendmail.value
34 <screen name="CrashlogAutoSubmitConfiguration" position="80,80" size="560,400" title="CrashlogAutoSubmit settings..." >
35 <widget name="config" zPosition="2" position="5,5" size="550,360" scrollbarMode="showOnDemand" transparent="1" />
36 <ePixmap pixmap="skin_default/div-h.png" position="0,300" zPosition="10" size="560,2" transparent="1" alphatest="on" />
37 <widget name="status" position="10,300" zPosition="10" size="540,50" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
38 <ePixmap pixmap="skin_default/buttons/red.png" position="0,360" zPosition="2" size="140,40" transparent="1" alphatest="on" />
39 <widget name="closetext" position="0,360" zPosition="10" size="140,40" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
40 <ePixmap pixmap="skin_default/buttons/green.png" position="140,360" zPosition="2" size="140,40" transparent="1" alphatest="on" />
41 <widget name="installtext" position="140,360" zPosition="10" size="140,40" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
42 <widget name="VKeyButton" pixmap="skin_default/buttons/button_yellow.png" position="285,370" zPosition="2" size="15,16" transparent="1" alphatest="on" />
43 <widget name="VKeyIcon" pixmap="skin_default/vkey_icon.png" position="300,355" zPosition="10" size="60,48" transparent="1" alphatest="on" />
44 <widget name="HelpWindow" position="175,250" zPosition="1" size="1,1" transparent="1" />
47 def __init__(self, session):
48 Screen.__init__(self, session)
49 self.session = session
52 self.addEmailEntry = None
53 self.EmailEntry = None
55 self.AnonCrashlogEntry = None
56 self.NetworkEntry = None
58 self.msgCrashlogMailer = False
60 self["shortcuts"] = ActionMap(["ShortcutActions", "SetupActions" ],
63 "cancel": self.keyCancel,
64 "red": self.keyCancel,
65 "green": self.keySave,
68 self["VirtualKB"] = ActionMap(["ColorActions" ],
70 "yellow": self.KeyYellow,
74 ConfigListScreen.__init__(self, self.list,session = self.session)
77 self["VKeyButton"] = Pixmap()
78 self["VKeyIcon"] = Pixmap()
79 self["closetext"] = Label(_("Close"))
80 self["installtext"] = Label(_("Save"))
81 self["HelpWindow"] = Label()
82 self["status"] = Label()
84 self["VKeyButton"].hide()
85 self["VKeyIcon"].hide()
86 self["VirtualKB"].setEnabled(False)
87 self.onShown.append(self.setWindowTitle)
88 self.onClose.append(self.msgCrashlogNotifier)
91 def setWindowTitle(self):
92 self.setTitle(_("CrashlogAutoSubmit settings..."))
95 ConfigListScreen.keyLeft(self)
99 ConfigListScreen.keyRight(self)
103 if self["config"].getCurrent() == self.EmailEntry:
104 self.session.openWithCallback(self.EmailCallback, VirtualKeyBoard, title = (_("Please enter your email address here:")), text = config.plugins.crashlogautosubmit.email.value)
105 if self["config"].getCurrent() == self.NameEntry:
106 self.session.openWithCallback(self.NameCallback, VirtualKeyBoard, title = (_("Please enter your name here (optional):")), text = config.plugins.crashlogautosubmit.name.value)
108 def EmailCallback(self, callback = None):
109 if callback is not None and len(callback):
110 config.plugins.crashlogautosubmit.email.setValue(callback)
111 self["config"].invalidate(self.EmailEntry)
113 def NameCallback(self, callback = None):
114 if callback is not None and len(callback):
115 config.plugins.crashlogautosubmit.name.setValue(callback)
116 self["config"].invalidate(self.NameEntry)
118 def createSetup(self):
120 self.MailEntry = getConfigListEntry(_("How to handle found crashlogs?"), config.plugins.crashlogautosubmit.sendmail)
121 self.LogEntry = getConfigListEntry(_("What to do with submitted crashlogs?"), config.plugins.crashlogautosubmit.sendlog)
122 self.addEmailEntry = getConfigListEntry(_("Include your email and name (optional) in the mail?"), config.plugins.crashlogautosubmit.attachemail)
123 self.EmailEntry = getConfigListEntry(_("Your email address:"), config.plugins.crashlogautosubmit.email)
124 self.NameEntry = getConfigListEntry(_("Your name (optional):"), config.plugins.crashlogautosubmit.name)
125 self.AnonCrashlogEntry = getConfigListEntry(_("Anonymize crashlog?"), config.plugins.crashlogautosubmit.sendAnonCrashlog)
126 self.NetworkEntry = getConfigListEntry(_("Add network configuration?"), config.plugins.crashlogautosubmit.addNetwork)
127 self.WlanEntry = getConfigListEntry(_("Add WLAN configuration?"), config.plugins.crashlogautosubmit.addWlan)
129 self.list.append( self.MailEntry )
130 if config.plugins.crashlogautosubmit.sendmail.value is not "send_never":
131 self.list.append( self.LogEntry )
132 self.list.append( self.addEmailEntry )
133 if config.plugins.crashlogautosubmit.attachemail.value is True:
134 self.list.append( self.EmailEntry )
135 self.list.append( self.NameEntry )
136 self.list.append( self.AnonCrashlogEntry )
137 self.list.append( self.NetworkEntry )
138 self.list.append( self.WlanEntry )
140 self["config"].list = self.list
141 self["config"].l.setList(self.list)
142 if not self.selectionChanged in self["config"].onSelectionChanged:
143 self["config"].onSelectionChanged.append(self.selectionChanged)
145 if not self.sendmailChanged in config.plugins.crashlogautosubmit.sendmail.notifiers:
146 config.plugins.crashlogautosubmit.sendmail.notifiers.append(self.sendmailChanged)
148 def sendmailChanged(self, configElement):
149 if configElement.value != CrashlogAutoSubmitConfiguration.oldMailEntryValue:
150 self.msgCrashlogMailer = True
152 self.msgCrashlogMailer = False
155 if self["config"].getCurrent() == self.MailEntry:
157 if self["config"].getCurrent() == self.addEmailEntry:
160 def selectionChanged(self):
161 current = self["config"].getCurrent()
162 if current == self.MailEntry:
163 self["status"].setText(_("Decide what should be done when crashlogs are found."))
164 self.disableVKeyIcon()
165 elif current == self.LogEntry:
166 self["status"].setText(_("Decide what should happen to the crashlogs after submission."))
167 self.disableVKeyIcon()
168 elif current == self.addEmailEntry:
169 self["status"].setText(_("Do you want to submit your email address and name so that we can contact you if needed?"))
170 self.disableVKeyIcon()
171 elif current == self.EmailEntry:
172 self["status"].setText(_("Enter your email address so that we can contact you if needed."))
173 self.enableVKeyIcon()
175 elif current == self.NameEntry:
176 self["status"].setText(_("Optionally enter your name if you want to."))
177 self.enableVKeyIcon()
179 elif current == self.AnonCrashlogEntry:
180 self["status"].setText(_("Adds enigma2 settings and dreambox model informations like SN, rev... if enabled."))
181 self.disableVKeyIcon()
182 elif current == self.NetworkEntry:
183 self["status"].setText(_("Adds network configuration if enabled."))
184 self.disableVKeyIcon()
185 elif current == self.WlanEntry:
186 self["status"].setText(_("Adds wlan configuration if enabled."))
187 self.disableVKeyIcon()
189 def enableVKeyIcon(self):
190 self["VKeyButton"].show()
191 self["VKeyIcon"].show()
192 self["VirtualKB"].setEnabled(True)
194 def showKeypad(self):
195 current = self["config"].getCurrent()
196 helpwindowpos = self["HelpWindow"].getPosition()
197 if hasattr(current[1], 'help_window'):
198 if current[1].help_window.instance is not None:
199 current[1].help_window.instance.show()
200 current[1].help_window.instance.move(ePoint(helpwindowpos[0],helpwindowpos[1]))
202 def disableVKeyIcon(self):
203 self["VKeyButton"].hide()
204 self["VKeyIcon"].hide()
205 self["VirtualKB"].setEnabled(False)
207 def hideKeypad(self):
208 current = self["config"].getCurrent()
209 if hasattr(current[1], 'help_window'):
210 if current[1].help_window.instance is not None:
211 current[1].help_window.instance.hide()
213 def cancelConfirm(self, result):
217 for x in self["config"].list:
223 if self["config"].isChanged():
225 self.session.openWithCallback(self.cancelConfirm, MessageBox, _("Really close without saving settings?"))
231 CrashlogAutoSubmitConfiguration.oldMailEntryValue = config.plugins.crashlogautosubmit.sendmail.value
232 ConfigListScreen.keySave(self)
234 def msgCrashlogNotifier(self):
235 if self.msgCrashlogMailer is True:
237 callCrashMailer(True, self.session)
238 except AttributeError:
239 print "error, not restarting crashlogmailer"
242 def mxServerFound(mxServer,session):
243 print "[CrashlogAutoSubmit] - mxServerFound -->", mxServer
244 crashLogFilelist = []
245 message = StringIO.StringIO()
246 writer = MimeWriter.MimeWriter(message)
247 mailFrom = "enigma2@crashlog.dream-multimedia-tv.de"
248 mailTo = "enigma2@crashlog.dream-multimedia-tv.de"
249 subject = "Automatically generated crashlogmail"
250 # Define the main body headers.
251 writer.addheader('To', "dream-multimedia-crashlogs <enigma2@crashlog.dream-multimedia-tv.de>")
252 writer.addheader('From', "CrashlogAutoSubmitter <enigma2@crashlog.dream-multimedia-tv.de>")
253 writer.addheader('Subject', str(subject))
254 writer.addheader('Date', smtp.rfc822date())
255 if config.plugins.crashlogautosubmit.attachemail.value is True:
256 if str(config.plugins.crashlogautosubmit.email.value) != "myemail@home.com":
257 writer.addheader('Reply-To', str(str(config.plugins.crashlogautosubmit.email.value)))
258 writer.addheader('MIME-Version', '1.0')
259 writer.startmultipartbody('mixed')
260 # start with a text/plain part
261 part = writer.nextpart()
262 body = part.startbody('text/plain')
264 # Define the message body
265 body_text1 = "\nHello\n\nHere are some crashlogs i found for you.\n"
266 if str(config.plugins.crashlogautosubmit.email.value) == "myemail@home.com":
269 user_email = "\nUser supplied email address: " + str(config.plugins.crashlogautosubmit.email.value)
270 if str(config.plugins.crashlogautosubmit.name.value) == "Dreambox User":
273 user_name = "\n\nOptional supplied name: " + str(config.plugins.crashlogautosubmit.name.value)
274 body_text2 = "\n\nThis is an automatically generated email from the CrashlogAutoSubmit plugin.\n\n\nHave a nice day.\n"
275 body_text = body_text1 + user_email + user_name + body_text2
276 body.write(body_text)
280 (_("Yes, and don't ask again"), "send_always"),
281 (_("No, not now"), "send_not"),
282 (_("No, send them never"), "send_never")
285 def handleError(error):
286 print "[CrashlogAutoSubmit] - Message send Error -->", error.getErrorMessage()
288 def handleSuccess(result):
289 print "[CrashlogAutoSubmit] - Message sent successfully -->",result
290 if len(crashLogFilelist):
291 for crashlog in crashLogFilelist:
292 if config.plugins.crashlogautosubmit.sendlog.value == "delete":
294 elif config.plugins.crashlogautosubmit.sendlog.value == "rename":
295 currfilename = str(os.path.basename(crashlog))
296 newfilename = "/media/hdd/" + currfilename + ".sent"
297 os.rename(crashlog,newfilename)
300 print "[CrashlogAutoSubmit] - send_mail"
301 if len(crashLogFilelist):
302 for crashlog in crashLogFilelist:
303 filename = str(os.path.basename(crashlog))
304 subpart = writer.nextpart()
305 subpart.addheader("Content-Transfer-Encoding", 'base64')
306 subpart.addheader("Content-Disposition",'attachment; filename="%s"' % filename)
307 subpart.addheader('Content-Description', 'Enigma2 crashlog')
308 body = subpart.startbody("%s; name=%s" % ('application/octet-stream', filename))
309 mimetools.encode(open(crashlog, 'rb'), body, 'base64')
311 sending = smtp.sendmail(str(mxServer), mailFrom, mailTo, message.getvalue())
312 sending.addCallback(handleSuccess).addErrback(handleError)
314 def handleAnswer(answer):
315 answer = answer and answer[1]
316 print "[CrashlogAutoSubmit] - handleAnswer --> ",answer
319 elif answer == "send_always":
320 config.plugins.crashlogautosubmit.sendmail.value = "send_always"
321 config.plugins.crashlogautosubmit.sendmail.save()
322 config.plugins.crashlogautosubmit.save()
323 config.plugins.save()
326 elif answer in ( None, "send_never"):
327 config.plugins.crashlogautosubmit.sendmail.value = "send_never"
328 config.plugins.crashlogautosubmit.sendmail.save()
329 config.plugins.crashlogautosubmit.save()
330 config.plugins.save()
332 elif answer == "send_not":
333 print "[CrashlogAutoSubmit] - not sending crashlogs for this time."
335 for crashlog in os.listdir('/media/hdd'):
336 if crashlog.startswith("enigma2_crash_") and crashlog.endswith(".log"):
337 print "[CrashlogAutoSubmit] - found crashlog: ",os.path.basename(crashlog)
338 crashLogFilelist.append('/media/hdd/' + crashlog)
340 if len(crashLogFilelist):
341 if config.plugins.crashlogautosubmit.sendmail.value == "send":
342 session.openWithCallback(handleAnswer, ChoiceBox, title=_("Crashlogs found!\nSend them to Dream Multimedia ?"), list = list)
343 elif config.plugins.crashlogautosubmit.sendmail.value == "send_always":
346 print "[CrashlogAutoSubmit] - no crashlogs found."
349 def getMailExchange(host):
350 print "[CrashlogAutoSubmit] - getMailExchange"
351 return relaymanager.MXCalculator().getMX(host).addCallback(_gotMXRecord)
353 def _gotMXRecord(mxRecord):
354 return str(mxRecord.name)
357 def startMailer(session):
358 if config.plugins.crashlogautosubmit.sendmail.value == "send_never":
359 print "[CrashlogAutoSubmit] - not starting CrashlogAutoSubmit"
362 def gotMXServer(mxServer):
363 print "[CrashlogAutoSubmit] gotMXServer: ",mxServer
364 mxServerFound(mxServer,session)
366 def handleMXError(error):
367 print "[CrashlogAutoSubmit] - MX resolve ERROR:", error.getErrorMessage()
369 if not config.misc.firstrun.value:
370 getMailExchange('crashlog.dream-multimedia-tv.de').addCallback(gotMXServer).addErrback(handleMXError)
373 def callCrashMailer(result,session):
375 print "[CrashlogAutoSubmit] - config changed"
378 print "[CrashlogAutoSubmit] - config not changed"
381 def autostart(reason, **kwargs):
382 print "[CrashlogAutoSubmit] - autostart"
383 if "session" in kwargs:
385 startMailer(kwargs["session"])
386 except ImportError, e:
387 print "[CrashlogAutoSubmit] Twisted-mail not available, not starting CrashlogAutoSubmitter", e
390 def openconfig(session, **kwargs):
391 session.open(CrashlogAutoSubmitConfiguration)
394 def selSetup(menuid, **kwargs):
395 if menuid != "system":
398 return [(_("Crashlog settings") + "...", openconfig, "crashlog_config", 70)]
401 def Plugins(**kwargs):
402 return [PluginDescriptor(where = [PluginDescriptor.WHERE_SESSIONSTART, PluginDescriptor.WHERE_AUTOSTART], fnc = autostart),
403 PluginDescriptor(name=_("CrashlogAutoSubmit"), description=_("CrashlogAutoSubmit settings"),where=PluginDescriptor.WHERE_MENU, fnc=selSetup)]