|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2012 - 2019 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing a user agent manager. |
|
8 """ |
|
9 |
|
10 from __future__ import unicode_literals |
|
11 |
|
12 import os |
|
13 |
|
14 from PyQt5.QtCore import pyqtSignal, QObject, QXmlStreamReader |
|
15 |
|
16 from E5Gui import E5MessageBox |
|
17 |
|
18 from Utilities.AutoSaver import AutoSaver |
|
19 import Utilities |
|
20 |
|
21 |
|
22 class UserAgentManager(QObject): |
|
23 """ |
|
24 Class implementing a user agent manager. |
|
25 |
|
26 @signal changed() emitted to indicate a change |
|
27 @signal userAgentSettingsSaved() emitted after the user agent settings |
|
28 were saved |
|
29 """ |
|
30 changed = pyqtSignal() |
|
31 userAgentSettingsSaved = pyqtSignal() |
|
32 |
|
33 def __init__(self, parent=None): |
|
34 """ |
|
35 Constructor |
|
36 |
|
37 @param parent reference to the parent object (QObject) |
|
38 """ |
|
39 super(UserAgentManager, self).__init__(parent) |
|
40 |
|
41 self.__agents = {} |
|
42 # dictionary with agent strings indexed by host name |
|
43 self.__loaded = False |
|
44 self.__saveTimer = AutoSaver(self, self.save) |
|
45 |
|
46 self.changed.connect(self.__saveTimer.changeOccurred) |
|
47 |
|
48 def getFileName(self): |
|
49 """ |
|
50 Public method to get the file name of the user agents file. |
|
51 |
|
52 @return name of the user agents file (string) |
|
53 """ |
|
54 return os.path.join( |
|
55 Utilities.getConfigDir(), "browser", "userAgentSettings.xml") |
|
56 |
|
57 def save(self): |
|
58 """ |
|
59 Public slot to save the user agent entries to disk. |
|
60 """ |
|
61 if not self.__loaded: |
|
62 return |
|
63 |
|
64 from .UserAgentWriter import UserAgentWriter |
|
65 agentFile = self.getFileName() |
|
66 writer = UserAgentWriter() |
|
67 if not writer.write(agentFile, self.__agents): |
|
68 E5MessageBox.critical( |
|
69 None, |
|
70 self.tr("Saving user agent data"), |
|
71 self.tr( |
|
72 """<p>User agent data could not be saved to""" |
|
73 """ <b>{0}</b></p>""").format(agentFile)) |
|
74 else: |
|
75 self.userAgentSettingsSaved.emit() |
|
76 |
|
77 def __load(self): |
|
78 """ |
|
79 Private method to load the saved user agent settings. |
|
80 """ |
|
81 agentFile = self.getFileName() |
|
82 if not os.path.exists(agentFile): |
|
83 self.__loadNonXml(os.path.splitext(agentFile)[0]) |
|
84 else: |
|
85 from .UserAgentReader import UserAgentReader |
|
86 reader = UserAgentReader() |
|
87 self.__agents = reader.read(agentFile) |
|
88 if reader.error() != QXmlStreamReader.NoError: |
|
89 E5MessageBox.warning( |
|
90 None, |
|
91 self.tr("Loading user agent data"), |
|
92 self.tr("""Error when loading user agent data on""" |
|
93 """ line {0}, column {1}:\n{2}""") |
|
94 .format(reader.lineNumber(), |
|
95 reader.columnNumber(), |
|
96 reader.errorString())) |
|
97 |
|
98 self.__loaded = True |
|
99 |
|
100 def __loadNonXml(self, agentFile): |
|
101 """ |
|
102 Private method to load non-XML user agent files. |
|
103 |
|
104 This method is to convert from the old, non-XML format to the new |
|
105 XML based format. |
|
106 |
|
107 @param agentFile name of the non-XML user agent file (string) |
|
108 """ |
|
109 if os.path.exists(agentFile): |
|
110 try: |
|
111 f = open(agentFile, "r", encoding="utf-8") |
|
112 lines = f.read() |
|
113 f.close() |
|
114 except IOError as err: |
|
115 E5MessageBox.critical( |
|
116 None, |
|
117 self.tr("Loading user agent data"), |
|
118 self.tr("""<p>User agent data could not be loaded """ |
|
119 """from <b>{0}</b></p>""" |
|
120 """<p>Reason: {1}</p>""") |
|
121 .format(agentFile, str(err))) |
|
122 return |
|
123 |
|
124 for line in lines.splitlines(): |
|
125 if not line or \ |
|
126 line.startswith("#") or \ |
|
127 "@@" not in line: |
|
128 continue |
|
129 |
|
130 host, agent = line.split("@@", 1) |
|
131 self.__agents[host] = agent |
|
132 |
|
133 os.remove(agentFile) |
|
134 |
|
135 self.__loaded = True |
|
136 |
|
137 # this does the conversion |
|
138 self.save() |
|
139 |
|
140 def reload(self): |
|
141 """ |
|
142 Public method to reload the user agent settings. |
|
143 """ |
|
144 if not self.__loaded: |
|
145 return |
|
146 |
|
147 self.__agents = {} |
|
148 self.__load() |
|
149 |
|
150 def close(self): |
|
151 """ |
|
152 Public method to close the user agents manager. |
|
153 """ |
|
154 self.__saveTimer.saveIfNeccessary() |
|
155 |
|
156 def removeUserAgent(self, host): |
|
157 """ |
|
158 Public method to remove a user agent entry. |
|
159 |
|
160 @param host host name (string) |
|
161 """ |
|
162 if host in self.__agents: |
|
163 del self.__agents[host] |
|
164 self.changed.emit() |
|
165 |
|
166 def allHostNames(self): |
|
167 """ |
|
168 Public method to get a list of all host names we a user agent setting |
|
169 for. |
|
170 |
|
171 @return sorted list of all host names (list of strings) |
|
172 """ |
|
173 if not self.__loaded: |
|
174 self.__load() |
|
175 |
|
176 return sorted(self.__agents.keys()) |
|
177 |
|
178 def hostsCount(self): |
|
179 """ |
|
180 Public method to get the number of available user agent settings. |
|
181 |
|
182 @return number of user agent settings (integer) |
|
183 """ |
|
184 if not self.__loaded: |
|
185 self.__load() |
|
186 |
|
187 return len(self.__agents) |
|
188 |
|
189 def userAgent(self, host): |
|
190 """ |
|
191 Public method to get the user agent setting for a host. |
|
192 |
|
193 @param host host name (string) |
|
194 @return user agent string (string) |
|
195 """ |
|
196 if not self.__loaded: |
|
197 self.__load() |
|
198 |
|
199 if host not in self.__agents: |
|
200 return "" |
|
201 |
|
202 return self.__agents[host] |
|
203 |
|
204 def setUserAgent(self, host, agent): |
|
205 """ |
|
206 Public method to set the user agent string for a host. |
|
207 |
|
208 @param host host name (string) |
|
209 @param agent user agent string (string) |
|
210 """ |
|
211 if host != "" and agent != "": |
|
212 self.__agents[host] = agent |
|
213 self.changed.emit() |
|
214 |
|
215 def userAgentForUrl(self, url): |
|
216 """ |
|
217 Public method to determine the user agent for the given URL. |
|
218 |
|
219 @param url URL to determine user agent for (QUrl) |
|
220 @return user agent string (string) |
|
221 """ |
|
222 if url.isValid(): |
|
223 host = url.host() |
|
224 return self.userAgent(host) |
|
225 |
|
226 return "" |
|
227 |
|
228 def setUserAgentForUrl(self, url, agent): |
|
229 """ |
|
230 Public method to set the user agent string for an URL. |
|
231 |
|
232 @param url URL to register user agent setting for (QUrl) |
|
233 @param agent new current user agent string (string) |
|
234 """ |
|
235 if url.isValid(): |
|
236 host = url.host() |
|
237 self.setUserAgent(host, agent) |