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