viewgit/index.php:465 Only variables should be passed by reference [2048]

viewgit/index.php:466 Non-static method GeSHi::get_language_name_from_extension() should not be called statically [2048]

  1. # -*- coding: utf-8 -*-
  2. #
  3. # mlmanager is a python package that aims to "organize"
  4. # your mldonkey downloads.
  5. #
  6. # You can easily write a script that take care of moving
  7. # a file in the right place and to write emails to the right
  8. # people that need to know about the download.
  9. #
  10. #
  11. # It is released under the GNU General Public License Version 3
  12. #
  13. # Author: Leonardo Robol <leo@robol.it>
  14. #
  15. #
  16. #
  17. # In this section of the file we set some internal variables to their
  18. # default value. Users can customize them after loading the package.
  19. #
  20. # The fully qualified (or not fully qualified - it really doesn't matter)
  21. # domain that the server is part of.
  22. domain = "example.com"
  23.  
  24. # This is the mail address that will be set as sender for all
  25. # the emails generated by the script.
  26. from_addr = "mldonkey <mldonkey@%s>" % domain
  27.  
  28. # Mail server that the script will use to deliver emails. It must be properly
  29. # configured to relay mail from the domain selected.
  30. mail_server = "localhost"
  31.  
  32. # Users that should be notified when an error occurs in the script. You
  33. # can use the wildcard "owner" to match the owner of the file downladed.
  34. # This is generally true for every email function in mlmanager
  35. error_recipients = [ "owner" ]
  36.  
  37. # Number of times that rsync should try to transfer the file before
  38. # giving up.
  39. rsync_tries = 5
  40.  
  41. # Set file extensions to match. You can add extensions in every category
  42. video_extensions = ['avi', 'mpeg', 'mpg', 'mkv', 'm2v', 'divx', 'xvid', 'mov']
  43. audio_extensions = ['mp3', 'ogg', 'wav', 'flac', 'aac' ]
  44. text_extensions = ['pdf', 'doc', 'odt', 'ods', 'odp', 'ppt', 'rtf',
  45. 'pps', 'xls' , 'txt' ]
  46. cdimage_extensions = [ 'iso', 'nrg', 'ccd']
  47. archive_extensions = [ 'rar', 'zip', '7z', 'tar.gz', 'tar.bz2', 'lzo' ]
  48.  
  49.  
  50. __author__ = "Leonardo Robol <leo@robol.it>"
  51.  
  52. import os, sys, socket, shutil, subprocess, time, smtplib
  53. from email.mime.text import MIMEText
  54.  
  55. class FileType():
  56. """
  57. This class represent the type of a file, i.e you
  58. can check if it is a video, a text, an image...
  59. It can be:
  60. - video
  61. - audio
  62. - text
  63. - archive
  64. - other
  65. """
  66.  
  67. def __init__(self, filename):
  68. self._filename = filename
  69. self._detect_type ()
  70.  
  71.  
  72. def _test_extension(self, extension):
  73. return self._filename.lower().endswith(extension)
  74.  
  75. def _detect_type(self):
  76. """Detect the type of the file and save it in the internal
  77. varaible _type"""
  78. if len(filter(self._test_extension, video_extensions)) > 0:
  79. self._type = "video"
  80. elif len(filter(self._test_extension, audio_extensions)) > 0:
  81. self._type = "audio"
  82. elif len(filter(self._test_extension, text_extensions)) > 0:
  83. self._type = "text"
  84. elif len(filter(self._test_extension, cdimage_extensions)) > 0:
  85. self._type = "cdimage"
  86. elif len(filter(self._test_extension, archive_extensions)) > 0:
  87. self._type = "archive"
  88. else:
  89. self._type = "other"
  90.  
  91. def is_video(self):
  92. return (self._type == "video")
  93.  
  94. def is_image(self):
  95. return (self._type == "audio")
  96.  
  97. def is_text(self):
  98. return (self._type == "text")
  99.  
  100. def is_cdimage(self):
  101. return (self._type == "cdimage")
  102.  
  103. def is_archive(self):
  104. return (self._type == "archive")
  105.  
  106. def __str__(self):
  107. return self._type
  108.  
  109. def __repr__(self):
  110. return "<FileType '%s'>" % self._type
  111.  
  112.  
  113. class Download():
  114. """
  115. This class represent a file or a folder downloaded via mldonkey.
  116. You should create an instance of this calling
  117.  
  118. d = Download()
  119.  
  120. or, if you want
  121.  
  122. d = Download(username = "admin", password = "mysecretpassword")
  123.  
  124. This allow the script to connect to the mldonkey daemon and ensure
  125. that the file have been committed. It is not needed for mldonkey
  126. >= 2.7, but IT IS REQUIRED if you run an earlier mldonkey!
  127. """
  128.  
  129. def __init__(self, username = None, password = None, filename = None, group = None):
  130. """Perform some heuristic to determine the filetype,
  131. filename, groups and similar"""
  132.  
  133. # Set username and password
  134. self._username = username
  135. self._password = password
  136.  
  137. # If you do not provide username or password we can't
  138. # execute any command
  139. if not self._username or not self._password:
  140. self._authentication_available = False
  141.  
  142. self._filename = filename
  143. self._group = group
  144.  
  145. # If filename is not set then we can recover it
  146. # from the environment variables.
  147. if self._filename is None:
  148. self._filename = os.getenv("FILENAME")
  149.  
  150. # La durata del download in secondi
  151. self._duration = os.getenv("DURATION")
  152.  
  153. # Recover other data from environment
  154. if not self._group:
  155. self._group = os.getenv("FILE_GROUP")
  156.  
  157. self._owner = os.getenv("FILE_OWNER")
  158.  
  159. self._incoming = os.getenv("INCOMING")
  160.  
  161. # This could be none, and if it's empty
  162. # we should set it to None
  163. self._user_email = os.getenv("USER_EMAIL")
  164. if self._user_email is "":
  165. self._user_email = None
  166.  
  167. # The file is not yet committed. You will need to commit it
  168. # before trying to move it. If we do not have authentication
  169. # assume that auto commit is enabled
  170. self._committed = False
  171. if not self._authentication_available:
  172. self._committed = True
  173. else:
  174. self.commit ()
  175.  
  176. # Construct the path of the file; this will be the real
  177. # path after it will be committed!
  178. self._dest_path = os.path.join(os.getenv("HOME"), self._incoming)
  179. self._dest_path = os.path.join(self._dest_path, self._filename)
  180.  
  181. # It seems that mldonkey can confuse about directory and files.
  182. if not os.path.exists(self._dest_path) and "directories" in self._dest_path:
  183. self._dest_path = self._dest_path.replace("directories", "files")
  184. if not os.path.exists(self._dest_path) and "files" in self._dest_path:
  185. self._dest_path = self._dest_path.replace("files", "directories")
  186.  
  187. # If we get called with a non-existant file as argument that
  188. # is really a problem.
  189. if not os.path.exists(self._dest_path):
  190. self._notify_error ("Selected file does not exists: %s" % self._dest_path)
  191.  
  192. try:
  193. self._type = FileType(self._filename)
  194. except Exception, e:
  195. self._type = "other"
  196.  
  197.  
  198. def __repr__(self):
  199. return "<Download '%s'>" % self._filename
  200.  
  201. def _authentication_command (self):
  202. if not self._authentication_available:
  203. self._notify_error("Authentication data is not available, I can't authenticate to mldonkey")
  204. return None
  205. return "auth %s %s" % (self._username, self._password)
  206.  
  207. def commit(self):
  208. """Commit the file, i.e. save it to the hard disk
  209. in its final position. This should be the first
  210. thing you do"""
  211.  
  212. authentication = self._authentication_command ()
  213. if not authentication:
  214. return None
  215.  
  216. commands = [ authentication,
  217. "commit" ]
  218. self.send_command (commands)
  219. self._committed = True
  220.  
  221.  
  222.  
  223. def send_command(self, command_list):
  224. """You can send a command, or a list of command
  225. to the daemon. Note that the every call to this
  226. function will open a connection to the daemon, so
  227. you will need to authenticate every time.
  228. """
  229. if isinstance(command_list, str):
  230. command_list = [ command_list ]
  231.  
  232. # Open the connection
  233. try:
  234. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  235. s.connect(("localhost", 4000))
  236. except Exception, e:
  237. self._notify_error("Unable to connect to mldonkey daemon: %s" % e)
  238.  
  239. # Costruct the command line
  240. command_line = "\n".join(command_list)
  241. # and execute it
  242. s.send(command_line + "\n")
  243.  
  244. # Cleanup
  245. s.send("quit\n")
  246. s.close ()
  247.  
  248. def move(self, destination_folder, filename = None):
  249. """Move the file to destination. destination_folder MUST be
  250. a folder. You could change the filename with the optional
  251. filename parameter"""
  252.  
  253. if not filename:
  254. filename = self._filename
  255.  
  256. # Assicuriamoci che il file sia stato creato
  257. if not self._committed:
  258. self.commit ()
  259.  
  260. # Be sure that this is a directory
  261. if not destination_folder.endswith(os.path.sep):
  262. destination_folder += os.path.sep
  263.  
  264. if not os.path.exists(destination_folder):
  265. self._notify_error("Destination directory %s does not exists" % destination_folder)
  266. return
  267.  
  268. shutil.move (self._dest_path, destination_folder + filename)
  269.  
  270. # Update _dest_path
  271. self._dest_path = destination_folder + filename
  272.  
  273. def copy(self, destination, track = False):
  274. """
  275. Copy the file to another destination. Destination could be a folder
  276. to move the file in, or a complete path. The script will keep track
  277. only of the original file, i.e. if you call move() it will move the
  278. original file; if this is not what you want, move() the file to the
  279. right location and then copy() it around."""
  280.  
  281. if not self._committed:
  282. self.commit()
  283.  
  284. shutil.copy(self._dest_path, destination)
  285.  
  286.  
  287. def rsync(self, remote_destination):
  288. """Rsync the file to the remote destination. There must be an ssh key
  289. in the remote server otherwise nothing will happen. The script will
  290. automatically try a bunch of time to retransfer the file if
  291. the connection fail."""
  292. if not self._committed:
  293. self.commit ()
  294.  
  295. errors = ""
  296.  
  297. # Initialize internal counter of the times we have tried to move the file
  298. self._rsync_counter = 0
  299. s = subprocess.Popen("rsync --partial -az --compress-level=9 \"%s\" \"%s\"" % (self._dest_path,
  300. remote_destination),
  301. shell = True, stderr = subprocess.PIPE, stdout = subprocess.PIPE)
  302.  
  303. errors += "\n" + s.communicate ()[1]
  304. ret_code = s.wait ()
  305.  
  306. # If we fail call this funtion recursively to retry...wait for 60 seconds and then go (it could
  307. # be only a network problem)
  308. if ret_code != 0:
  309. self._rsync_counter += 1
  310. if self._rsync_counter < rsync_tries:
  311. time.sleep (60)
  312. self.rsync(remote_destination)
  313. else:
  314. self._notify_error("Rsync transfer of file %s failed more than 5 times, aborting\n\n%s" % (self._filename, errors))
  315.  
  316. def _notify_error(self, message):
  317. """Notify error via email"""
  318. self._send_email (error_recipients, "[mlmanager] An error occurred",
  319. message)
  320.  
  321. def notify_email(self, recipients, subject, message):
  322. """Notify something to some people via email"""
  323. self._send_email (recipients, subject, message)
  324.  
  325. def _send_email(self, recipients, subject, message):
  326. """Low level function to send an e-mail."""
  327.  
  328. msg = MIMEText(message)
  329. msg.set_charset ("utf-8")
  330. msg['From'] = from_addr
  331.  
  332. # If recipients is a string make it a list
  333. if isinstance(recipients, str):
  334. recipients = [ recipients ]
  335.  
  336. # Add user email if requested, and if present in the
  337. # profile of the user
  338. if "owner" in recipients:
  339. recipients.remove("owner")
  340. if self._user_email is not None:
  341. recipients.append(self._user_email)
  342.  
  343. msg['To'] = ", ".join(recipients)
  344. msg['Subject'] = subject
  345.  
  346. # Obtain message data
  347. data = msg.as_string ()
  348.  
  349. # Open a connection to the SMTP server
  350. try:
  351. s = smtplib.SMTP( host = mail_server )
  352. s.sendmail (from_addr, recipients, data)
  353. s.quit ()
  354. except Exception, e:
  355. raise RuntimeError("Error while notifying you of an error: %s" % e)
  356.  
  357. def is_in_group(self, group):
  358. """Return True if file is part of the selected group,
  359. False otherwise"""
  360. return (self._group == group)
  361.  
  362.  
  363. def get_type(self):
  364. """
  365. Return the type of the selected file, it could be
  366. video, audio, image, cdimage, archive or other, if none matches.
  367. """
  368. return str(self._type)
  369.  
  370. def get_filename(self):
  371. """Return filename"""
  372. return self._filename
  373.  
  374. def get_group(self):
  375. """Return group"""
  376. return self._group
  377.  
  378. def get_user(self):
  379. """Return duration"""
  380. return self._owner
  381.  
  382. def get_duration(self):
  383. """
  384. Obtain the duration as a tuple (hours, minutes, seconds)
  385. """
  386. d = int(self._duration)
  387. seconds = d % 60
  388. minutes = (d - seconds)/60 % 60
  389. hours = (d - seconds - 60*minutes)/3600
  390.  
  391. return (hours, minutes, seconds)
  392.