1
2
3
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
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
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
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
64
65 PRINTABLE_CHARACTERS = string.letters + string.digits + string.punctuation + " \t\r\n"
66
67
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
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
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
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
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
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
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
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
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 """
151
153 t = self._ServerProxy__transport
154 t.timeout = timeout
155
156 if hasattr(t, "_connection") and t._connection[1] and t._connection[1].sock:
157 t._connection[1].sock.settimeout(timeout)
158
161 self.timeout = kwargs.pop("timeout", None)
162 xmlrpclib.Transport.__init__(self, *args, **kwargs)
163
169
171 """Singleton.
172 @see: http://stackoverflow.com/questions/6760685/creating-a-singleton-in-python
173 """
174 _instances = {}
179
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
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
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
224 if isinstance(s, unicode):
225 return s
226
227
228 result = brute_enc(s)
229
230
231 if (not result) and HAVE_CHARDET:
232 result = chardet_enc(s)
233
234
235
236 if not result:
237 result = unicode(s, errors="replace")
238
239 return result
240
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
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