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
12 from Tools import Notifications
15 from twisted.mail import smtp, relaymanager
16 import MimeWriter, mimetools, StringIO
18 config.plugins.crashlogautosubmit = ConfigSubsection()
19 config.plugins.crashlogautosubmit.sendmail = ConfigSelection(default = "send", choices = [
20 ("send", _("Always ask before sending")), ("send_always", _("Don't ask, just send")), ("send_never", _("Disable crashlog reporting"))])
21 config.plugins.crashlogautosubmit.sendlog = ConfigSelection(default = "rename", choices = [
22 ("delete", _("Delete crashlogs")), ("rename", _("Rename crashlogs"))])
23 config.plugins.crashlogautosubmit.attachemail = ConfigYesNo(default = False)
24 config.plugins.crashlogautosubmit.email = ConfigText(default = "myemail@home.com", fixed_size = False)
25 config.plugins.crashlogautosubmit.name = ConfigText(default = "Dreambox User", fixed_size = False)
26 config.plugins.crashlogautosubmit.sendAnonCrashlog = ConfigYesNo(default = False)
27 config.plugins.crashlogautosubmit.addNetwork = ConfigYesNo(default = False)
28 config.plugins.crashlogautosubmit.addWlan = ConfigYesNo(default = False)
30 class CrashlogAutoSubmitConfiguration(Screen, ConfigListScreen):
32 oldMailEntryValue = config.plugins.crashlogautosubmit.sendmail.value
35 <screen name="CrashlogAutoSubmitConfiguration" position="80,80" size="560,400" title="CrashlogAutoSubmit settings..." >
36 <widget name="config" zPosition="2" position="5,5" size="550,360" scrollbarMode="showOnDemand" transparent="1" />
37 <ePixmap pixmap="skin_default/div-h.png" position="0,300" zPosition="10" size="560,2" transparent="1" alphatest="on" />
38 <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" />
39 <ePixmap pixmap="skin_default/buttons/red.png" position="0,360" zPosition="2" size="140,40" transparent="1" alphatest="on" />
40 <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" />
41 <ePixmap pixmap="skin_default/buttons/green.png" position="140,360" zPosition="2" size="140,40" transparent="1" alphatest="on" />
42 <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" />
43 <widget name="VKeyButton" pixmap="skin_default/buttons/button_yellow.png" position="285,370" zPosition="2" size="15,16" transparent="1" alphatest="on" />
44 <widget name="VKeyIcon" pixmap="skin_default/vkey_icon.png" position="300,355" zPosition="10" size="60,48" transparent="1" alphatest="on" />
45 <widget name="HelpWindow" position="175,250" zPosition="1" size="1,1" transparent="1" />
48 def __init__(self, session):
49 Screen.__init__(self, session)
50 self.session = session
53 self.addEmailEntry = None
54 self.EmailEntry = None
56 self.AnonCrashlogEntry = None
57 self.NetworkEntry = None
59 self.msgCrashlogMailer = False
61 self["shortcuts"] = ActionMap(["ShortcutActions", "SetupActions" ],
64 "cancel": self.keyCancel,
65 "red": self.keyCancel,
66 "green": self.keySave,
69 self["VirtualKB"] = ActionMap(["ColorActions" ],
71 "yellow": self.KeyYellow,
75 ConfigListScreen.__init__(self, self.list,session = self.session)
78 self["VKeyButton"] = Pixmap()
79 self["VKeyIcon"] = Pixmap()
80 self["closetext"] = Label(_("Close"))
81 self["installtext"] = Label(_("Save"))
82 self["HelpWindow"] = Label()
83 self["status"] = Label()
85 self["VKeyButton"].hide()
86 self["VKeyIcon"].hide()
87 self["VirtualKB"].setEnabled(False)
88 self.onShown.append(self.setWindowTitle)
89 self.onClose.append(self.msgCrashlogNotifier)
92 def setWindowTitle(self):
93 self.setTitle(_("CrashlogAutoSubmit settings..."))
96 ConfigListScreen.keyLeft(self)
100 ConfigListScreen.keyRight(self)
104 if self["config"].getCurrent() == self.EmailEntry:
105 self.session.openWithCallback(self.EmailCallback, VirtualKeyBoard, title = (_("Please enter your email address here:")), text = config.plugins.crashlogautosubmit.email.value)
106 if self["config"].getCurrent() == self.NameEntry:
107 self.session.openWithCallback(self.NameCallback, VirtualKeyBoard, title = (_("Please enter your name here (optional):")), text = config.plugins.crashlogautosubmit.name.value)
109 def EmailCallback(self, callback = None):
110 if callback is not None and len(callback):
111 config.plugins.crashlogautosubmit.email.setValue(callback)
112 self["config"].invalidate(self.EmailEntry)
114 def NameCallback(self, callback = None):
115 if callback is not None and len(callback):
116 config.plugins.crashlogautosubmit.name.setValue(callback)
117 self["config"].invalidate(self.NameEntry)
119 def createSetup(self):
121 self.MailEntry = getConfigListEntry(_("How to handle found crashlogs?"), config.plugins.crashlogautosubmit.sendmail)
122 self.LogEntry = getConfigListEntry(_("What to do with submitted crashlogs?"), config.plugins.crashlogautosubmit.sendlog)
123 self.addEmailEntry = getConfigListEntry(_("Include your email and name (optional) in the mail?"), config.plugins.crashlogautosubmit.attachemail)
124 self.EmailEntry = getConfigListEntry(_("Your email address:"), config.plugins.crashlogautosubmit.email)
125 self.NameEntry = getConfigListEntry(_("Your name (optional):"), config.plugins.crashlogautosubmit.name)
126 self.AnonCrashlogEntry = getConfigListEntry(_("Anonymize crashlog?"), config.plugins.crashlogautosubmit.sendAnonCrashlog)
127 self.NetworkEntry = getConfigListEntry(_("Add network configuration?"), config.plugins.crashlogautosubmit.addNetwork)
128 self.WlanEntry = getConfigListEntry(_("Add WLAN configuration?"), config.plugins.crashlogautosubmit.addWlan)
130 self.list.append( self.MailEntry )
131 if config.plugins.crashlogautosubmit.sendmail.value is not "send_never":
132 self.list.append( self.LogEntry )
133 self.list.append( self.addEmailEntry )
134 if config.plugins.crashlogautosubmit.attachemail.value is True:
135 self.list.append( self.EmailEntry )
136 self.list.append( self.NameEntry )
137 self.list.append( self.AnonCrashlogEntry )
138 self.list.append( self.NetworkEntry )
139 self.list.append( self.WlanEntry )
141 self["config"].list = self.list
142 self["config"].l.setList(self.list)
143 if not self.selectionChanged in self["config"].onSelectionChanged:
144 self["config"].onSelectionChanged.append(self.selectionChanged)
146 if not self.sendmailChanged in config.plugins.crashlogautosubmit.sendmail.notifiers:
147 config.plugins.crashlogautosubmit.sendmail.notifiers.append(self.sendmailChanged)
149 def sendmailChanged(self, configElement):
150 if configElement.value != CrashlogAutoSubmitConfiguration.oldMailEntryValue:
151 self.msgCrashlogMailer = True
153 self.msgCrashlogMailer = False
156 if self["config"].getCurrent() == self.MailEntry:
158 if self["config"].getCurrent() == self.addEmailEntry:
161 def selectionChanged(self):
162 current = self["config"].getCurrent()
163 if current == self.MailEntry:
164 self["status"].setText(_("Decide what should be done when crashlogs are found."))
165 self.disableVKeyIcon()
166 elif current == self.LogEntry:
167 self["status"].setText(_("Decide what should happen to the crashlogs after submission."))
168 self.disableVKeyIcon()
169 elif current == self.addEmailEntry:
170 self["status"].setText(_("Do you want to submit your email address and name so that we can contact you if needed?"))
171 self.disableVKeyIcon()
172 elif current == self.EmailEntry:
173 self["status"].setText(_("Enter your email address so that we can contact you if needed."))
174 self.enableVKeyIcon()
176 elif current == self.NameEntry:
177 self["status"].setText(_("Optionally enter your name if you want to."))
178 self.enableVKeyIcon()
180 elif current == self.AnonCrashlogEntry:
181 self["status"].setText(_("Adds enigma2 settings and dreambox model informations like SN, rev... if enabled."))
182 self.disableVKeyIcon()
183 elif current == self.NetworkEntry:
184 self["status"].setText(_("Adds network configuration if enabled."))
185 self.disableVKeyIcon()
186 elif current == self.WlanEntry:
187 self["status"].setText(_("Adds wlan configuration if enabled."))
188 self.disableVKeyIcon()
190 def enableVKeyIcon(self):
191 self["VKeyButton"].show()
192 self["VKeyIcon"].show()
193 self["VirtualKB"].setEnabled(True)
195 def showKeypad(self):
196 current = self["config"].getCurrent()
197 helpwindowpos = self["HelpWindow"].getPosition()
198 if hasattr(current[1], 'help_window'):
199 if current[1].help_window.instance is not None:
200 current[1].help_window.instance.show()
201 current[1].help_window.instance.move(ePoint(helpwindowpos[0],helpwindowpos[1]))
203 def disableVKeyIcon(self):
204 self["VKeyButton"].hide()
205 self["VKeyIcon"].hide()
206 self["VirtualKB"].setEnabled(False)
208 def hideKeypad(self):
209 current = self["config"].getCurrent()
210 if hasattr(current[1], 'help_window'):
211 if current[1].help_window.instance is not None:
212 current[1].help_window.instance.hide()
214 def cancelConfirm(self, result):
218 for x in self["config"].list:
224 if self["config"].isChanged():
226 self.session.openWithCallback(self.cancelConfirm, MessageBox, _("Really close without saving settings?"))
232 CrashlogAutoSubmitConfiguration.oldMailEntryValue = config.plugins.crashlogautosubmit.sendmail.value
233 ConfigListScreen.keySave(self)
235 def msgCrashlogNotifier(self):
236 if self.msgCrashlogMailer is True:
238 callCrashMailer(True, self.session)
239 except AttributeError:
240 print "error, not restarting crashlogmailer"
243 def mxServerFound(mxServer,session):
244 print "[CrashlogAutoSubmit] - mxServerFound -->", mxServer
245 crashLogFilelist = []
246 message = StringIO.StringIO()
247 writer = MimeWriter.MimeWriter(message)
248 mailFrom = "enigma2@crashlog.dream-multimedia-tv.de"
249 mailTo = "enigma2@crashlog.dream-multimedia-tv.de"
250 subject = "Automatically generated crashlogmail"
251 # Define the main body headers.
252 writer.addheader('To', "dream-multimedia-crashlogs <enigma2@crashlog.dream-multimedia-tv.de>")
253 writer.addheader('From', "CrashlogAutoSubmitter <enigma2@crashlog.dream-multimedia-tv.de>")
254 writer.addheader('Subject', str(subject))
255 writer.addheader('Date', smtp.rfc822date())
256 if config.plugins.crashlogautosubmit.attachemail.value is True:
257 if str(config.plugins.crashlogautosubmit.email.value) != "myemail@home.com":
258 writer.addheader('Reply-To', str(str(config.plugins.crashlogautosubmit.email.value)))
259 writer.addheader('MIME-Version', '1.0')
260 writer.startmultipartbody('mixed')
261 # start with a text/plain part
262 part = writer.nextpart()
263 body = part.startbody('text/plain')
265 # Define the message body
266 body_text1 = "\nHello\n\nHere are some crashlogs i found for you.\n"
267 if str(config.plugins.crashlogautosubmit.email.value) == "myemail@home.com":
270 user_email = "\nUser supplied email address: " + str(config.plugins.crashlogautosubmit.email.value)
271 if str(config.plugins.crashlogautosubmit.name.value) == "Dreambox User":
274 user_name = "\n\nOptional supplied name: " + str(config.plugins.crashlogautosubmit.name.value)
275 body_text2 = "\n\nThis is an automatically generated email from the CrashlogAutoSubmit plugin.\n\n\nHave a nice day.\n"
276 body_text = body_text1 + user_email + user_name + body_text2
277 body.write(body_text)
281 (_("Yes, and don't ask again"), "send_always"),
282 (_("No, not now"), "send_not"),
283 (_("No, send them never"), "send_never")
286 def handleError(error):
287 print "[CrashlogAutoSubmit] - Message send Error -->", error.getErrorMessage()
289 def handleSuccess(result):
290 print "[CrashlogAutoSubmit] - Message sent successfully -->",result
291 if len(crashLogFilelist):
292 for crashlog in crashLogFilelist:
293 if config.plugins.crashlogautosubmit.sendlog.value == "delete":
295 elif config.plugins.crashlogautosubmit.sendlog.value == "rename":
296 currfilename = str(os.path.basename(crashlog))
297 newfilename = "/media/hdd/" + currfilename + ".sent"
298 os.rename(crashlog,newfilename)
301 print "[CrashlogAutoSubmit] - send_mail"
302 if len(crashLogFilelist):
303 for crashlog in crashLogFilelist:
304 filename = str(os.path.basename(crashlog))
305 subpart = writer.nextpart()
306 subpart.addheader("Content-Transfer-Encoding", 'base64')
307 subpart.addheader("Content-Disposition",'attachment; filename="%s"' % filename)
308 subpart.addheader('Content-Description', 'Enigma2 crashlog')
309 body = subpart.startbody("%s; name=%s" % ('application/octet-stream', filename))
310 mimetools.encode(open(crashlog, 'rb'), body, 'base64')
312 sending = smtp.sendmail(str(mxServer), mailFrom, mailTo, message.getvalue())
313 sending.addCallback(handleSuccess).addErrback(handleError)
315 def handleAnswer(answer):
316 answer = answer and answer[1]
317 print "[CrashlogAutoSubmit] - handleAnswer --> ",answer
320 elif answer == "send_always":
321 config.plugins.crashlogautosubmit.sendmail.value = "send_always"
322 config.plugins.crashlogautosubmit.sendmail.save()
323 config.plugins.crashlogautosubmit.save()
324 config.plugins.save()
327 elif answer in ( None, "send_never"):
328 config.plugins.crashlogautosubmit.sendmail.value = "send_never"
329 config.plugins.crashlogautosubmit.sendmail.save()
330 config.plugins.crashlogautosubmit.save()
331 config.plugins.save()
333 elif answer == "send_not":
334 print "[CrashlogAutoSubmit] - not sending crashlogs for this time."
336 for crashlog in os.listdir('/media/hdd'):
337 if crashlog.startswith("enigma2_crash_") and crashlog.endswith(".log"):
338 print "[CrashlogAutoSubmit] - found crashlog: ",os.path.basename(crashlog)
339 crashLogFilelist.append('/media/hdd/' + crashlog)
341 if len(crashLogFilelist):
342 if config.plugins.crashlogautosubmit.sendmail.value == "send":
343 Notifications.AddNotificationWithCallback(handleAnswer, ChoiceBox, title=_("Crashlogs found!\nSend them to Dream Multimedia?"), list = list)
344 elif config.plugins.crashlogautosubmit.sendmail.value == "send_always":
347 print "[CrashlogAutoSubmit] - no crashlogs found."
350 def getMailExchange(host):
351 print "[CrashlogAutoSubmit] - getMailExchange"
352 return relaymanager.MXCalculator().getMX(host).addCallback(_gotMXRecord)
354 def _gotMXRecord(mxRecord):
355 return str(mxRecord.name)
358 def startMailer(session):
359 if config.plugins.crashlogautosubmit.sendmail.value == "send_never":
360 print "[CrashlogAutoSubmit] - not starting CrashlogAutoSubmit"
363 def gotMXServer(mxServer):
364 print "[CrashlogAutoSubmit] gotMXServer: ",mxServer
365 mxServerFound(mxServer,session)
367 def handleMXError(error):
368 print "[CrashlogAutoSubmit] - MX resolve ERROR:", error.getErrorMessage()
370 if not config.misc.firstrun.value:
371 getMailExchange('crashlog.dream-multimedia-tv.de').addCallback(gotMXServer).addErrback(handleMXError)
374 def callCrashMailer(result,session):
376 print "[CrashlogAutoSubmit] - config changed"
379 print "[CrashlogAutoSubmit] - config not changed"
382 def autostart(reason, **kwargs):
383 print "[CrashlogAutoSubmit] - autostart"
384 if "session" in kwargs:
386 startMailer(kwargs["session"])
387 except ImportError, e:
388 print "[CrashlogAutoSubmit] Twisted-mail not available, not starting CrashlogAutoSubmitter", e
391 def openconfig(session, **kwargs):
392 session.open(CrashlogAutoSubmitConfiguration)
395 def selSetup(menuid, **kwargs):
396 if menuid != "system":
399 return [(_("Crashlog settings") + "...", openconfig, "crashlog_config", 70)]
402 def Plugins(**kwargs):
403 return [PluginDescriptor(where = [PluginDescriptor.WHERE_SESSIONSTART, PluginDescriptor.WHERE_AUTOSTART], fnc = autostart),
404 PluginDescriptor(name=_("CrashlogAutoSubmit"), description=_("CrashlogAutoSubmit settings"),where=PluginDescriptor.WHERE_MENU, fnc=selSetup)]