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