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.Sources.StaticText import StaticText
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 = True)
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="center,center" size="560,440" title="CrashlogAutoSubmit settings" >
36 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
37 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
38 <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
39 <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
40 <widget name="config" zPosition="2" position="5,50" size="550,300" scrollbarMode="showOnDemand" transparent="1" />
41 <ePixmap pixmap="skin_default/div-h.png" position="0,390" zPosition="10" size="560,2" transparent="1" alphatest="on" />
42 <widget source="status" render="Label" position="10,400" size="540,40" zPosition="10" font="Regular;20" halign="center" valign="center" backgroundColor="#25062748" transparent="1"/>
43 <widget name="VKeyIcon" pixmap="skin_default/buttons/key_text.png" position="10,420" zPosition="10" size="35,25" transparent="1" alphatest="on" />
44 <widget name="HelpWindow" pixmap="skin_default/vkey_icon.png" position="160,325" zPosition="1" size="1,1" transparent="1" alphatest="on" />
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(["VirtualKeyboardActions" ],
70 "showVirtualKeyboard": self.KeyText,
74 ConfigListScreen.__init__(self, self.list,session = self.session)
77 self["key_red"] = StaticText(_("Close"))
78 self["key_green"] = StaticText(_("Save"))
79 self["status"] = StaticText()
80 self["VKeyIcon"] = Pixmap()
81 self["HelpWindow"] = Pixmap()
83 self["VKeyIcon"].hide()
84 self["VirtualKB"].setEnabled(False)
85 self.onShown.append(self.setWindowTitle)
86 self.onClose.append(self.msgCrashlogNotifier)
89 def setWindowTitle(self):
90 self.setTitle(_("CrashlogAutoSubmit settings..."))
93 ConfigListScreen.keyLeft(self)
97 ConfigListScreen.keyRight(self)
101 if self["config"].getCurrent() == self.EmailEntry:
102 self.session.openWithCallback(self.EmailCallback, VirtualKeyBoard, title = (_("Please enter your email address here:")), text = config.plugins.crashlogautosubmit.email.value)
103 if self["config"].getCurrent() == self.NameEntry:
104 self.session.openWithCallback(self.NameCallback, VirtualKeyBoard, title = (_("Please enter your name here (optional):")), text = config.plugins.crashlogautosubmit.name.value)
106 def EmailCallback(self, callback = None):
107 if callback is not None and len(callback):
108 config.plugins.crashlogautosubmit.email.setValue(callback)
109 self["config"].invalidate(self.EmailEntry)
111 def NameCallback(self, callback = None):
112 if callback is not None and len(callback):
113 config.plugins.crashlogautosubmit.name.setValue(callback)
114 self["config"].invalidate(self.NameEntry)
116 def createSetup(self):
118 self.MailEntry = getConfigListEntry(_("How to handle found crashlogs?"), config.plugins.crashlogautosubmit.sendmail)
119 self.LogEntry = getConfigListEntry(_("What to do with submitted crashlogs?"), config.plugins.crashlogautosubmit.sendlog)
120 self.addEmailEntry = getConfigListEntry(_("Include your email and name (optional) in the mail?"), config.plugins.crashlogautosubmit.attachemail)
121 self.EmailEntry = getConfigListEntry(_("Your email address:"), config.plugins.crashlogautosubmit.email)
122 self.NameEntry = getConfigListEntry(_("Your name (optional):"), config.plugins.crashlogautosubmit.name)
123 self.AnonCrashlogEntry = getConfigListEntry(_("Anonymize crashlog?"), config.plugins.crashlogautosubmit.sendAnonCrashlog)
124 self.NetworkEntry = getConfigListEntry(_("Add network configuration?"), config.plugins.crashlogautosubmit.addNetwork)
125 self.WlanEntry = getConfigListEntry(_("Add WLAN configuration?"), config.plugins.crashlogautosubmit.addWlan)
127 self.list.append( self.MailEntry )
128 if config.plugins.crashlogautosubmit.sendmail.value is not "send_never":
129 self.list.append( self.LogEntry )
130 self.list.append( self.addEmailEntry )
131 if config.plugins.crashlogautosubmit.attachemail.value is True:
132 self.list.append( self.EmailEntry )
133 self.list.append( self.NameEntry )
134 self.list.append( self.AnonCrashlogEntry )
135 self.list.append( self.NetworkEntry )
136 self.list.append( self.WlanEntry )
138 self["config"].list = self.list
139 self["config"].l.setList(self.list)
140 if not self.selectionChanged in self["config"].onSelectionChanged:
141 self["config"].onSelectionChanged.append(self.selectionChanged)
143 if not self.sendmailChanged in config.plugins.crashlogautosubmit.sendmail.notifiers:
144 config.plugins.crashlogautosubmit.sendmail.notifiers.append(self.sendmailChanged)
146 def sendmailChanged(self, configElement):
147 if configElement.value != CrashlogAutoSubmitConfiguration.oldMailEntryValue:
148 self.msgCrashlogMailer = True
150 self.msgCrashlogMailer = False
153 if self["config"].getCurrent() == self.MailEntry:
155 if self["config"].getCurrent() == self.addEmailEntry:
158 def selectionChanged(self):
159 current = self["config"].getCurrent()
160 if current == self.MailEntry:
161 self["status"].setText(_("Decide what should be done when crashlogs are found."))
162 self.disableVKeyIcon()
163 elif current == self.LogEntry:
164 self["status"].setText(_("Decide what should happen to the crashlogs after submission."))
165 self.disableVKeyIcon()
166 elif current == self.addEmailEntry:
167 self["status"].setText(_("Do you want to submit your email address and name so that we can contact you if needed?"))
168 self.disableVKeyIcon()
169 elif current == self.EmailEntry:
170 self["status"].setText(_("Enter your email address so that we can contact you if needed."))
171 self.enableVKeyIcon()
173 elif current == self.NameEntry:
174 self["status"].setText(_("Optionally enter your name if you want to."))
175 self.enableVKeyIcon()
177 elif current == self.AnonCrashlogEntry:
178 self["status"].setText(_("Adds enigma2 settings and dreambox model informations like SN, rev... if enabled."))
179 self.disableVKeyIcon()
180 elif current == self.NetworkEntry:
181 self["status"].setText(_("Adds network configuration if enabled."))
182 self.disableVKeyIcon()
183 elif current == self.WlanEntry:
184 self["status"].setText(_("Adds wlan configuration if enabled."))
185 self.disableVKeyIcon()
187 def enableVKeyIcon(self):
188 self["VKeyIcon"].show()
189 self["VirtualKB"].setEnabled(True)
191 def showKeypad(self):
192 current = self["config"].getCurrent()
193 helpwindowpos = self["HelpWindow"].getPosition()
194 if hasattr(current[1], 'help_window'):
195 if current[1].help_window.instance is not None:
196 current[1].help_window.instance.show()
197 current[1].help_window.instance.move(ePoint(helpwindowpos[0],helpwindowpos[1]))
199 def disableVKeyIcon(self):
200 self["VKeyIcon"].hide()
201 self["VirtualKB"].setEnabled(False)
203 def hideKeypad(self):
204 current = self["config"].getCurrent()
205 if hasattr(current[1], 'help_window'):
206 if current[1].help_window.instance is not None:
207 current[1].help_window.instance.hide()
209 def cancelConfirm(self, result):
213 for x in self["config"].list:
219 if self["config"].isChanged():
221 self.session.openWithCallback(self.cancelConfirm, MessageBox, _("Really close without saving settings?"))
227 CrashlogAutoSubmitConfiguration.oldMailEntryValue = config.plugins.crashlogautosubmit.sendmail.value
228 ConfigListScreen.keySave(self)
230 def msgCrashlogNotifier(self):
231 if self.msgCrashlogMailer is True:
233 callCrashMailer(True, self.session)
234 except AttributeError:
235 print "error, not restarting crashlogmailer"
238 def mxServerFound(mxServer,session):
239 print "[CrashlogAutoSubmit] - mxServerFound -->", mxServer
240 crashLogFilelist = []
241 message = StringIO.StringIO()
242 writer = MimeWriter.MimeWriter(message)
243 mailFrom = "enigma2@crashlog.dream-multimedia-tv.de"
244 mailTo = "enigma2@crashlog.dream-multimedia-tv.de"
245 subject = "Automatically generated crashlogmail"
246 # Define the main body headers.
247 writer.addheader('To', "dream-multimedia-crashlogs <enigma2@crashlog.dream-multimedia-tv.de>")
248 writer.addheader('From', "CrashlogAutoSubmitter <enigma2@crashlog.dream-multimedia-tv.de>")
249 writer.addheader('Subject', str(subject))
250 writer.addheader('Date', smtp.rfc822date())
251 if config.plugins.crashlogautosubmit.attachemail.value is True:
252 if str(config.plugins.crashlogautosubmit.email.value) != "myemail@home.com":
253 writer.addheader('Reply-To', str(str(config.plugins.crashlogautosubmit.email.value)))
254 writer.addheader('MIME-Version', '1.0')
255 writer.startmultipartbody('mixed')
256 # start with a text/plain part
257 part = writer.nextpart()
258 body = part.startbody('text/plain')
260 # Define the message body
261 body_text1 = "\nHello\n\nHere are some crashlogs i found for you.\n"
262 if str(config.plugins.crashlogautosubmit.email.value) == "myemail@home.com":
265 user_email = "\nUser supplied email address: " + str(config.plugins.crashlogautosubmit.email.value)
266 if str(config.plugins.crashlogautosubmit.name.value) == "Dreambox User":
269 user_name = "\n\nOptional supplied name: " + str(config.plugins.crashlogautosubmit.name.value)
270 body_text2 = "\n\nThis is an automatically generated email from the CrashlogAutoSubmit plugin.\n\n\nHave a nice day.\n"
271 body_text = body_text1 + user_email + user_name + body_text2
272 body.write(body_text)
276 (_("Yes, and don't ask again"), "send_always"),
277 (_("No, not now"), "send_not"),
278 (_("No, send them never"), "send_never")
281 def handleError(error):
282 print "[CrashlogAutoSubmit] - Message send Error -->", error.getErrorMessage()
284 def handleSuccess(result):
285 print "[CrashlogAutoSubmit] - Message sent successfully -->",result
286 if len(crashLogFilelist):
287 for crashlog in crashLogFilelist:
288 if config.plugins.crashlogautosubmit.sendlog.value == "delete":
290 elif config.plugins.crashlogautosubmit.sendlog.value == "rename":
291 currfilename = str(os.path.basename(crashlog))
292 newfilename = "/media/hdd/" + currfilename + ".sent"
293 os.rename(crashlog,newfilename)
296 print "[CrashlogAutoSubmit] - send_mail"
297 if len(crashLogFilelist):
298 for crashlog in crashLogFilelist:
299 filename = str(os.path.basename(crashlog))
300 subpart = writer.nextpart()
301 subpart.addheader("Content-Transfer-Encoding", 'base64')
302 subpart.addheader("Content-Disposition",'attachment; filename="%s"' % filename)
303 subpart.addheader('Content-Description', 'Enigma2 crashlog')
304 body = subpart.startbody("%s; name=%s" % ('application/octet-stream', filename))
305 mimetools.encode(open(crashlog, 'rb'), body, 'base64')
307 sending = smtp.sendmail(str(mxServer), mailFrom, mailTo, message.getvalue())
308 sending.addCallback(handleSuccess).addErrback(handleError)
310 def handleAnswer(answer):
311 answer = answer and answer[1]
312 print "[CrashlogAutoSubmit] - handleAnswer --> ",answer
315 elif answer == "send_always":
316 config.plugins.crashlogautosubmit.sendmail.value = "send_always"
317 config.plugins.crashlogautosubmit.sendmail.save()
318 config.plugins.crashlogautosubmit.save()
319 config.plugins.save()
322 elif answer in ( None, "send_never"):
323 config.plugins.crashlogautosubmit.sendmail.value = "send_never"
324 config.plugins.crashlogautosubmit.sendmail.save()
325 config.plugins.crashlogautosubmit.save()
326 config.plugins.save()
328 elif answer == "send_not":
329 print "[CrashlogAutoSubmit] - not sending crashlogs for this time."
331 for crashlog in os.listdir('/media/hdd'):
332 if crashlog.startswith("enigma2_crash_") and crashlog.endswith(".log"):
333 print "[CrashlogAutoSubmit] - found crashlog: ",os.path.basename(crashlog)
334 crashLogFilelist.append('/media/hdd/' + crashlog)
336 if len(crashLogFilelist):
337 if config.plugins.crashlogautosubmit.sendmail.value == "send":
338 Notifications.AddNotificationWithCallback(handleAnswer, ChoiceBox, title=_("Crashlogs found!\nSend them to Dream Multimedia?"), list = list)
339 elif config.plugins.crashlogautosubmit.sendmail.value == "send_always":
342 print "[CrashlogAutoSubmit] - no crashlogs found."
345 def getMailExchange(host):
346 print "[CrashlogAutoSubmit] - getMailExchange"
347 return relaymanager.MXCalculator().getMX(host).addCallback(_gotMXRecord)
349 def _gotMXRecord(mxRecord):
350 return str(mxRecord.name)
353 def startMailer(session):
354 if config.plugins.crashlogautosubmit.sendmail.value == "send_never":
355 print "[CrashlogAutoSubmit] - not starting CrashlogAutoSubmit"
358 def gotMXServer(mxServer):
359 print "[CrashlogAutoSubmit] gotMXServer: ",mxServer
360 mxServerFound(mxServer,session)
362 def handleMXError(error):
363 print "[CrashlogAutoSubmit] - MX resolve ERROR:", error.getErrorMessage()
365 if not config.misc.firstrun.value:
366 getMailExchange('crashlog.dream-multimedia-tv.de').addCallback(gotMXServer).addErrback(handleMXError)
369 def callCrashMailer(result,session):
371 print "[CrashlogAutoSubmit] - config changed"
374 print "[CrashlogAutoSubmit] - config not changed"
377 def autostart(reason, **kwargs):
378 print "[CrashlogAutoSubmit] - autostart"
379 if "session" in kwargs:
381 startMailer(kwargs["session"])
382 except ImportError, e:
383 print "[CrashlogAutoSubmit] Twisted-mail not available, not starting CrashlogAutoSubmitter", e
386 def openconfig(session, **kwargs):
387 session.open(CrashlogAutoSubmitConfiguration)
390 def selSetup(menuid, **kwargs):
391 if menuid != "system":
394 return [(_("Crashlog settings") + "...", openconfig, "crashlog_config", 70)]
397 def Plugins(**kwargs):
398 return [PluginDescriptor(where = [PluginDescriptor.WHERE_SESSIONSTART, PluginDescriptor.WHERE_AUTOSTART], fnc = autostart),
399 PluginDescriptor(name=_("CrashlogAutoSubmit"), description=_("CrashlogAutoSubmit settings"),where=PluginDescriptor.WHERE_MENU, fnc=selSetup)]