Package IDAscope :: Package idascope :: Package core :: Module WinApiProvider
[hide private]
[frames] | no frames]

Source Code for Module IDAscope.idascope.core.WinApiProvider

  1  #!/usr/bin/python 
  2  ######################################################################## 
  3  # Copyright (c) 2012 
  4  # Daniel Plohmann <daniel.plohmann<at>gmail<dot>com> 
  5  # Alexander Hanel <alexander.hanel<at>gmail<dot>com> 
  6  # All rights reserved. 
  7  ######################################################################## 
  8  # 
  9  #  This file is part of IDAscope 
 10  # 
 11  #  IDAscope is free software: you can redistribute it and/or modify it 
 12  #  under the terms of the GNU General Public License as published by 
 13  #  the Free Software Foundation, either version 3 of the License, or 
 14  #  (at your option) any later version. 
 15  # 
 16  #  This program is distributed in the hope that it will be useful, but 
 17  #  WITHOUT ANY WARRANTY; without even the implied warranty of 
 18  #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
 19  #  General Public License for more details. 
 20  # 
 21  #  You should have received a copy of the GNU General Public License 
 22  #  along with this program.  If not, see 
 23  #  <http://www.gnu.org/licenses/>. 
 24  # 
 25  ######################################################################## 
 26  # Credits: 
 27  # - Thanks to Sascha Rommelfangen for testing / fixing path resolution 
 28  #   for OS X. 
 29  ######################################################################## 
 30   
 31  import json 
 32  import os 
 33   
 34  import JsonHelper 
 35   
 36   
37 -class WinApiProvider():
38 """ 39 Data provider for request concerning WinApi information. 40 """ 41
42 - def __init__(self, idascope_config):
43 print ("Loading WinApiProvider") 44 self.idascope_config = idascope_config 45 self.os = os 46 self.winapi_data = {} 47 if self.idascope_config.winapi_load_keyword_database: 48 self._load_keywords() 49 self.last_delivered_filepath = self.idascope_config.winapi_rootdir 50 self.backward_history = [] 51 self.forward_history = [] 52 self.is_appending_to_history = True
53
54 - def _load_keywords(self):
55 """ 56 Loads the keywords database from the file specified in the config. 57 """ 58 keywords_file = open(self.idascope_config.winapi_keywords_file, "r") 59 self.winapi_data = json.loads(keywords_file.read(), object_hook=JsonHelper.decode_dict)
60
62 """ 63 Determines wther the offline MSDN database is available or not. 64 This is evaluated based on whether the keywords database has been loaded or not. 65 @return: (bool) availablity of the MSDN database 66 """ 67 if len(self.winapi_data.keys()) > 0: 68 return True 69 return False
70
71 - def get_keywords_for_initial(self, keyword_initial):
72 """ 73 Get all keywords that start with the given initial character. 74 @param keyword_initial: an initial character 75 @type keyword_initial: str 76 @return: (a list of str) keywords in WinApi that start with that initial. 77 """ 78 if keyword_initial in self.winapi_data.keys(): 79 return sorted(self.winapi_data[keyword_initial], key=str.lower) 80 else: 81 return []
82
83 - def get_keyword_content(self, keyword):
84 """ 85 Get the content for this keyword. 86 @type keyword: str 87 @return: (str) HTML content. 88 """ 89 api_filenames = self._get_api_filenames(keyword) 90 if len(api_filenames) == 1: 91 api_filenames = [self.idascope_config.winapi_rootdir + api_filenames[0]] 92 return self._get_document_content(api_filenames)
93
94 - def get_linked_document_content(self, url):
95 """ 96 Get the content for a requested linked document 97 @param url: URL of the requested file 98 @type url: QUrl 99 @return: a tuple (str, str) with content and anchor within the content 100 """ 101 anchor = "" 102 if url.isRelative(): 103 url_str = url.toString() 104 anchor = "" 105 document_content = "" 106 if "#" in url_str: 107 anchor = url_str[1 + url_str.rfind("#"):] 108 url_str = url_str[:url_str.rfind("#")] 109 if url_str != "": 110 filename = self.os.path.join(str(self.last_delivered_filepath), str(url_str)) 111 document_content = self._get_single_document_content(filename) 112 return document_content, anchor 113 else: 114 return self._get_single_document_content(url.toString()), anchor
115
116 - def get_history_states(self):
117 """ 118 Get information about whether history stepping (backward, forward) is available or not. 119 @return: a tuple (boolean, boolean) telling about availability of history stepping. 120 """ 121 return (len(self.backward_history) > 1, len(self.forward_history) > 0)
122
124 """ 125 Get the content of the previously accessed document. This implements the well-known "back"-button 126 functionality. 127 @return: a tuple (str, str) with content and anchor within the content 128 """ 129 self._cleanup_histories() 130 # first move latest visited document to forward queue. 131 if len(self.backward_history) > 0: 132 history_entry = self.backward_history.pop() 133 self.forward_history.append(history_entry) 134 # obtain former penultimate document from history and return its content 135 if len(self.backward_history) > 0: 136 self.is_appending_to_history = False 137 history_entry = self.backward_history[-1] 138 document_content = self._get_document_content(history_entry[0]), history_entry[1] 139 self.is_appending_to_history = True 140 return document_content 141 return ("", "")
142
144 """ 145 Get the content of the previously accessed document. This implements the well-known "back"-button 146 functionality. 147 @return: a tuple (str, str) with content and anchor within the content 148 """ 149 # first move latest visited document again to backward queue. 150 self._cleanup_histories() 151 if len(self.forward_history) > 0: 152 history_entry = self.forward_history.pop() 153 self.backward_history.append(history_entry) 154 self.is_appending_to_history = False 155 document_content = self._get_document_content(history_entry[0]), history_entry[1] 156 self.is_appending_to_history = True 157 return document_content 158 return ("", "")
159
160 - def _cleanup_histories(self):
161 """ 162 Eliminate subsequent similar items from history lists 163 """ 164 self.backward_history = self._cleanup_list(self.backward_history) 165 self.forward_history = self._cleanup_list(self.forward_history)
166
167 - def _cleanup_list(self, input_list):
168 """ 169 Eliminate subsequent similar items from a list 170 @param input_list: A list of arbitrary items 171 @type input_list: list 172 @return: (list) the input list without subsequent similar items 173 """ 174 cleaned_list = [] 175 last_entry = None 176 for entry in input_list: 177 if entry != last_entry: 178 cleaned_list.append(entry) 179 last_entry = entry 180 return cleaned_list
181
182 - def _get_api_filenames(self, keyword):
183 """ 184 Get filenames that are associated with the given keyword. 185 @param keyword: keyword to get the filenames for 186 @type keyword: str 187 @return: (a list of str) filenames that cover this keyword. 188 """ 189 if len(keyword) > 0: 190 keyword_initial = keyword[0].lower() 191 if keyword_initial in self.winapi_data.keys(): 192 if keyword in self.winapi_data[keyword_initial]: 193 return self.winapi_data[keyword_initial][keyword] 194 return []
195
196 - def _get_document_content(self, filenames):
197 """ 198 Produce the document content for a given list of filenames. 199 If there are multiple filenames, no document content is returned but a rendered list fo the filenames, 200 @param filenames: the filename(s) to get content for 201 @type filenames: list of str 202 @return: (str) HTML content. 203 """ 204 document_content = "<p>No entries for your query.</p>" 205 if len(filenames) > 1: 206 document_content = self._generate_html_list_of_filenames(filenames) 207 if self.is_appending_to_history: 208 self.forward_history = [] 209 self.backward_history.append((filenames, "")) 210 self._cleanup_histories() 211 elif len(filenames) == 1: 212 document_content = self._get_single_document_content(filenames[0]) 213 return document_content
214
215 - def _generate_html_list_of_filenames(self, filenames):
216 """ 217 Convert a list of filenames as string into a mini-HTML document with the list entries as links to the files 218 in a bullet list. 219 @param filenames: the filenames to include in the bullet list 220 @type filenames: list of str 221 @return: (str) a HTML file with a bullet list of links to the filenames 222 """ 223 document_content = "<p>Multiple files are covering this keyword. Choose one:</p><ul>" 224 for filename in filenames: 225 # sanitize filenames as obtained from the config file. 226 filename = filename.replace('\\', self.os.sep) 227 document_content += "<li><a href=\"%s\">%s</a></li>" % (self.idascope_config.winapi_rootdir + \ 228 filename, filename) 229 return document_content
230
231 - def _get_single_document_content(self, filename):
232 """ 233 Load a single document by filename and return its content. 234 @param filename: the filename to load 235 @type filename: str 236 @return: (str) the content of the file 237 """ 238 document_content = "" 239 try: 240 # sanitize the filename as obtained from the config file. 241 filename = filename.replace('\\', self.os.sep) 242 with open(filename, "r") as f: 243 document_content = f.read() 244 self.last_delivered_filepath = filename[:filename.rfind(self.os.sep)] + self.os.sep 245 if self.is_appending_to_history: 246 self.forward_history = [] 247 self.backward_history.append(([filename], "")) 248 self._cleanup_histories() 249 except Exception as exc: 250 document_content = "<html><head /><body>Well, something has gone wrong here. Try again with some" \ 251 + " proper API name.<hr /><p>Exception: %s</p></body></html>" % exc 252 return document_content
253