OSDN Git Service

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