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 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  from datetime import datetime 
 13   
 14  from lib.cuckoo.common.exceptions import CuckooOperationalError 
 15  from lib.cuckoo.common.config import Config 
 16  from lib.cuckoo.common.constants import CUCKOO_ROOT 
 17   
 18  try: 
 19      import chardet 
 20      HAVE_CHARDET = True 
 21  except ImportError: 
 22      HAVE_CHARDET = False 
 23   
24 -def create_folders(root=".", folders=[]):
25 """Create directories. 26 @param root: root path. 27 @param folders: folders list to be created. 28 @raise CuckooOperationalError: if fails to create folder. 29 """ 30 for folder in folders: 31 if os.path.isdir(os.path.join(root, folder)): 32 continue 33 else: 34 create_folder(root, folder)
35
36 -def create_folder(root=".", folder=None):
37 """Create directory. 38 @param root: root path. 39 @param folder: folder name to be created. 40 @raise CuckooOperationalError: if fails to create folder. 41 """ 42 if not os.path.exists(os.path.join(root, folder)) and folder: 43 folder_path = os.path.join(root, folder) 44 if not os.path.isdir(folder_path): 45 try: 46 os.makedirs(folder_path) 47 except OSError: 48 raise CuckooOperationalError("Unable to create folder: %s" % 49 folder_path)
50 51
52 -def delete_folder(folder):
53 """Delete a folder and all its subdirectories. 54 @param folder: path to delete. 55 @raise CuckooOperationalError: if fails to delete folder. 56 """ 57 if os.path.exists(folder): 58 try: 59 shutil.rmtree(folder) 60 except OSError: 61 raise CuckooOperationalError("Unable to delete folder: " 62 "{0}".format(folder))
63 64 65 # don't allow all characters in "string.printable", as newlines, carriage 66 # returns, tabs, \x0b, and \x0c may mess up reports 67 PRINTABLE_CHARACTERS = string.letters + string.digits + string.punctuation + " \t\r\n" 68 69
70 -def convert_char(c):
71 """Escapes characters. 72 @param c: dirty char. 73 @return: sanitized char. 74 """ 75 if c in PRINTABLE_CHARACTERS: 76 return c 77 else: 78 return "\\x%02x" % ord(c)
79 80
81 -def is_printable(s):
82 """ Test if a string is printable.""" 83 for c in s: 84 if not c in PRINTABLE_CHARACTERS: 85 return False 86 return True
87
88 -def convert_to_printable(s):
89 """Convert char to printable. 90 @param s: string. 91 @return: sanitized string. 92 """ 93 if is_printable(s): 94 return s 95 return "".join(convert_char(c) for c in s)
96
97 -def datetime_to_iso(timestamp):
98 """Parse a datatime string and returns a datetime in iso format. 99 @param timestamp: timestamp string 100 @return: ISO datetime 101 """ 102 return datetime.strptime(timestamp, "%Y-%m-%d %H:%M:%S").isoformat()
103
104 -def get_filename_from_path(path):
105 """Cross-platform filename extraction from path. 106 @param path: file path. 107 @return: filename. 108 """ 109 dirpath, filename = ntpath.split(path) 110 return filename if filename else ntpath.basename(dirpath)
111
112 -def store_temp_file(filedata, filename):
113 """Store a temporary file. 114 @param filedata: content of the original file. 115 @param filename: name of the original file. 116 @return: path to the temporary file. 117 """ 118 filename = get_filename_from_path(filename) 119 120 # Reduce length (100 is arbitrary). 121 filename = filename[:100] 122 123 options = Config(os.path.join(CUCKOO_ROOT, "conf", "cuckoo.conf")) 124 tmppath = options.cuckoo.tmppath 125 targetpath = os.path.join(tmppath, "cuckoo-tmp") 126 if not os.path.exists(targetpath): 127 os.mkdir(targetpath) 128 129 tmp_dir = tempfile.mkdtemp(prefix="upload_", dir=targetpath) 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 not self.timeout is 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 - def __call__(cls, *args, **kwargs):
179 if cls not in cls._instances: 180 cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs) 181 return cls._instances[cls]
182
183 -def logtime(dt):
184 """Formats time like a logger does, for the csv output 185 (e.g. "2013-01-25 13:21:44,590") 186 @param dt: datetime object 187 @return: time string 188 """ 189 t = time.strftime("%Y-%m-%d %H:%M:%S", dt.timetuple()) 190 s = "%s,%03d" % (t, dt.microsecond/1000) 191 return s
192
193 -def time_from_cuckoomon(s):
194 """Parse time string received from cuckoomon via netlog 195 @param s: time string 196 @return: datetime object 197 """ 198 return datetime.strptime(s, "%Y-%m-%d %H:%M:%S,%f")
199
200 -def to_unicode(s):
201 """Attempt to fix non uft-8 string into utf-8. It tries to guess input encoding, 202 if fail retry with a replace strategy (so undetectable chars will be escaped). 203 @see: fuller list of encodings at http://docs.python.org/library/codecs.html#standard-encodings 204 """ 205 206 def brute_enc(s2): 207 """Trying to decode via simple brute forcing.""" 208 encodings = ("ascii", "utf8", "latin1") 209 for enc in encodings: 210 try: 211 return unicode(s2, enc) 212 except UnicodeDecodeError: 213 pass 214 return None
215 216 def chardet_enc(s2): 217 """Guess encoding via chardet.""" 218 enc = chardet.detect(s2)["encoding"] 219 220 try: 221 return unicode(s2, enc) 222 except UnicodeDecodeError: 223 pass 224 return None 225 226 # If already in unicode, skip. 227 if isinstance(s, unicode): 228 return s 229 230 # First try to decode against a little set of common encodings. 231 result = brute_enc(s) 232 233 # Try via chardet. 234 if (not result) and HAVE_CHARDET: 235 result = chardet_enc(s) 236 237 # If not possible to convert the input string, try again with 238 # a replace strategy. 239 if not result: 240 result = unicode(s, errors="replace") 241 242 return result 243
244 -def cleanup_value(v):
245 """Cleanup utility function, strips some unwanted parts from values.""" 246 v = str(v) 247 if v.startswith("\\??\\"): 248 v = v[4:] 249 return v
250
251 -def sanitize_filename(x):
252 """Kind of awful but necessary sanitizing of filenames to 253 get rid of unicode problems.""" 254 out = "" 255 for c in x: 256 if c in string.letters + string.digits + " _-.": 257 out += c 258 else: 259 out += "_" 260 261 return out
262