OSDN Git Service

2df6853616e03259b4901df520ae98c6accaa823
[opentween/open-tween.git] / OpenTween / WebBrowserController.cs
1 // OpenTween - Client of Twitter
2 // Copyright (c) 2007-2011 kiri_feather (@kiri_feather) <kiri.feather@gmail.com>
3 //           (c) 2008-2011 Moz (@syo68k)
4 //           (c) 2008-2011 takeshik (@takeshik) <http://www.takeshik.org/>
5 //           (c) 2010-2011 anis774 (@anis774) <http://d.hatena.ne.jp/anis774/>
6 //           (c) 2010-2011 fantasticswallow (@f_swallow) <http://twitter.com/f_swallow>
7 //           (c) 2011      Egtra (@egtra) <http://dev.activebasic.com/egtra/>
8 // All rights reserved.
9 // 
10 // This file is part of OpenTween.
11 // 
12 // This program is free software; you can redistribute it and/or modify it
13 // under the terms of the GNU General Public License as published by the Free
14 // Software Foundation; either version 3 of the License, or (at your option)
15 // any later version.
16 // 
17 // This program is distributed in the hope that it will be useful, but
18 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 // for more details. 
21 // 
22 // You should have received a copy of the GNU General Public License along
23 // with this program. If not, see <http://www.gnu.org/licenses/>, or write to
24 // the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
25 // Boston, MA 02110-1301, USA.
26
27 using System;
28 using System.Collections.Generic;
29 using System.Linq;
30 using System.Text;
31 using System.Runtime.InteropServices;
32 using System.Threading;
33 using System.Text.RegularExpressions;
34 using System.Runtime.InteropServices.ComTypes;
35 using System.Windows.Forms;
36
37 namespace OpenTween
38 {
39     #region "WebBrowserAPI"
40     internal static class WebBrowserAPI
41     {
42         public static int INET_E_DEFAULT_ACTION = unchecked((int)0x800C0011);
43
44         public enum URLZONE
45         {
46             URLZONE_LOCAL_MACHINE = 0,
47             URLZONE_INTRANET = URLZONE_LOCAL_MACHINE + 1,
48             URLZONE_TRUSTED = URLZONE_INTRANET + 1,
49             URLZONE_INTERNET = URLZONE_TRUSTED + 1,
50             URLZONE_UNTRUSTED = URLZONE_INTERNET + 1,
51         }
52
53         public static int URLACTION_MIN = 0x1000;
54
55         public static int URLACTION_DOWNLOAD_MIN = 0x1000;
56         public static int URLACTION_DOWNLOAD_SIGNED_ACTIVEX = 0x1001;
57         public static int URLACTION_DOWNLOAD_UNSIGNED_ACTIVEX = 0x1004;
58         public static int URLACTION_DOWNLOAD_CURR_MAX = 0x1004;
59         public static int URLACTION_DOWNLOAD_MAX = 0x11FF;
60
61         public static int URLACTION_ACTIVEX_MIN = 0x1200;
62         public static int URLACTION_ACTIVEX_RUN = 0x1200;
63         public static int URLPOLICY_ACTIVEX_CHECK_LIST = 0x10000;
64         public static int URLACTION_ACTIVEX_OVERRIDE_OBJECT_SAFETY = 0x1201;
65         public static int URLACTION_ACTIVEX_OVERRIDE_DATA_SAFETY = 0x1202;
66         public static int URLACTION_ACTIVEX_OVERRIDE_SCRIPT_SAFETY = 0x1203;
67         public static int URLACTION_SCRIPT_OVERRIDE_SAFETY = 0x1401;
68         public static int URLACTION_ACTIVEX_CONFIRM_NOOBJECTSAFETY = 0x1204;
69         public static int URLACTION_ACTIVEX_TREATASUNTRUSTED = 0x1205;
70         public static int URLACTION_ACTIVEX_NO_WEBOC_SCRIPT = 0x1206;
71         public static int URLACTION_ACTIVEX_CURR_MAX = 0x1206;
72         public static int URLACTION_ACTIVEX_MAX = 0x13FF;
73
74         public static int URLACTION_SCRIPT_MIN = 0x1400;
75         public static int URLACTION_SCRIPT_RUN = 0x1400;
76         public static int URLACTION_SCRIPT_JAVA_USE = 0x1402;
77         public static int URLACTION_SCRIPT_SAFE_ACTIVEX = 0x1405;
78         public static int URLACTION_CROSS_DOMAIN_DATA = 0x1406;
79         public static int URLACTION_SCRIPT_PASTE = 0x1407;
80         public static int URLACTION_SCRIPT_CURR_MAX = 0x1407;
81         public static int URLACTION_SCRIPT_MAX = 0x15FF;
82
83         public static int URLACTION_HTML_MIN = 0x1600;
84         public static int URLACTION_HTML_SUBMIT_FORMS = 0x1601;                                 // aggregate next two
85         public static int URLACTION_HTML_SUBMIT_FORMS_FROM = 0x1602;                            //
86         public static int URLACTION_HTML_SUBMIT_FORMS_TO = 0x1603;                              //
87         public static int URLACTION_HTML_FONT_DOWNLOAD = 0x1604;
88         public static int URLACTION_HTML_JAVA_RUN = 0x1605;                                     // derive from Java custom policy
89         public static int URLACTION_HTML_USERDATA_SAVE = 0x1606;
90         public static int URLACTION_HTML_SUBFRAME_NAVIGATE = 0x1607;
91         public static int URLACTION_HTML_META_REFRESH = 0x1608;
92         public static int URLACTION_HTML_MIXED_CONTENT = 0x1609;
93         public static int URLACTION_HTML_MAX = 0x17FF;
94
95         public static int URLACTION_SHELL_MIN = 0x1800;
96         public static int URLACTION_SHELL_INSTALL_DTITEMS = 0x1800;
97         public static int URLACTION_SHELL_MOVE_OR_COPY = 0x1802;
98         public static int URLACTION_SHELL_FILE_DOWNLOAD = 0x1803;
99         public static int URLACTION_SHELL_VERB = 0x1804;
100         public static int URLACTION_SHELL_WEBVIEW_VERB = 0x1805;
101         public static int URLACTION_SHELL_SHELLEXECUTE = 0x1806;
102         public static int URLACTION_SHELL_CURR_MAX = 0x1806;
103         public static int URLACTION_SHELL_MAX = 0x19FF;
104
105         public static int URLACTION_NETWORK_MIN = 0x1A00;
106
107         public static int URLACTION_CREDENTIALS_USE = 0x1A00;
108         public static int URLPOLICY_CREDENTIALS_SILENT_LOGON_OK = 0x0;
109         public static int URLPOLICY_CREDENTIALS_MUST_PROMPT_USER = 0x10000;
110         public static int URLPOLICY_CREDENTIALS_CONDITIONAL_PROMPT = 0x20000;
111         public static int URLPOLICY_CREDENTIALS_ANONYMOUS_ONLY = 0x30000;
112
113         public static int URLACTION_AUTHENTICATE_CLIENT = 0x1A01;
114         public static int URLPOLICY_AUTHENTICATE_CLEARTEXT_OK = 0x0;
115         public static int URLPOLICY_AUTHENTICATE_CHALLENGE_RESPONSE = 0x10000;
116         public static int URLPOLICY_AUTHENTICATE_MUTUAL_ONLY = 0x30000;
117
118
119         public static int URLACTION_COOKIES = 0x1A02;
120         public static int URLACTION_COOKIES_SESSION = 0x1A03;
121
122         public static int URLACTION_CLIENT_CERT_PROMPT = 0x1A04;
123
124         public static int URLACTION_COOKIES_THIRD_PARTY = 0x1A05;
125         public static int URLACTION_COOKIES_SESSION_THIRD_PARTY = 0x1A06;
126
127         public static int URLACTION_COOKIES_ENABLED = 0x1A10;
128
129         public static int URLACTION_NETWORK_CURR_MAX = 0x1A10;
130         public static int URLACTION_NETWORK_MAX = 0x1BFF;
131
132
133         public static int URLACTION_JAVA_MIN = 0x1C00;
134         public static int URLACTION_JAVA_PERMISSIONS = 0x1C00;
135         public static int URLPOLICY_JAVA_PROHIBIT = 0x0;
136         public static int URLPOLICY_JAVA_HIGH = 0x10000;
137         public static int URLPOLICY_JAVA_MEDIUM = 0x20000;
138         public static int URLPOLICY_JAVA_LOW = 0x30000;
139         public static int URLPOLICY_JAVA_CUSTOM = 0x800000;
140         public static int URLACTION_JAVA_CURR_MAX = 0x1C00;
141         public static int URLACTION_JAVA_MAX = 0x1CFF;
142
143
144         // The following Infodelivery actions should have no default policies
145         // in the registry.  They assume that no default policy means fall
146         // back to the global restriction.  If an admin sets a policy per
147         // zone, then it overrides the global restriction.
148
149         public static int URLACTION_INFODELIVERY_MIN = 0x1D00;
150         public static int URLACTION_INFODELIVERY_NO_ADDING_CHANNELS = 0x1D00;
151         public static int URLACTION_INFODELIVERY_NO_EDITING_CHANNELS = 0x1D01;
152         public static int URLACTION_INFODELIVERY_NO_REMOVING_CHANNELS = 0x1D02;
153         public static int URLACTION_INFODELIVERY_NO_ADDING_SUBSCRIPTIONS = 0x1D03;
154         public static int URLACTION_INFODELIVERY_NO_EDITING_SUBSCRIPTIONS = 0x1D04;
155         public static int URLACTION_INFODELIVERY_NO_REMOVING_SUBSCRIPTIONS = 0x1D05;
156         public static int URLACTION_INFODELIVERY_NO_CHANNEL_LOGGING = 0x1D06;
157         public static int URLACTION_INFODELIVERY_CURR_MAX = 0x1D06;
158         public static int URLACTION_INFODELIVERY_MAX = 0x1DFF;
159         public static int URLACTION_CHANNEL_SOFTDIST_MIN = 0x1E00;
160         public static int URLACTION_CHANNEL_SOFTDIST_PERMISSIONS = 0x1E05;
161         public static int URLPOLICY_CHANNEL_SOFTDIST_PROHIBIT = 0x10000;
162         public static int URLPOLICY_CHANNEL_SOFTDIST_PRECACHE = 0x20000;
163         public static int URLPOLICY_CHANNEL_SOFTDIST_AUTOINSTALL = 0x30000;
164         public static int URLACTION_CHANNEL_SOFTDIST_MAX = 0x1EFF;
165
166         // For each action specified above the system maintains
167         // a set of policies for the action.
168         // The only policies supported currently are permissions (i.e. is something allowed)
169         // and logging status.
170         // IMPORTANT: If you are defining your own policies don't overload the meaning of the
171         // loword of the policy. You can use the hiword to store any policy bits which are only
172         // meaningful to your action.
173         // For an example of how to do this look at the URLPOLICY_JAVA above
174
175         // Permissions
176         public static byte URLPOLICY_ALLOW = 0x0;
177         public static byte URLPOLICY_QUERY = 0x1;
178         public static byte URLPOLICY_DISALLOW = 0x3;
179
180         // Notifications are not done when user already queried.
181         public static int URLPOLICY_NOTIFY_ON_ALLOW = 0x10;
182         public static int URLPOLICY_NOTIFY_ON_DISALLOW = 0x20;
183
184         // Logging is done regardless of whether user was queried.
185         public static int URLPOLICY_LOG_ON_ALLOW = 0x40;
186         public static int URLPOLICY_LOG_ON_DISALLOW = 0x80;
187
188         public static int URLPOLICY_MASK_PERMISSIONS = 0xF;
189
190
191         public static int URLPOLICY_DONTCHECKDLGBOX = 0x100;
192
193
194         // ----------------------------------------------------------------------
195         // ここ以下は COM Interface の宣言です。
196         public static Guid IID_IProfferService = new Guid("cb728b20-f786-11ce-92ad-00aa00a74cd0");
197         public static Guid SID_SProfferService = new Guid("cb728b20-f786-11ce-92ad-00aa00a74cd0");
198         public static Guid IID_IInternetSecurityManager = new Guid("79eac9ee-baf9-11ce-8c82-00aa004ba90b");
199
200         [ComImport,
201         Guid("6d5140c1-7436-11ce-8034-00aa006009fa"),
202         InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
203         public interface IServiceProvider
204         {
205             [PreserveSig]
206             int QueryService([In] ref Guid guidService, [In] ref Guid riid, out IntPtr ppvObject);
207         }
208
209         [ComImport,
210         Guid("cb728b20-f786-11ce-92ad-00aa00a74cd0"),
211         InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
212         public interface IProfferService
213         {
214             [PreserveSig]
215             int ProfferService([In] ref Guid guidService, [In] IServiceProvider psp, out int cookie);
216
217             [PreserveSig]
218             int RevokeService([In] int cookie);
219         }
220
221         [ComImport,
222         Guid("79eac9ed-baf9-11ce-8c82-00aa004ba90b"),
223         InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
224         public interface IInternetSecurityMgrSite
225         {
226             [PreserveSig]
227             int GetWindow(out IntPtr hwnd);
228
229             [PreserveSig]
230             int EnableModeless([In, MarshalAs(UnmanagedType.Bool)] bool fEnable);
231         }
232
233         [ComImport,
234         Guid("79eac9ee-baf9-11ce-8c82-00aa004ba90b"),
235         InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
236         public interface IInternetSecurityManager
237         {
238             [PreserveSig]
239             int SetSecuritySite([In] IInternetSecurityMgrSite pSite);
240
241             [PreserveSig]
242             int GetSecuritySite(out IInternetSecurityMgrSite pSite);
243
244             [PreserveSig]
245             int MapUrlToZone([In, MarshalAs(UnmanagedType.LPWStr)] string pwszUrl, out int pdwZone, int dwFlags);
246
247             [PreserveSig]
248             int GetSecurityId([MarshalAs(UnmanagedType.LPWStr)] string pwszUrl, [MarshalAs(UnmanagedType.LPArray)] byte[] pbSecurityId, ref UInt32 pcbSecurityId, UInt32 dwReserved);
249
250             [PreserveSig]
251             int ProcessUrlAction([In, MarshalAs(UnmanagedType.LPWStr)] string pwszUrl, int dwAction, out byte pPolicy, int cbPolicy, byte pContext, int cbContext, int dwFlags, int dwReserved);
252
253             [PreserveSig]
254             int QueryCustomPolicy([In, MarshalAs(UnmanagedType.LPWStr)] string pwszUrl, ref Guid guidKey, byte ppPolicy, int pcbPolicy, byte pContext, int cbContext, int dwReserved);
255
256             [PreserveSig]
257             int SetZoneMapping(int dwZone, [In, MarshalAs(UnmanagedType.LPWStr)] string lpszPattern, int dwFlags);
258
259             [PreserveSig]
260             int GetZoneMappings(int dwZone, ref IEnumString ppenumstring, int dwFlags);
261         }
262     }
263     #endregion
264
265     public class InternetSecurityManager : WebBrowserAPI.IServiceProvider, WebBrowserAPI.IInternetSecurityManager
266     {
267     #region "HRESULT"
268         private enum HRESULT
269         {
270             S_OK = 0x0,
271             S_FALSE = 0x1,
272             E_NOTIMPL = unchecked((int)0x80004001),
273             E_NOINTERFACE = unchecked((int)0x80004002),
274         }
275     #endregion
276
277         [Flags] public enum POLICY
278         {
279             ALLOW_ACTIVEX = 0x1,
280             ALLOW_SCRIPT = 0x2,
281         }
282
283         private object ocx = new object();
284         private WebBrowserAPI.IServiceProvider ocxServiceProvider;
285         private IntPtr profferServicePtr = new IntPtr();
286         private WebBrowserAPI.IProfferService profferService;
287
288         private POLICY _Policy = 0; // DefaultですべてDisAllow
289
290         public InternetSecurityManager(WebBrowser _WebBrowser)
291         {
292             // ActiveXコントロール取得
293             _WebBrowser.Url = new Uri("about:blank"); //ActiveXを初期化する
294
295             do
296             {
297                 Thread.Sleep(100);
298                 Application.DoEvents();
299             } while (_WebBrowser.ReadyState != WebBrowserReadyState.Complete);
300
301             ocx = _WebBrowser.ActiveXInstance;
302
303             // IServiceProvider.QueryService() を使って IProfferService を取得
304             ocxServiceProvider = (WebBrowserAPI.IServiceProvider)ocx;
305
306             try
307             {
308                 ocxServiceProvider.QueryService(
309                     ref WebBrowserAPI.SID_SProfferService,
310                     ref WebBrowserAPI.IID_IProfferService, out profferServicePtr);
311             }
312             catch (SEHException ex)
313             {
314                 MyCommon.TraceOut(ex, "ocxServiceProvider.QueryService() HRESULT:" + ex.ErrorCode.ToString("X8") + Environment.NewLine);
315                 return;
316             }
317             catch (ExternalException ex)
318             {
319                 MyCommon.TraceOut(ex, "ocxServiceProvider.QueryService() HRESULT:" + ex.ErrorCode.ToString("X8") + Environment.NewLine);
320                 return;
321             }
322
323
324             profferService = (WebBrowserAPI.IProfferService)Marshal.GetObjectForIUnknown(profferServicePtr);
325
326             // IProfferService.ProfferService() を使って
327             // 自分を IInternetSecurityManager として提供
328             try
329             {
330                 profferService.ProfferService(
331                     ref WebBrowserAPI.IID_IInternetSecurityManager, this, out var cookie);
332             }
333             catch (SEHException ex)
334             {
335                 MyCommon.TraceOut(ex, "IProfferSerive.ProfferService() HRESULT:" + ex.ErrorCode.ToString("X8") + Environment.NewLine);
336                 return;
337             }
338             catch (ExternalException ex)
339             {
340                 MyCommon.TraceOut(ex, "IProfferSerive.ProfferService() HRESULT:" + ex.ErrorCode.ToString("X8") + Environment.NewLine);
341                 return;
342             }
343         }
344
345         int WebBrowserAPI.IServiceProvider.QueryService(ref Guid guidService,
346             ref Guid riid, out IntPtr ppvObject)
347         {
348
349             ppvObject = IntPtr.Zero;
350             if (guidService.CompareTo(
351                 WebBrowserAPI.IID_IInternetSecurityManager) == 0)
352             {
353                 // 自分から IID_IInternetSecurityManager を
354                 // QueryInterface して返す
355                 var punk = Marshal.GetIUnknownForObject(this);
356                 return Marshal.QueryInterface(punk, ref riid, out ppvObject);
357             }
358             return (int)HRESULT.E_NOINTERFACE;
359         }
360
361         int WebBrowserAPI.IInternetSecurityManager.GetSecurityId(string pwszUrl, byte[] pbSecurityId, ref uint pcbSecurityId, uint dwReserved)
362         {
363             return WebBrowserAPI.INET_E_DEFAULT_ACTION;
364         }
365
366         int WebBrowserAPI.IInternetSecurityManager.GetSecuritySite(out WebBrowserAPI.IInternetSecurityMgrSite pSite)
367         {
368             pSite = null;
369             return WebBrowserAPI.INET_E_DEFAULT_ACTION;
370         }
371
372         int WebBrowserAPI.IInternetSecurityManager.GetZoneMappings(int dwZone, ref IEnumString ppenumstring, int dwFlags)
373         {
374             ppenumstring = null;
375             return WebBrowserAPI.INET_E_DEFAULT_ACTION;
376         }
377
378         int WebBrowserAPI.IInternetSecurityManager.MapUrlToZone(string pwszUrl, out int pdwZone, int dwFlags)
379         {
380             pdwZone = 0;
381             if (pwszUrl == "about:blank") return WebBrowserAPI.INET_E_DEFAULT_ACTION;
382             try
383             {
384                 var urlStr = MyCommon.IDNEncode(pwszUrl);
385                 if (urlStr == null) return WebBrowserAPI.URLPOLICY_DISALLOW;
386                 var url = new Uri(urlStr);
387                 if (url.Scheme == "data")
388                 {
389                     return WebBrowserAPI.URLPOLICY_DISALLOW;
390                 }
391             }
392             catch (Exception)
393             {
394                 return WebBrowserAPI.URLPOLICY_DISALLOW;
395             }
396             return WebBrowserAPI.INET_E_DEFAULT_ACTION;
397         }
398
399         const byte URLPOLICY_ALLOW = 0;
400
401         int WebBrowserAPI.IInternetSecurityManager.ProcessUrlAction(string pwszUrl, int dwAction, out byte pPolicy, int cbPolicy, byte pContext, int cbContext, int dwFlags, int dwReserved)
402         {
403             pPolicy = URLPOLICY_ALLOW;
404             //スクリプト実行状態かを検査しポリシー設定
405             if (WebBrowserAPI.URLACTION_SCRIPT_MIN <= dwAction &
406                 dwAction <= WebBrowserAPI.URLACTION_SCRIPT_MAX)
407             {
408                 // スクリプト実行状態
409                 if ((_Policy & POLICY.ALLOW_SCRIPT) == POLICY.ALLOW_SCRIPT)
410                 {
411                     pPolicy = WebBrowserAPI.URLPOLICY_ALLOW;
412                 }
413                 else
414                 {
415                     pPolicy = WebBrowserAPI.URLPOLICY_DISALLOW;
416                 }
417                 if (Regex.IsMatch(pwszUrl, @"^https?://((api\.)?twitter\.com/|([a-zA-Z0-9]+\.)?twimg\.com/)")) pPolicy = WebBrowserAPI.URLPOLICY_ALLOW;
418                 return (int)HRESULT.S_OK;
419             }
420             // ActiveX実行状態かを検査しポリシー設定
421             if (WebBrowserAPI.URLACTION_ACTIVEX_MIN <= dwAction &
422                 dwAction <= WebBrowserAPI.URLACTION_ACTIVEX_MAX)
423             {
424                 // ActiveX実行状態
425                 if ((_Policy & POLICY.ALLOW_ACTIVEX) == POLICY.ALLOW_ACTIVEX)
426                 {
427                     pPolicy = WebBrowserAPI.URLPOLICY_ALLOW;
428                 }
429                 else
430                 {
431                     pPolicy = WebBrowserAPI.URLPOLICY_DISALLOW;
432                 }
433                 return (int)HRESULT.S_OK;
434             }
435             //他のものについてはデフォルト処理
436             return WebBrowserAPI.INET_E_DEFAULT_ACTION;
437         }
438
439         int WebBrowserAPI.IInternetSecurityManager.QueryCustomPolicy(string pwszUrl, ref Guid guidKey, byte ppPolicy, int pcbPolicy, byte pContext, int cbContext, int dwReserved)
440         {
441             return WebBrowserAPI.INET_E_DEFAULT_ACTION;
442         }
443
444         int WebBrowserAPI.IInternetSecurityManager.SetSecuritySite(WebBrowserAPI.IInternetSecurityMgrSite pSite)
445         {
446             return WebBrowserAPI.INET_E_DEFAULT_ACTION;
447         }
448
449         int WebBrowserAPI.IInternetSecurityManager.SetZoneMapping(int dwZone, string lpszPattern, int dwFlags)
450         {
451             return WebBrowserAPI.INET_E_DEFAULT_ACTION;
452         }
453
454
455         public POLICY SecurityPolicy
456         {
457             get
458             {
459                 return _Policy;
460             }
461             set
462             {
463                 _Policy = value;
464             }
465         }
466     }
467 }