Package lib :: Package cuckoo :: Package common :: Module utils
[hide private]
[frames] | no frames]

Source Code for Module lib.cuckoo.common.utils

  1  # Copyright (C) 2010-2015 Cuckoo Foundation. 
  2  # This file is part of Cuckoo Sandbox - http://www.cuckoosandbox.org 
  3  # See the file 'docs/LICENSE' for copying permission. 
  4   
  5  import os 
  6  import time 
  7  import shutil 
  8  import ntpath 
  9  import string 
 10  import tempfile 
 11  import xmlrpclib 
 12  import inspect 
 13  import threading 
 14  import multiprocessing 
 15  from datetime import datetime 
 16   
 17  from lib.cuckoo.common.exceptions import CuckooOperationalError 
 18  from lib.cuckoo.common.config import Config 
 19   
 20  try: 
 21      import chardet 
 22      HAVE_CHARDET = True 
 23  except ImportError: 
 24      HAVE_CHARDET = False 
 25   
26 -def create_folders(root=".", folders=[]):
27 """Create directories. 28 @param root: root path. 29 @param folders: folders list to be created. 30 @raise CuckooOperationalError: if fails to create folder. 31 """ 32 for folder in folders: 33 create_folder(root, folder)
34
35 -def create_folder(root=".", folder=None):
36 """Create directory. 37 @param root: root path. 38 @param folder: folder name to be created. 39 @raise CuckooOperationalError: if fails to create folder. 40 """ 41 folder_path = os.path.join(root, folder) 42 if folder and not os.path.isdir(folder_path): 43 try: 44 os.makedirs(folder_path) 45 except OSError: 46 raise CuckooOperationalError("Unable to create folder: %s" % 47 folder_path)
48
49 -def delete_folder(folder):
50 """Delete a folder and all its subdirectories. 51 @param folder: path to delete. 52 @raise CuckooOperationalError: if fails to delete folder. 53 """ 54 if os.path.exists(folder): 55 try: 56 shutil.rmtree(folder) 57 except OSError: 58 raise CuckooOperationalError("Unable to delete folder: " 59 "{0}".format(folder))
60 61 # Don't allow all characters in "string.printable", as newlines, carriage 62 # returns, tabs, \x0b, and \x0c may mess up reports. 63 PRINTABLE_CHARACTERS = \ 64 string.letters + string.digits + string.punctuation + " \t\r\n" 65
66 -def convert_char(c):
67 """Escapes characters. 68 @param c: dirty char. 69 @return: sanitized char. 70 """ 71 if c in PRINTABLE_CHARACTERS: 72 return c 73 else: 74 return "\\x%02x" % ord(c)
75
76 -def is_printable(s):
77 """ Test if a string is printable.""" 78 for c in s: 79 if c not in PRINTABLE_CHARACTERS: 80 return False 81 return True
82
83 -def convert_to_printable(s):
84 """Convert char to printable. 85 @param s: string. 86 @return: sanitized string. 87 """ 88 if is_printable(s): 89 return s 90 return "".join(convert_char(c) for c in s)
91
92 -def datetime_to_iso(timestamp):
93 """Parse a datatime string and returns a datetime in iso format. 94 @param timestamp: timestamp string 95 @return: ISO datetime 96 """ 97 return datetime.strptime(timestamp, "%Y-%m-%d %H:%M:%S").isoformat()
98
99 -def get_filename_from_path(path):
100 """Cross-platform filename extraction from path. 101 @param path: file path. 102 @return: filename. 103 """ 104 dirpath, filename = ntpath.split(path) 105 return filename if filename else ntpath.basename(dirpath)
106
107 -def store_temp_file(filedata, filename, path=None):
108 """Store a temporary file. 109 @param filedata: content of the original file. 110 @param filename: name of the original file. 111 @param path: optional path for temp directory. 112 @return: path to the temporary file. 113 """ 114 filename = get_filename_from_path(filename) 115 116 # Reduce length (100 is arbitrary). 117 filename = filename[:100] 118 119 options = Config() 120 # Create temporary directory path. 121 if path: 122 target_path = path 123 else: 124 tmp_path = options.cuckoo.get("tmppath", "/tmp") 125 target_path = os.path.join(tmp_path, "cuckoo-tmp") 126 if not os.path.exists(target_path): 127 os.mkdir(target_path) 128 129 tmp_dir = tempfile.mkdtemp(prefix="upload_", dir=target_path) 130 tmp_file_path = os.path.join(tmp_dir, filename) 131 with open(tmp_file_path, "wb") as tmp_file: 132 # If filedata is file object, do chunked copy. 133 if hasattr(filedata, "read"): 134 chunk = filedata.read(1024) 135 while chunk: 136 tmp_file.write(chunk) 137 chunk = filedata.read(1024) 138 else: 139 tmp_file.write(filedata) 140 141 return tmp_file_path
142
143 -class TimeoutServer(xmlrpclib.ServerProxy):
144 """Timeout server for XMLRPC. 145 XMLRPC + timeout - still a bit ugly - but at least gets rid of setdefaulttimeout 146 inspired by http://stackoverflow.com/questions/372365/set-timeout-for-xmlrpclib-serverproxy 147 (although their stuff was messy, this is cleaner) 148 @see: http://stackoverflow.com/questions/372365/set-timeout-for-xmlrpclib-serverproxy 149 """
150 - def __init__(self, *args, **kwargs):
151 timeout = kwargs.pop("timeout", None) 152 kwargs["transport"] = TimeoutTransport(timeout=timeout) 153 xmlrpclib.ServerProxy.__init__(self, *args, **kwargs)
154
155 - def _set_timeout(self, timeout):
156 t = self._ServerProxy__transport 157 t.timeout = timeout 158 # If we still have a socket we need to update that as well. 159 if hasattr(t, "_connection") and t._connection[1] and t._connection[1].sock: 160 t._connection[1].sock.settimeout(timeout)
161
162 -class TimeoutTransport(xmlrpclib.Transport):
163 - def __init__(self, *args, **kwargs):
164 self.timeout = kwargs.pop("timeout", None) 165 xmlrpclib.Transport.__init__(self, *args, **kwargs)
166
167 - def make_connection(self, *args, **kwargs):
168 conn = xmlrpclib.Transport.make_connection(self, *args, **kwargs) 169 if self.timeout is not None: 170 conn.timeout = self.timeout 171 return conn
172
173 -class Singleton(type):
174 """Singleton. 175 @see: http://stackoverflow.com/questions/6760685/creating-a-singleton-in-python 176 """ 177 _instances = {} 178
179 - def __call__(cls, *args, **kwargs):
180 if cls not in cls._instances: 181 cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs) 182 return cls._instances[cls]
183
184 -def logtime(dt):
185 """Formats time like a logger does, for the csv output 186 (e.g. "2013-01-25 13:21:44,590") 187 @param dt: datetime object 188 @return: time string 189 """ 190 t = time.strftime("%Y-%m-%d %H:%M:%S", dt.timetuple()) 191 s = "%s,%03d" % (t, dt.microsecond/1000) 192 return s
193
194 -def time_from_cuckoomon(s):
195 """Parse time string received from cuckoomon via netlog 196 @param s: time string 197 @return: datetime object 198 """ 199 return datetime.strptime(s, "%Y-%m-%d %H:%M:%S,%f")
200
201 -def to_unicode(s):
202 """Attempt to fix non uft-8 string into utf-8. It tries to guess input encoding, 203 if fail retry with a replace strategy (so undetectable chars will be escaped). 204 @see: fuller list of encodings at http://docs.python.org/library/codecs.html#standard-encodings 205 """ 206 207 def brute_enc(s2): 208 """Trying to decode via simple brute forcing.""" 209 encodings = ("ascii", "utf8", "latin1") 210 for enc in encodings: 211 try: 212 return unicode(s2, enc) 213 except UnicodeDecodeError: 214 pass 215 return None
216 217 def chardet_enc(s2): 218 """Guess encoding via chardet.""" 219 enc = chardet.detect(s2)["encoding"] 220 221 try: 222 return unicode(s2, enc) 223 except UnicodeDecodeError: 224 pass 225 return None 226 227 # If already in unicode, skip. 228 if isinstance(s, unicode): 229 return s 230 231 # First try to decode against a little set of common encodings. 232 result = brute_enc(s) 233 234 # Try via chardet. 235 if not result and HAVE_CHARDET: 236 result = chardet_enc(s) 237 238 # If not possible to convert the input string, try again with 239 # a replace strategy. 240 if not result: 241 result = unicode(s, errors="replace") 242 243 return result 244
245 -def cleanup_value(v):
246 """Cleanup utility function, strips some unwanted parts from values.""" 247 v = str(v) 248 if v.startswith("\\??\\"): 249 v = v[4:] 250 return v
251
252 -def sanitize_filename(x):
253 """Kind of awful but necessary sanitizing of filenames to 254 get rid of unicode problems.""" 255 out = "" 256 for c in x: 257 if c in string.letters + string.digits + " _-.": 258 out += c 259 else: 260 out += "_" 261 262 return out
263
264 -def classlock(f):
265 """Classlock decorator (created for database.Database). 266 Used to put a lock to avoid sqlite errors. 267 """ 268 def inner(self, *args, **kwargs): 269 curframe = inspect.currentframe() 270 calframe = inspect.getouterframes(curframe, 2) 271 272 if calframe[1][1].endswith("database.py"): 273 return f(self, *args, **kwargs) 274 275 with self._lock: 276 return f(self, *args, **kwargs)
277 278 return inner 279
280 -class SuperLock(object):
281 - def __init__(self):
282 self.tlock = threading.Lock() 283 self.mlock = multiprocessing.Lock()
284
285 - def __enter__(self):
286 self.tlock.acquire() 287 self.mlock.acquire()
288 - def __exit__(self, type, value, traceback):
289 self.mlock.release() 290 self.tlock.release()
291