├── LICENSE ├── README.md ├── local-server-apps ├── Web.config ├── rule.ashx ├── transmit.ashx └── url-info.html ├── release ├── iss │ ├── scripts │ │ ├── isxdl │ │ │ ├── chinese.ini │ │ │ ├── english.ini │ │ │ ├── isxdl.dll │ │ │ └── isxdl.iss │ │ ├── products.iss │ │ └── products │ │ │ ├── dotnetfx45full.iss │ │ │ ├── dotnetfxversion.iss │ │ │ ├── fileversion.iss │ │ │ ├── msi31.iss │ │ │ ├── stringversion.iss │ │ │ └── winversion.iss │ ├── x-wall-full.iss │ └── x-wall.iss ├── plonk.exe ├── version ├── version(suggest).js ├── version-v2.xml ├── version.js ├── version_nogoa.js ├── x-wall-setup-full.exe ├── x-wall-setup.exe └── x-wall-setup.zip ├── rules ├── gfwlist.action ├── gfwlist2privoxy.js ├── rules ├── rules-v2 ├── updater.js └── x-list.txt └── src ├── App.xaml ├── App.xaml.cs ├── Classes ├── AppSetting.cs ├── GAESimulator.cs ├── GoAgent.cs ├── NotificationController.cs ├── Operation.cs ├── Plink.cs ├── Privoxy.cs ├── Profiles.cs ├── Rules.cs ├── Settings.cs └── UIBinding.cs ├── CustomRulesEditor.xaml ├── CustomRulesEditor.xaml.cs ├── GAEWizard.xaml ├── GAEWizard.xaml.cs ├── Icons ├── main.ico ├── tray.error.ico ├── tray.ok.ico ├── tray.processing.ico └── tray.stopped.ico ├── Langs ├── Default.xaml └── zh.xaml ├── MainWindow.xaml ├── MainWindow.xaml.cs ├── Properties ├── AssemblyInfo.cs ├── Resources.Designer.cs ├── Resources.resx ├── Settings.Designer.cs ├── Settings.settings └── app.manifest ├── ShowUpdateLog.xaml ├── ShowUpdateLog.xaml.cs ├── X-Wall.csproj ├── X-Wall.csproj.user ├── X-Wall.sln ├── X-Wall.suo ├── X-Wall.v12.suo ├── app.config ├── copy.bat ├── mgwz.dll ├── plink.exe ├── plonk.exe ├── post-build.txt ├── privoxy.exe └── resources ├── about-logo.png ├── icon-error.ico ├── icon.ico ├── logo-error.png ├── logo.png ├── privoxy-templates ├── connect-failed ├── connection-timeout ├── default ├── forwarding-failed ├── lang-helper.js ├── mod-content-begin ├── mod-content-end ├── mod-gfw-operation ├── mod-head ├── mod-head-error ├── mod-header ├── mod-header-error ├── mod-lang-helper ├── no-server-data ├── no-such-domain └── show-url-info ├── spirits.png └── style.css /LICENSE: -------------------------------------------------------------------------------- 1 | The Artistic License 2.0 2 | 3 | Copyright (c) 2015 LunaDream 4 | 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | This license establishes the terms under which a given free software 11 | Package may be copied, modified, distributed, and/or redistributed. 12 | The intent is that the Copyright Holder maintains some artistic 13 | control over the development of that Package while still keeping the 14 | Package available as open source and free software. 15 | 16 | You are always permitted to make arrangements wholly outside of this 17 | license directly with the Copyright Holder of a given Package. If the 18 | terms of this license do not permit the full use that you propose to 19 | make of the Package, you should contact the Copyright Holder and seek 20 | a different licensing arrangement. 21 | 22 | Definitions 23 | 24 | "Copyright Holder" means the individual(s) or organization(s) 25 | named in the copyright notice for the entire Package. 26 | 27 | "Contributor" means any party that has contributed code or other 28 | material to the Package, in accordance with the Copyright Holder's 29 | procedures. 30 | 31 | "You" and "your" means any person who would like to copy, 32 | distribute, or modify the Package. 33 | 34 | "Package" means the collection of files distributed by the 35 | Copyright Holder, and derivatives of that collection and/or of 36 | those files. A given Package may consist of either the Standard 37 | Version, or a Modified Version. 38 | 39 | "Distribute" means providing a copy of the Package or making it 40 | accessible to anyone else, or in the case of a company or 41 | organization, to others outside of your company or organization. 42 | 43 | "Distributor Fee" means any fee that you charge for Distributing 44 | this Package or providing support for this Package to another 45 | party. It does not mean licensing fees. 46 | 47 | "Standard Version" refers to the Package if it has not been 48 | modified, or has been modified only in ways explicitly requested 49 | by the Copyright Holder. 50 | 51 | "Modified Version" means the Package, if it has been changed, and 52 | such changes were not explicitly requested by the Copyright 53 | Holder. 54 | 55 | "Original License" means this Artistic License as Distributed with 56 | the Standard Version of the Package, in its current version or as 57 | it may be modified by The Perl Foundation in the future. 58 | 59 | "Source" form means the source code, documentation source, and 60 | configuration files for the Package. 61 | 62 | "Compiled" form means the compiled bytecode, object code, binary, 63 | or any other form resulting from mechanical transformation or 64 | translation of the Source form. 65 | 66 | 67 | Permission for Use and Modification Without Distribution 68 | 69 | (1) You are permitted to use the Standard Version and create and use 70 | Modified Versions for any purpose without restriction, provided that 71 | you do not Distribute the Modified Version. 72 | 73 | 74 | Permissions for Redistribution of the Standard Version 75 | 76 | (2) You may Distribute verbatim copies of the Source form of the 77 | Standard Version of this Package in any medium without restriction, 78 | either gratis or for a Distributor Fee, provided that you duplicate 79 | all of the original copyright notices and associated disclaimers. At 80 | your discretion, such verbatim copies may or may not include a 81 | Compiled form of the Package. 82 | 83 | (3) You may apply any bug fixes, portability changes, and other 84 | modifications made available from the Copyright Holder. The resulting 85 | Package will still be considered the Standard Version, and as such 86 | will be subject to the Original License. 87 | 88 | 89 | Distribution of Modified Versions of the Package as Source 90 | 91 | (4) You may Distribute your Modified Version as Source (either gratis 92 | or for a Distributor Fee, and with or without a Compiled form of the 93 | Modified Version) provided that you clearly document how it differs 94 | from the Standard Version, including, but not limited to, documenting 95 | any non-standard features, executables, or modules, and provided that 96 | you do at least ONE of the following: 97 | 98 | (a) make the Modified Version available to the Copyright Holder 99 | of the Standard Version, under the Original License, so that the 100 | Copyright Holder may include your modifications in the Standard 101 | Version. 102 | 103 | (b) ensure that installation of your Modified Version does not 104 | prevent the user installing or running the Standard Version. In 105 | addition, the Modified Version must bear a name that is different 106 | from the name of the Standard Version. 107 | 108 | (c) allow anyone who receives a copy of the Modified Version to 109 | make the Source form of the Modified Version available to others 110 | under 111 | 112 | (i) the Original License or 113 | 114 | (ii) a license that permits the licensee to freely copy, 115 | modify and redistribute the Modified Version using the same 116 | licensing terms that apply to the copy that the licensee 117 | received, and requires that the Source form of the Modified 118 | Version, and of any works derived from it, be made freely 119 | available in that license fees are prohibited but Distributor 120 | Fees are allowed. 121 | 122 | 123 | Distribution of Compiled Forms of the Standard Version 124 | or Modified Versions without the Source 125 | 126 | (5) You may Distribute Compiled forms of the Standard Version without 127 | the Source, provided that you include complete instructions on how to 128 | get the Source of the Standard Version. Such instructions must be 129 | valid at the time of your distribution. If these instructions, at any 130 | time while you are carrying out such distribution, become invalid, you 131 | must provide new instructions on demand or cease further distribution. 132 | If you provide valid instructions or cease distribution within thirty 133 | days after you become aware that the instructions are invalid, then 134 | you do not forfeit any of your rights under this license. 135 | 136 | (6) You may Distribute a Modified Version in Compiled form without 137 | the Source, provided that you comply with Section 4 with respect to 138 | the Source of the Modified Version. 139 | 140 | 141 | Aggregating or Linking the Package 142 | 143 | (7) You may aggregate the Package (either the Standard Version or 144 | Modified Version) with other packages and Distribute the resulting 145 | aggregation provided that you do not charge a licensing fee for the 146 | Package. Distributor Fees are permitted, and licensing fees for other 147 | components in the aggregation are permitted. The terms of this license 148 | apply to the use and Distribution of the Standard or Modified Versions 149 | as included in the aggregation. 150 | 151 | (8) You are permitted to link Modified and Standard Versions with 152 | other works, to embed the Package in a larger work of your own, or to 153 | build stand-alone binary or bytecode versions of applications that 154 | include the Package, and Distribute the result without restriction, 155 | provided the result does not expose a direct interface to the Package. 156 | 157 | 158 | Items That are Not Considered Part of a Modified Version 159 | 160 | (9) Works (including, but not limited to, modules and scripts) that 161 | merely extend or make use of the Package, do not, by themselves, cause 162 | the Package to be a Modified Version. In addition, such works are not 163 | considered parts of the Package itself, and are not subject to the 164 | terms of this license. 165 | 166 | 167 | General Provisions 168 | 169 | (10) Any use, modification, and distribution of the Standard or 170 | Modified Versions is governed by this Artistic License. By using, 171 | modifying or distributing the Package, you accept this license. Do not 172 | use, modify, or distribute the Package, if you do not accept this 173 | license. 174 | 175 | (11) If your Modified Version has been derived from a Modified 176 | Version made by someone other than you, you are nevertheless required 177 | to ensure that your Modified Version complies with the requirements of 178 | this license. 179 | 180 | (12) This license does not grant you the right to use any trademark, 181 | service mark, tradename, or logo of the Copyright Holder. 182 | 183 | (13) This license includes the non-exclusive, worldwide, 184 | free-of-charge patent license to make, have made, use, offer to sell, 185 | sell, import and otherwise transfer the Package with respect to any 186 | patent claims licensable by the Copyright Holder that are necessarily 187 | infringed by the Package. If you institute patent litigation 188 | (including a cross-claim or counterclaim) against any party alleging 189 | that the Package constitutes direct or contributory patent 190 | infringement, then this Artistic License to you shall terminate on the 191 | date that such litigation is filed. 192 | 193 | (14) Disclaimer of Warranty: 194 | THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS 195 | IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED 196 | WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR 197 | NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL 198 | LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL 199 | BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 200 | DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF 201 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #XWall 2 | 3 | ~~Please visit [xwall.im/en-US/](http://xwall.im/en-US/) for more information.~~ 4 | ~~请访问 [xwall.im](http://xwall.im) 了解更多.~~ 5 | 6 | 使用说明请见[这里](https://github.com/lunarlove/XWall/wiki/%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E). 7 | 8 | XWall 目前估计只有几百用户, 大家如果觉得好用的话, 欢迎在博客 (服务器在墙外要考虑被墙的风险) 或者 SNS 上推荐, 有原创教程尤佳. 9 | 10 | ![XWall Screenshot](https://raw.github.com/lunarlove/XWall/gh-pages/images/1.png) 11 | 12 | 另外顺便维护了供 Privoxy 使用的 GFWList (action 文件), 需要的同学可以下载, 默认是转发 1080 端口的 SOCKSv5 代理, 其他请参照 Privoxy 的手册自行修改了. 13 | [Privoxy GFWList Action File](https://raw.github.com/lunarlove/XWall/master/rules/gfwlist.action) 14 | -------------------------------------------------------------------------------- /local-server-apps/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 10 | 11 | 12 | 13 | 14 |
15 | 16 |
17 |
18 |
19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 46 | 47 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /local-server-apps/rule.ashx: -------------------------------------------------------------------------------- 1 | <%@ WebHandler Language="C#" Class="Rule" %> 2 | 3 | using System; 4 | using System.Web; 5 | using System.IO; 6 | 7 | public class Rule : IHttpHandler { 8 | 9 | public void ProcessRequest (HttpContext context) { 10 | var req = context.Request; 11 | var res = context.Response; 12 | var query = req.QueryString; 13 | 14 | var root = context.Server.MapPath("~/") + @"..\configs\"; 15 | string file = ""; 16 | string rule = ""; 17 | 18 | if (query["new"] != null) { 19 | file = root + "new-rule-cmd"; 20 | rule = query["new"]; 21 | } 22 | else if (query["del"] != null) { 23 | file = root + "del-rule-cmd"; 24 | rule = query["del"]; 25 | } 26 | 27 | var ruleCommandWatcher = new FileSystemWatcher(Path.GetDirectoryName(file), Path.GetFileName(file)); 28 | File.WriteAllText(file, rule); 29 | var result = (!ruleCommandWatcher.WaitForChanged(WatcherChangeTypes.Deleted, 10000).TimedOut).ToString().ToLower(); 30 | 31 | string text; 32 | if (query["callback"] != null) { 33 | res.ContentType = "text/javascript"; 34 | text = query["callback"] + "(" + result + ");"; 35 | } 36 | else { 37 | if (query["type"] != null) { 38 | res.ContentType = query["type"]; 39 | } 40 | text = result.ToString(); 41 | } 42 | res.Write(text); 43 | } 44 | 45 | public bool IsReusable { 46 | get { 47 | return false; 48 | } 49 | } 50 | 51 | } -------------------------------------------------------------------------------- /local-server-apps/transmit.ashx: -------------------------------------------------------------------------------- 1 | <%@ WebHandler Language="C#" Class="Transmit" %> 2 | 3 | using System; 4 | using System.Web; 5 | 6 | public class Transmit : IHttpHandler { 7 | 8 | public void ProcessRequest (HttpContext context) { 9 | var req = context.Request; 10 | var res = context.Response; 11 | var query = req.QueryString; 12 | 13 | if (query["file"] != null) { 14 | if (query["type"] != null) { 15 | res.ContentType = query["type"]; 16 | } 17 | if (query["nocache"] != null) { 18 | res.Cache.SetCacheability(HttpCacheability.NoCache); 19 | res.Cache.SetNoStore(); 20 | } 21 | res.BinaryWrite(System.IO.File.ReadAllBytes(context.Server.MapPath("~/") + @"..\resources\" + query["file"])); 22 | } 23 | else if (query["config"] != null) { 24 | string text; 25 | var config = System.IO.File.ReadAllText(context.Server.MapPath("~/") + @"..\configs\" + query["config"]); 26 | if (query["callback"] != null) { 27 | res.ContentType = "text/javascript"; 28 | text = query["callback"] + "(" + config + ");"; 29 | } 30 | else { 31 | if (query["type"] != null) { 32 | res.ContentType = query["type"]; 33 | } 34 | text = config; 35 | } 36 | res.Cache.SetCacheability(HttpCacheability.NoCache); 37 | res.Cache.SetNoStore(); 38 | res.Write(text); 39 | } 40 | } 41 | 42 | public bool IsReusable { 43 | get { 44 | return false; 45 | } 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /local-server-apps/url-info.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 25 |
26 |
27 |
28 |
29 |
30 |

View Whether a URL Will Be Forwarded

31 | 35 |

Please enter a URL:

36 |
37 |

38 | 39 | 40 |

41 |
42 |
43 |
44 |

查看 URL 是否会被转发

45 | 49 |

请输入一个 URL:

50 |
51 |

52 | 53 | 54 |

55 |
56 |
57 |
58 | 76 |
77 | 80 |
81 | 153 | 154 | 155 | 156 | -------------------------------------------------------------------------------- /release/iss/scripts/isxdl/chinese.ini: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lunadream/XWall/0a0a08b89a91cf323e4142e84ae9f22d29483556/release/iss/scripts/isxdl/chinese.ini -------------------------------------------------------------------------------- /release/iss/scripts/isxdl/english.ini: -------------------------------------------------------------------------------- 1 | [strings] 2 | ; General 3 | 100=File Download 4 | 101=Do you want to cancel the download? 5 | 102=%1 (%2 of %3) 6 | 103=%1 KB 7 | 104=%1 KB of %2 KB (%3%) 8 | 9 | ; Status information 10 | 110=Getting file information... 11 | 111=Redirecting to %1 12 | 112=Sending request... 13 | 113=Resolving %1 14 | 114=Connected to %1 15 | 115=Receiving... 16 | 116=Connecting to %1 17 | 18 | ; Error messages 19 | 120=Error connecting to Internet.\n\n%1 20 | 121=Error opening %1.\n\nThe server returned status code %2. 21 | 122=Error reading URL.\n\n%1 22 | 123=Error writing file %1.\n\n%2 23 | 124=Error opening file %1.\n\n%2 24 | 125='%1' is an invalid URL. 25 | 126=Error opening %1.\n\n%2 26 | 127=Error sending request.\n\n%1 27 | 128=Unsupported protocol. Only HTTP and FTP protocols are supported. 28 | 129=Failed to connect to %1.\n\n%2 29 | 130=Failed to query status code.\n\n%1 30 | 131=Error requesting file.\n\n%1 31 | 32 | ; Other 33 | 144=About... 34 | 146=Download 35 | 147=Setup is now downloading additional files to your computer. 36 | 37 | ; labels 38 | 160=File: 39 | 161=Speed: 40 | 162=Status: 41 | 163=Elapsed Time: 42 | 164=Remaining Time: 43 | 165=Current File: 44 | 166=Overall Progress: 45 | 167=Cancel 46 | 168=OK 47 | 169=User Name and Password 48 | 170=User Name: 49 | 171=Password: 50 | -------------------------------------------------------------------------------- /release/iss/scripts/isxdl/isxdl.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lunadream/XWall/0a0a08b89a91cf323e4142e84ae9f22d29483556/release/iss/scripts/isxdl/isxdl.dll -------------------------------------------------------------------------------- /release/iss/scripts/isxdl/isxdl.iss: -------------------------------------------------------------------------------- 1 | [Files] 2 | Source: "scripts\isxdl\isxdl.dll"; Flags: dontcopy 3 | 4 | [Code] 5 | //replace PAnsiChar with PChar on non-unicode Inno Setup 6 | procedure isxdl_AddFile(URL, Filename: PAnsiChar); 7 | external 'isxdl_AddFile@files:isxdl.dll stdcall'; 8 | 9 | function isxdl_DownloadFiles(hWnd: Integer): Integer; 10 | external 'isxdl_DownloadFiles@files:isxdl.dll stdcall'; 11 | 12 | //replace PAnsiChar with PChar on non-unicode Inno Setup 13 | function isxdl_SetOption(Option, Value: PAnsiChar): Integer; 14 | external 'isxdl_SetOption@files:isxdl.dll stdcall'; 15 | -------------------------------------------------------------------------------- /release/iss/scripts/products.iss: -------------------------------------------------------------------------------- 1 | #include "isxdl\isxdl.iss" 2 | 3 | [CustomMessages] 4 | DependenciesDir=MyProgramDependencies 5 | 6 | en.depdownload_msg=The following applications are required before setup can continue:%n%n%1%nDownload and install now? 7 | 8 | en.depdownload_memo_title=Download dependencies 9 | 10 | en.depinstall_memo_title=Install dependencies 11 | 12 | 13 | en.depinstall_title=Installing dependencies 14 | 15 | en.depinstall_description=Please wait while Setup installs dependencies on your computer. 16 | 17 | en.depinstall_status=Installing %1... 18 | 19 | en.depinstall_missing=%1 must be installed before setup can continue. Please install %1 and run Setup again. 20 | 21 | en.depinstall_error=An error occured while installing the dependencies. Please restart the computer and run the setup again or install the following dependencies manually:%n 22 | 23 | en.isxdl_langfile= 24 | 25 | [Files] 26 | Source: "scripts\isxdl\chinese.ini"; Flags: dontcopy 27 | 28 | [Code] 29 | type 30 | TProduct = record 31 | File: String; 32 | Title: String; 33 | Parameters: String; 34 | InstallClean : boolean; 35 | MustRebootAfter : boolean; 36 | end; 37 | 38 | InstallResult = (InstallSuccessful, InstallRebootRequired, InstallError); 39 | 40 | var 41 | installMemo, downloadMemo, downloadMessage: string; 42 | products: array of TProduct; 43 | delayedReboot: boolean; 44 | DependencyPage: TOutputProgressWizardPage; 45 | 46 | 47 | procedure AddProduct(FileName, Parameters, Title, Size, URL: string; InstallClean : boolean; MustRebootAfter : boolean); 48 | var 49 | path: string; 50 | i: Integer; 51 | begin 52 | installMemo := installMemo + '%1' + Title + #13; 53 | 54 | path := ExpandConstant('{src}{\}') + CustomMessage('DependenciesDir') + '\' + FileName; 55 | if not FileExists(path) then begin 56 | path := ExpandConstant('{tmp}{\}') + FileName; 57 | 58 | isxdl_AddFile(URL, path); 59 | 60 | downloadMemo := downloadMemo + '%1' + Title + #13; 61 | downloadMessage := downloadMessage + ' ' + Title + ' (' + Size + ')' + #13; 62 | end; 63 | 64 | i := GetArrayLength(products); 65 | SetArrayLength(products, i + 1); 66 | products[i].File := path; 67 | products[i].Title := Title; 68 | products[i].Parameters := Parameters; 69 | products[i].InstallClean := InstallClean; 70 | products[i].MustRebootAfter := MustRebootAfter; 71 | end; 72 | 73 | function SmartExec(prod : TProduct; var ResultCode : Integer) : boolean; 74 | begin 75 | if (LowerCase(Copy(prod.File,Length(prod.File)-2,3)) = 'exe') then begin 76 | Result := Exec(prod.File, prod.Parameters, '', SW_SHOWNORMAL, ewWaitUntilTerminated, ResultCode); 77 | end else begin 78 | Result := ShellExec('', prod.File, prod.Parameters, '', SW_SHOWNORMAL, ewWaitUntilTerminated, ResultCode); 79 | end; 80 | end; 81 | 82 | function PendingReboot : boolean; 83 | var names: String; 84 | begin 85 | if (RegQueryMultiStringValue(HKEY_LOCAL_MACHINE, 'SYSTEM\CurrentControlSet\Control\Session Manager', 'PendingFileRenameOperations', names)) then begin 86 | Result := true; 87 | end else if ((RegQueryMultiStringValue(HKEY_LOCAL_MACHINE, 'SYSTEM\CurrentControlSet\Control\Session Manager', 'SetupExecute', names)) and (names <> '')) then begin 88 | Result := true; 89 | end else begin 90 | Result := false; 91 | end; 92 | end; 93 | 94 | function InstallProducts: InstallResult; 95 | var 96 | ResultCode, i, productCount, finishCount: Integer; 97 | begin 98 | Result := InstallSuccessful; 99 | productCount := GetArrayLength(products); 100 | 101 | if productCount > 0 then begin 102 | DependencyPage := CreateOutputProgressPage(CustomMessage('depinstall_title'), CustomMessage('depinstall_description')); 103 | DependencyPage.Show; 104 | 105 | for i := 0 to productCount - 1 do begin 106 | if (products[i].InstallClean and (delayedReboot or PendingReboot())) then begin 107 | Result := InstallRebootRequired; 108 | break; 109 | end; 110 | 111 | DependencyPage.SetText(FmtMessage(CustomMessage('depinstall_status'), [products[i].Title]), ''); 112 | DependencyPage.SetProgress(i, productCount); 113 | 114 | if SmartExec(products[i], ResultCode) then begin 115 | //setup executed; ResultCode contains the exit code 116 | //MsgBox(products[i].Title + ' install executed. Result Code: ' + IntToStr(ResultCode), mbInformation, MB_OK); 117 | if (products[i].MustRebootAfter) then begin 118 | //delay reboot after install if we installed the last dependency anyways 119 | if (i = productCount - 1) then begin 120 | delayedReboot := true; 121 | end else begin 122 | Result := InstallRebootRequired; 123 | end; 124 | break; 125 | end else if (ResultCode = 0) then begin 126 | finishCount := finishCount + 1; 127 | end else if (ResultCode = 3010) then begin 128 | //ResultCode 3010: A restart is required to complete the installation. This message indicates success. 129 | delayedReboot := true; 130 | finishCount := finishCount + 1; 131 | end else begin 132 | Result := InstallError; 133 | break; 134 | end; 135 | end else begin 136 | //MsgBox(products[i].Title + ' install failed. Result Code: ' + IntToStr(ResultCode), mbInformation, MB_OK); 137 | Result := InstallError; 138 | break; 139 | end; 140 | end; 141 | 142 | //only leave not installed products for error message 143 | for i := 0 to productCount - finishCount - 1 do begin 144 | products[i] := products[i+finishCount]; 145 | end; 146 | SetArrayLength(products, productCount - finishCount); 147 | 148 | DependencyPage.Hide; 149 | end; 150 | end; 151 | 152 | function PrepareToInstall(var NeedsRestart: boolean): String; 153 | var 154 | i: Integer; 155 | s: string; 156 | begin 157 | delayedReboot := false; 158 | 159 | //DelTree(ExpandConstant('{app}\templates'), True, True, True); 160 | 161 | case InstallProducts() of 162 | InstallError: begin 163 | s := CustomMessage('depinstall_error'); 164 | 165 | for i := 0 to GetArrayLength(products) - 1 do begin 166 | s := s + #13 + ' ' + products[i].Title; 167 | end; 168 | 169 | Result := s; 170 | end; 171 | InstallRebootRequired: begin 172 | Result := products[0].Title; 173 | NeedsRestart := true; 174 | 175 | //write into the registry that the installer needs to be executed again after restart 176 | RegWriteStringValue(HKEY_CURRENT_USER, 'SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce', 'InstallBootstrap', ExpandConstant('{srcexe}')); 177 | end; 178 | end; 179 | end; 180 | 181 | function NeedRestart : boolean; 182 | begin 183 | if (delayedReboot) then 184 | Result := true; 185 | end; 186 | 187 | function UpdateReadyMemo(Space, NewLine, MemoUserInfoInfo, MemoDirInfo, MemoTypeInfo, MemoComponentsInfo, MemoGroupInfo, MemoTasksInfo: String): String; 188 | var 189 | s: string; 190 | begin 191 | if downloadMemo <> '' then 192 | s := s + CustomMessage('depdownload_memo_title') + ':' + NewLine + FmtMessage(downloadMemo, [Space]) + NewLine; 193 | if installMemo <> '' then 194 | s := s + CustomMessage('depinstall_memo_title') + ':' + NewLine + FmtMessage(installMemo, [Space]) + NewLine; 195 | 196 | s := s + MemoDirInfo + NewLine + NewLine + MemoGroupInfo 197 | 198 | if MemoTasksInfo <> '' then 199 | s := s + NewLine + NewLine + MemoTasksInfo; 200 | 201 | Result := s 202 | end; 203 | 204 | function NextButtonClick(CurPageID: Integer): boolean; 205 | begin 206 | Result := true; 207 | 208 | if CurPageID = wpReady then begin 209 | if downloadMemo <> '' then begin 210 | //change isxdl language only if it is not english because isxdl default language is already english 211 | if (ActiveLanguage() <> 'en') then begin 212 | ExtractTemporaryFile(CustomMessage('isxdl_langfile')); 213 | isxdl_SetOption('language', ExpandConstant('{tmp}{\}') + CustomMessage('isxdl_langfile')); 214 | end; 215 | //isxdl_SetOption('title', FmtMessage(SetupMessage(msgSetupWindowTitle), [CustomMessage('appname')])); 216 | 217 | if SuppressibleMsgBox(FmtMessage(CustomMessage('depdownload_msg'), [downloadMessage]), mbConfirmation, MB_YESNO, IDYES) = IDNO then 218 | Result := false 219 | else if isxdl_DownloadFiles(StrToInt(ExpandConstant('{wizardhwnd}'))) = 0 then 220 | Result := false; 221 | end; 222 | end; 223 | end; 224 | 225 | function IsX86: boolean; 226 | begin 227 | Result := (ProcessorArchitecture = paX86) or (ProcessorArchitecture = paUnknown); 228 | end; 229 | 230 | function IsX64: boolean; 231 | begin 232 | Result := Is64BitInstallMode and (ProcessorArchitecture = paX64); 233 | end; 234 | 235 | function IsIA64: boolean; 236 | begin 237 | Result := Is64BitInstallMode and (ProcessorArchitecture = paIA64); 238 | end; 239 | 240 | function GetString(x86, x64, ia64: String): String; 241 | begin 242 | if IsX64() and (x64 <> '') then begin 243 | Result := x64; 244 | end else if IsIA64() and (ia64 <> '') then begin 245 | Result := ia64; 246 | end else begin 247 | Result := x86; 248 | end; 249 | end; 250 | 251 | function GetArchitectureString(): String; 252 | begin 253 | if IsX64() then begin 254 | Result := '_x64'; 255 | end else if IsIA64() then begin 256 | Result := '_ia64'; 257 | end else begin 258 | Result := ''; 259 | end; 260 | end; -------------------------------------------------------------------------------- /release/iss/scripts/products/dotnetfx45full.iss: -------------------------------------------------------------------------------- 1 | // requires Windows Vista SP2, Windows 7 SP1, Windows 8, Windows 8.1, Windows Server 2008 SP2, Windows Server 2008 R2 SP1, Windows Server 2012 and Windows Server 2012 R2 2 | // requires Windows Installer 3.1 3 | // WARNING: express setup (downloads and installs the components depending on your OS) if you want to deploy it on cd or network download the full bootsrapper on website below 4 | // http://www.microsoft.com/downloads/details.aspx?FamilyID=ab99342f-5d1a-413d-8319-81da479ab0d7 5 | 6 | [CustomMessages] 7 | dotnetfx4full_title=.NET Framework 4.5.2 8 | dotnetfx4full_size=66.8MB 9 | 10 | [Code] 11 | const 12 | dotnetfx4full_url = 'http://download.microsoft.com/download/E/2/1/E21644B5-2DF2-47C2-91BD-63C560427900/NDP452-KB2901907-x86-x64-AllOS-ENU.exe'; 13 | 14 | procedure dotnetfx45(MinVersion: integer); 15 | begin 16 | if (not netfxinstalled(NetFx45, '') or (netfxspversion(NetFx45, '') < MinVersion)) then 17 | AddProduct('dotnetfx4full' + GetArchitectureString() + '.exe', 18 | '/lang:enu /passive /norestart', 19 | CustomMessage('dotnetfx4full_title'), 20 | CustomMessage('dotnetfx4full_size'), 21 | dotnetfx4full_url, 22 | false, false); 23 | end; -------------------------------------------------------------------------------- /release/iss/scripts/products/dotnetfxversion.iss: -------------------------------------------------------------------------------- 1 | [Code] 2 | type 3 | NetFXType = (NetFx10, NetFx11, NetFx20, NetFx30, NetFx35, NetFx40Client, NetFx40Full, NetFx45); 4 | 5 | const 6 | netfx11plus_reg = 'Software\Microsoft\NET Framework Setup\NDP\'; 7 | 8 | function netfxinstalled(version: NetFXType; lcid: string): boolean; 9 | var 10 | regVersion: cardinal; 11 | regVersionString: string; 12 | begin 13 | if (lcid <> '') then 14 | lcid := '\' + lcid; 15 | 16 | if (version = NetFx10) then begin 17 | RegQueryStringValue(HKLM, 'Software\Microsoft\.NETFramework\Policy\v1.0\3705', 'Install', regVersionString); 18 | Result := regVersionString <> ''; 19 | end else begin 20 | case version of 21 | NetFx11: 22 | RegQueryDWordValue(HKLM, netfx11plus_reg + 'v1.1.4322' + lcid, 'Install', regVersion); 23 | NetFx20: 24 | RegQueryDWordValue(HKLM, netfx11plus_reg + 'v2.0.50727' + lcid, 'Install', regVersion); 25 | NetFx30: 26 | RegQueryDWordValue(HKLM, netfx11plus_reg + 'v3.0\Setup' + lcid, 'InstallSuccess', regVersion); 27 | NetFx35: 28 | RegQueryDWordValue(HKLM, netfx11plus_reg + 'v3.5' + lcid, 'Install', regVersion); 29 | NetFx40Client: 30 | RegQueryDWordValue(HKLM, netfx11plus_reg + 'v4\Client' + lcid, 'Install', regVersion); 31 | NetFx40Full: 32 | RegQueryDWordValue(HKLM, netfx11plus_reg + 'v4\Full' + lcid, 'Install', regVersion); 33 | NetFx45: 34 | begin 35 | RegQueryDWordValue(HKLM, netfx11plus_reg + 'v4\Full' + lcid, 'Release', regVersion); 36 | // >= 4.5.0 and <= 4.5.?(Win10) 37 | Result := (regVersion >= 378389); 38 | Exit; 39 | end; 40 | end; 41 | Result := (regVersion <> 0); 42 | end; 43 | end; 44 | 45 | function netfxspversion(version: NetFXType; lcid: string): integer; 46 | var 47 | regVersion: cardinal; 48 | begin 49 | if (lcid <> '') then 50 | lcid := '\' + lcid; 51 | 52 | case version of 53 | NetFx10: 54 | //not supported 55 | regVersion := -1; 56 | NetFx11: 57 | if (not RegQueryDWordValue(HKLM, netfx11plus_reg + 'v1.1.4322' + lcid, 'SP', regVersion)) then 58 | regVersion := -1; 59 | NetFx20: 60 | if (not RegQueryDWordValue(HKLM, netfx11plus_reg + 'v2.0.50727' + lcid, 'SP', regVersion)) then 61 | regVersion := -1; 62 | NetFx30: 63 | if (not RegQueryDWordValue(HKLM, netfx11plus_reg + 'v3.0' + lcid, 'SP', regVersion)) then 64 | regVersion := -1; 65 | NetFx35: 66 | if (not RegQueryDWordValue(HKLM, netfx11plus_reg + 'v3.5' + lcid, 'SP', regVersion)) then 67 | regVersion := -1; 68 | NetFx40Client: 69 | if (not RegQueryDWordValue(HKLM, netfx11plus_reg + 'v4\Client' + lcid, 'Servicing', regVersion)) then 70 | regVersion := -1; 71 | NetFx40Full: 72 | if (not RegQueryDWordValue(HKLM, netfx11plus_reg + 'v4\Full' + lcid, 'Servicing', regVersion)) then 73 | regVersion := -1; 74 | NetFx45: 75 | if (RegQueryDWordValue(HKLM, netfx11plus_reg + 'v4\Full' + lcid, 'Release', regVersion)) then begin 76 | if (regVersion >= 381029) then 77 | regVersion := 9 //4.5.?(Win10) 78 | else if (regVersion = 379893) then 79 | regVersion := 2 // 4.5.2 80 | else if (regVersion = 378675) or (regVersion = 378758) then 81 | regVersion := 1 // 4.5.1 82 | else if (regVersion = 378389) then 83 | regVersion := 0 // 4.5.0 84 | else 85 | regVersion := -1; 86 | end; 87 | end; 88 | Result := regVersion; 89 | end; 90 | -------------------------------------------------------------------------------- /release/iss/scripts/products/fileversion.iss: -------------------------------------------------------------------------------- 1 | [Code] 2 | function GetFullVersion(VersionMS, VersionLS: cardinal): string; 3 | var 4 | version: string; 5 | begin 6 | version := IntToStr(word(VersionMS shr 16)); 7 | version := version + '.' + IntToStr(word(VersionMS and not $ffff0000)); 8 | 9 | version := version + '.' + IntToStr(word(VersionLS shr 16)); 10 | version := version + '.' + IntToStr(word(VersionLS and not $ffff0000)); 11 | 12 | Result := version; 13 | end; 14 | 15 | function fileversion(file: string): string; 16 | var 17 | versionMS, versionLS: cardinal; 18 | begin 19 | if GetVersionNumbers(file, versionMS, versionLS) then 20 | Result := GetFullVersion(versionMS, versionLS) 21 | else 22 | Result := '0'; 23 | end; 24 | -------------------------------------------------------------------------------- /release/iss/scripts/products/msi31.iss: -------------------------------------------------------------------------------- 1 | [CustomMessages] 2 | msi31_title=Windows Installer 3.1 3 | msi31_size=2.5 MB 4 | 5 | [Code] 6 | const 7 | msi31_url = 'http://download.microsoft.com/download/1/4/7/147ded26-931c-4daf-9095-ec7baf996f46/WindowsInstaller-KB893803-v2-x86.exe'; 8 | 9 | procedure msi31(MinVersion: string); 10 | begin 11 | // Check for required Windows Installer 3.0 on Windows 2000 or higher 12 | if (IsX86() and minwinversion(5, 0) and (compareversion(fileversion(ExpandConstant('{sys}{\}msi.dll')), MinVersion) < 0)) then 13 | AddProduct('msi31.exe', 14 | '/passive /norestart', 15 | CustomMessage('msi31_title'), 16 | CustomMessage('msi31_size'), 17 | msi31_url, 18 | false, false); 19 | end; -------------------------------------------------------------------------------- /release/iss/scripts/products/stringversion.iss: -------------------------------------------------------------------------------- 1 | function stringtoversion(var temp: String): Integer; 2 | var 3 | part: String; 4 | pos1: Integer; 5 | 6 | begin 7 | if (Length(temp) = 0) then begin 8 | Result := -1; 9 | Exit; 10 | end; 11 | 12 | pos1 := Pos('.', temp); 13 | if (pos1 = 0) then begin 14 | Result := StrToInt(temp); 15 | temp := ''; 16 | end else begin 17 | part := Copy(temp, 1, pos1 - 1); 18 | temp := Copy(temp, pos1 + 1, Length(temp)); 19 | Result := StrToInt(part); 20 | end; 21 | end; 22 | 23 | function compareinnerversion(var x, y: String): Integer; 24 | var 25 | num1, num2: Integer; 26 | 27 | begin 28 | num1 := stringtoversion(x); 29 | num2 := stringtoversion(y); 30 | if (num1 = -1) or (num2 = -1) then begin 31 | Result := 0; 32 | Exit; 33 | end; 34 | 35 | if (num1 < num2) then begin 36 | Result := -1; 37 | end else if (num1 > num2) then begin 38 | Result := 1; 39 | end else begin 40 | Result := compareinnerversion(x, y); 41 | end; 42 | end; 43 | 44 | function compareversion(versionA, versionB: String): Integer; 45 | var 46 | temp1, temp2: String; 47 | 48 | begin 49 | temp1 := versionA; 50 | temp2 := versionB; 51 | Result := compareinnerversion(temp1, temp2); 52 | end; 53 | -------------------------------------------------------------------------------- /release/iss/scripts/products/winversion.iss: -------------------------------------------------------------------------------- 1 | [Code] 2 | var 3 | WindowsVersion: TWindowsVersion; 4 | 5 | procedure initwinversion(); 6 | begin 7 | GetWindowsVersionEx(WindowsVersion); 8 | end; 9 | 10 | function exactwinversion(MajorVersion, MinorVersion: integer): boolean; 11 | begin 12 | Result := (WindowsVersion.Major = MajorVersion) and (WindowsVersion.Minor = MinorVersion); 13 | end; 14 | 15 | function minwinversion(MajorVersion, MinorVersion: integer): boolean; 16 | begin 17 | Result := (WindowsVersion.Major > MajorVersion) or ((WindowsVersion.Major = MajorVersion) and (WindowsVersion.Minor >= MinorVersion)); 18 | end; 19 | 20 | function maxwinversion(MajorVersion, MinorVersion: integer): boolean; 21 | begin 22 | Result := (WindowsVersion.Major < MajorVersion) or ((WindowsVersion.Major = MajorVersion) and (WindowsVersion.Minor <= MinorVersion)); 23 | end; 24 | 25 | function exactwinspversion(MajorVersion, MinorVersion, SpVersion: integer): boolean; 26 | begin 27 | if exactwinversion(MajorVersion, MinorVersion) then 28 | Result := WindowsVersion.ServicePackMajor = SpVersion 29 | else 30 | Result := true; 31 | end; 32 | 33 | function minwinspversion(MajorVersion, MinorVersion, SpVersion: integer): boolean; 34 | begin 35 | if exactwinversion(MajorVersion, MinorVersion) then 36 | Result := WindowsVersion.ServicePackMajor >= SpVersion 37 | else 38 | Result := true; 39 | end; 40 | 41 | function maxwinspversion(MajorVersion, MinorVersion, SpVersion: integer): boolean; 42 | begin 43 | if exactwinversion(MajorVersion, MinorVersion) then 44 | Result := WindowsVersion.ServicePackMajor <= SpVersion 45 | else 46 | Result := true; 47 | end; -------------------------------------------------------------------------------- /release/iss/x-wall-full.iss: -------------------------------------------------------------------------------- 1 | ; Script generated by the Inno Setup Script Wizard. 2 | ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! 3 | 4 | #define MyAppName "X-Wall" 5 | #define MyAppExeName "x-wall.exe" 6 | #define MyAppVersion GetFileVersion("E:\WorkSpace\XWall\src\bin\Release\x-wall.exe") 7 | #define MyAppPublisher "Groinup Studio" 8 | #define MyAppURL "http://x-wall.org" 9 | 10 | [Setup] 11 | ; NOTE: The value of AppId uniquely identifies this application. 12 | ; Do not use the same AppId value in installers for other applications. 13 | ; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) 14 | AppID={{CEE80EAA-3CD9-425B-8119-F3ECBCB5DB52} 15 | AppName={#MyAppName} 16 | AppVerName={#MyAppName} 17 | AppPublisher={#MyAppPublisher} 18 | AppPublisherURL={#MyAppURL} 19 | AppVersion={#MyAppVersion} 20 | VersionInfoVersion={#MyAppVersion} 21 | VersionInfoTextVersion={#MyAppVersion} 22 | VersionInfoCompany={#MyAppPublisher} 23 | VersionInfoCopyright={#MyAppPublisher} 24 | DefaultDirName={pf}\{#MyAppName} 25 | DefaultGroupName={#MyAppName} 26 | OutputDir=E:\WorkSpace\XWall\release 27 | OutputBaseFilename=x-wall-setup-full 28 | SetupIconFile=E:\WorkSpace\XWall\src\Icons\main.ico 29 | UninstallDisplayIcon=E:\WorkSpace\XWall\src\Icons\main.ico 30 | Compression=lzma/Max 31 | SolidCompression=true 32 | 33 | [Languages] 34 | Name: "en"; MessagesFile: "compiler:Default.isl" 35 | 36 | [Tasks] 37 | Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked 38 | 39 | [Files] 40 | Source: "E:\WorkSpace\XWall\src\bin\Release\x-wall.exe"; DestDir: "{app}"; Flags: ignoreversion 41 | Source: "E:\WorkSpace\XWall\src\bin\Release\x-wall.exe.config"; DestDir: "{app}"; Flags: ignoreversion 42 | Source: "E:\WorkSpace\XWall\src\bin\Release\WebDev.WebHost20.dll"; DestDir: "{app}"; Flags: ignoreversion 43 | Source: "E:\WorkSpace\XWall\src\bin\Release\mgwz.dll"; DestDir: "{app}"; Flags: ignoreversion 44 | Source: "E:\WorkSpace\XWall\src\bin\Release\plink.exe"; DestDir: "{app}"; Flags: ignoreversion 45 | Source: "E:\WorkSpace\XWall\src\bin\Release\plonk.exe"; DestDir: "{app}"; Flags: ignoreversion 46 | Source: "E:\WorkSpace\XWall\src\bin\Release\privoxy.exe"; DestDir: "{app}"; Flags: ignoreversion 47 | Source: "E:\WorkSpace\XWall\local-server-apps\*"; DestDir: "{commonappdata}\{#MyAppName}\local-server-apps"; Flags: ignoreversion recursesubdirs 48 | Source: "E:\WorkSpace\XWall\src\resources\*"; DestDir: "{commonappdata}\{#MyAppName}\resources"; Flags: ignoreversion recursesubdirs 49 | Source: "E:\WorkSpace\XWall\rules\rules-v2"; DestDir: "{commonappdata}\{#MyAppName}\configs"; DestName: "online-rules"; Flags: ignoreversion; Permissions: authusers-full 50 | Source: "E:\WorkSpace\XWall\goagent\*"; DestDir: "{commonappdata}\X-Wall\goagent"; Flags: ignoreversion recursesubdirs; Permissions: authusers-full 51 | 52 | [Icons] 53 | Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}" 54 | Name: "{userdesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon 55 | 56 | [Run] 57 | Filename: "{commonappdata}\{#MyAppName}\goagent\local\python27.exe"; Parameters: """{commonappdata}\{#MyAppName}\goagent\local\import-ca.py"""; Flags: runhidden 58 | Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, "&", "&&")}}"; Flags: nowait postinstall runascurrentuser 59 | 60 | #include "scripts\products.iss" 61 | 62 | #include "scripts\products\stringversion.iss" 63 | #include "scripts\products\winversion.iss" 64 | #include "scripts\products\fileversion.iss" 65 | #include "scripts\products\dotnetfxversion.iss" 66 | 67 | #include "scripts\products\msi31.iss" 68 | #include "scripts\products\dotnetfx45full.iss" 69 | 70 | [Registry] 71 | Root: "HKCR"; Subkey: "xwall"; Flags: deletekey 72 | 73 | [InstallDelete] 74 | Type: files; Name: "{commondesktop}\{#MyAppName}.lnk" 75 | Type: filesandordirs; Name: "{app}\templates" 76 | Type: filesandordirs; Name: "{app}\local-server-apps" 77 | Type: filesandordirs; Name: "{app}\configs" 78 | Type: filesandordirs; Name: "{app}\resources" 79 | Type: files; Name: "{app}\online-rules" 80 | Type: files; Name: "{app}\update-mark" 81 | Type: files; Name: "{app}\privoxy.config" 82 | Type: files; Name: "{app}\privoxy.action" 83 | Type: filesandordirs; Name: "{commonappdata}\{#MyAppName}\goagent" 84 | 85 | [CustomMessages] 86 | win_sp_title=Windows %1 Service Pack %2 87 | 88 | [UninstallDelete] 89 | Type: filesandordirs; Name: "{app}" 90 | Type: filesandordirs; Name: "{commonappdata}\{#MyAppName}" 91 | 92 | [Dirs] 93 | 94 | [Code] 95 | Function InitializeSetup : Boolean; 96 | var 97 | ResultCode : Integer; 98 | begin 99 | initwinversion(); 100 | msi31('3.1'); 101 | dotnetfx45(2); 102 | Result := true; 103 | end; 104 | 105 | Function InitializeUninstall : Boolean; 106 | var 107 | ResultCode : Integer; 108 | begin 109 | Exec(ExpandConstant('{app}\x-wall.exe'),'uninstall', '', SW_HIDE, ewWaitUntilTerminated, ResultCode); 110 | Result := true; 111 | end; 112 | -------------------------------------------------------------------------------- /release/iss/x-wall.iss: -------------------------------------------------------------------------------- 1 | ; Script generated by the Inno Setup Script Wizard. 2 | ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! 3 | 4 | #define MyAppName "X-Wall" 5 | #define MyAppExeName "x-wall.exe" 6 | #define MyAppVersion GetFileVersion("E:\WorkSpace\XWall\src\bin\Release\x-wall.exe") 7 | #define MyAppPublisher "LunaTech Inc." 8 | #define MyAppURL "https://github.com/lunarlove/XWall" 9 | 10 | [Setup] 11 | ; NOTE: The value of AppId uniquely identifies this application. 12 | ; Do not use the same AppId value in installers for other applications. 13 | ; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) 14 | AppID={{CEE80EAA-3CD9-425B-8119-F3ECBCB5DB52} 15 | AppName={#MyAppName} 16 | AppVerName={#MyAppName} 17 | AppPublisher={#MyAppPublisher} 18 | AppPublisherURL={#MyAppURL} 19 | AppVersion={#MyAppVersion} 20 | VersionInfoVersion={#MyAppVersion} 21 | VersionInfoTextVersion={#MyAppVersion} 22 | VersionInfoCompany={#MyAppPublisher} 23 | VersionInfoCopyright={#MyAppPublisher} 24 | DefaultDirName={pf}\{#MyAppName} 25 | DefaultGroupName={#MyAppName} 26 | OutputDir=E:\WorkSpace\XWall\release 27 | OutputBaseFilename=x-wall-setup 28 | SetupIconFile=E:\WorkSpace\XWall\src\Icons\main.ico 29 | UninstallDisplayIcon=E:\WorkSpace\XWall\src\Icons\main.ico 30 | Compression=lzma/Max 31 | SolidCompression=true 32 | MinVersion=6.0 33 | 34 | [Languages] 35 | Name: "en"; MessagesFile: "compiler:Default.isl" 36 | 37 | [Tasks] 38 | Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked 39 | 40 | [Files] 41 | Source: "E:\WorkSpace\XWall\src\bin\Release\x-wall.exe"; DestDir: "{app}"; Flags: ignoreversion 42 | Source: "E:\WorkSpace\XWall\src\bin\Release\x-wall.exe.config"; DestDir: "{app}"; Flags: ignoreversion 43 | Source: "E:\WorkSpace\XWall\src\bin\Release\WebDev.WebHost20.dll"; DestDir: "{app}"; Flags: ignoreversion 44 | Source: "E:\WorkSpace\XWall\src\bin\Release\mgwz.dll"; DestDir: "{app}"; Flags: ignoreversion 45 | Source: "E:\WorkSpace\XWall\src\bin\Release\plink.exe"; DestDir: "{app}"; Flags: ignoreversion 46 | Source: "E:\WorkSpace\XWall\src\bin\Release\plonk.exe"; DestDir: "{app}"; Flags: ignoreversion 47 | Source: "E:\WorkSpace\XWall\src\bin\Release\privoxy.exe"; DestDir: "{app}"; Flags: ignoreversion 48 | Source: "E:\WorkSpace\XWall\local-server-apps\*"; DestDir: "{commonappdata}\{#MyAppName}\local-server-apps"; Flags: ignoreversion recursesubdirs 49 | Source: "E:\WorkSpace\XWall\src\resources\*"; DestDir: "{commonappdata}\{#MyAppName}\resources"; Flags: ignoreversion recursesubdirs 50 | Source: "E:\WorkSpace\XWall\rules\rules-v2"; DestDir: "{commonappdata}\{#MyAppName}\configs"; DestName: "online-rules"; Flags: ignoreversion; Permissions: authusers-full 51 | 52 | [Icons] 53 | Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}" 54 | Name: "{userdesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon 55 | 56 | [Run] 57 | Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, "&", "&&")}}"; Flags: nowait postinstall runascurrentuser 58 | 59 | #include "scripts\products.iss" 60 | 61 | #include "scripts\products\stringversion.iss" 62 | #include "scripts\products\winversion.iss" 63 | #include "scripts\products\fileversion.iss" 64 | #include "scripts\products\dotnetfxversion.iss" 65 | 66 | #include "scripts\products\msi31.iss" 67 | #include "scripts\products\dotnetfx45full.iss" 68 | 69 | [Registry] 70 | Root: "HKCR"; Subkey: "xwall"; Flags: deletekey 71 | 72 | [InstallDelete] 73 | Type: files; Name: "{commondesktop}\{#MyAppName}.lnk" 74 | Type: filesandordirs; Name: "{app}\templates" 75 | Type: filesandordirs; Name: "{app}\local-server-apps" 76 | Type: filesandordirs; Name: "{app}\configs" 77 | Type: filesandordirs; Name: "{app}\resources" 78 | Type: files; Name: "{app}\online-rules" 79 | Type: files; Name: "{app}\update-mark" 80 | Type: files; Name: "{app}\privoxy.config" 81 | Type: files; Name: "{app}\privoxy.action" 82 | 83 | [CustomMessages] 84 | win_sp_title=Windows %1 Service Pack %2 85 | 86 | [UninstallDelete] 87 | Type: filesandordirs; Name: "{app}" 88 | Type: filesandordirs; Name: "{commonappdata}\{#MyAppName}" 89 | 90 | [Dirs] 91 | 92 | [Code] 93 | Function InitializeSetup : Boolean; 94 | var 95 | ResultCode : Integer; 96 | begin 97 | initwinversion(); 98 | msi31('3.1'); 99 | dotnetfx45(2); 100 | Result := true; 101 | end; 102 | 103 | Function InitializeUninstall : Boolean; 104 | var 105 | ResultCode : Integer; 106 | begin 107 | Exec(ExpandConstant('{app}\x-wall.exe'),'uninstall', '', SW_HIDE, ewWaitUntilTerminated, ResultCode); 108 | Result := true; 109 | end; 110 | -------------------------------------------------------------------------------- /release/plonk.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lunadream/XWall/0a0a08b89a91cf323e4142e84ae9f22d29483556/release/plonk.exe -------------------------------------------------------------------------------- /release/version: -------------------------------------------------------------------------------- 1 | 1.3.5592.39489 2 | 1.3.5553.35642 3 | XWall 1.3.5592.39489 更新日志 \newline-- 基于 1.3.5553.35642 --\newline1.增加了使用私钥连接SSH服务器的功能 -------------------------------------------------------------------------------- /release/version(suggest).js: -------------------------------------------------------------------------------- 1 | var fso = new ActiveXObject("Scripting.FileSystemObject"); 2 | 3 | var version = fso.getFileVersion("x-wall-setup.exe"); 4 | 5 | var file = fso.openTextFile("version"); 6 | var info = file.readAll(); 7 | file.close(); 8 | 9 | var versions = info.split("\r\n"); 10 | versions[0] = versions[1] = version; 11 | 12 | file = fso.createTextFile("version"); 13 | file.write(versions.join("\r\n")); 14 | file.close(); 15 | 16 | //file = fso.createTextFile("..\\..\\gh-pages\\release\\version"); 17 | //file.write(version); 18 | //file.close(); -------------------------------------------------------------------------------- /release/version-v2.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 1.3.5553.35642 4 | 1.3.5592.39489 5 | false 6 | https://github.com/lunarlove/XWall/raw/master/release/x-wall-setup.exe 7 | https://github.com/lunarlove/XWall/raw/master/release/x-wall-setup-full.exe 8 | XWall 1.3.5592.39489 更新日志\newline\newline-- 基于1.3.5553.35642\newline1.增加了使用私钥连接SSH服务器的功能 9 | -------------------------------------------------------------------------------- /release/version.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | var shell = new ActiveXObject("WScript.Shell"); 3 | var result = shell.run('"C:\\Program Files (x86)\\Inno Setup 5\\ISCC.exe" "E:\\WorkSpace\\XWall\\release\\iss\\x-wall.iss"', 1, true); 4 | result = result || shell.run('"C:\\Program Files (x86)\\Inno Setup 5\\ISCC.exe" "E:\\WorkSpace\\XWall\\release\\iss\\x-wall-full.iss"', 1, true); 5 | 6 | if (result != 0) { 7 | WScript.echo("Build installer failed."); 8 | return; 9 | } 10 | 11 | var fso = new ActiveXObject("Scripting.FileSystemObject"); 12 | try { 13 | fso.deleteFile("x-wall-setup-with-plonk.exe"); 14 | } 15 | catch (e) { } 16 | 17 | //shell.run("cmd /c mklink /h x-wall-setup-with-plonk.exe x-wall-setup.exe"); 18 | 19 | var version = fso.getFileVersion("x-wall-setup.exe"); 20 | 21 | var file = fso.openTextFile("version"); 22 | var info = file.readAll(); 23 | file.close(); 24 | 25 | var versions = info.split("\r\n"); 26 | versions[0] = version; 27 | 28 | file = fso.createTextFile("version"); 29 | file.write(versions.join("\r\n")); 30 | file.close(); 31 | 32 | //file = fso.createTextFile("..\\..\\gh-pages\\release\\version"); 33 | //file.write(version); 34 | //file.close(); 35 | })(); -------------------------------------------------------------------------------- /release/version_nogoa.js: -------------------------------------------------------------------------------- 1 | var fso = new ActiveXObject("Scripting.FileSystemObject"); 2 | 3 | var version = fso.getFileVersion("x-wall-setup.exe"); 4 | 5 | var file = fso.openTextFile("version"); 6 | var info = file.readAll(); 7 | file.close(); 8 | 9 | var versions = info.split("\r\n"); 10 | versions[0] = version; 11 | 12 | file = fso.createTextFile("version"); 13 | file.write(versions.join("\r\n")); 14 | file.close(); 15 | 16 | //file = fso.createTextFile("..\\..\\gh-pages\\release\\version"); 17 | //file.write(version); 18 | //file.close(); -------------------------------------------------------------------------------- /release/x-wall-setup-full.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lunadream/XWall/0a0a08b89a91cf323e4142e84ae9f22d29483556/release/x-wall-setup-full.exe -------------------------------------------------------------------------------- /release/x-wall-setup.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lunadream/XWall/0a0a08b89a91cf323e4142e84ae9f22d29483556/release/x-wall-setup.exe -------------------------------------------------------------------------------- /release/x-wall-setup.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lunadream/XWall/0a0a08b89a91cf323e4142e84ae9f22d29483556/release/x-wall-setup.zip -------------------------------------------------------------------------------- /rules/gfwlist2privoxy.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lunadream/XWall/0a0a08b89a91cf323e4142e84ae9f22d29483556/rules/gfwlist2privoxy.js -------------------------------------------------------------------------------- /rules/updater.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lunadream/XWall/0a0a08b89a91cf323e4142e84ae9f22d29483556/rules/updater.js -------------------------------------------------------------------------------- /rules/x-list.txt: -------------------------------------------------------------------------------- 1 | ! GFW Related Sites 2 | x-wall.org 3 | 4 | ! Contents 5 | ||zh.wikipedia.org 6 | ||wikipedia.org/search-redirect.php?*language=zh 7 | 8 | ! Google Related 9 | ||google. 10 | ||googleusercontent.com 11 | ||googleapis.com 12 | ||g.doubleclick.net 13 | ||adsense.com 14 | 15 | ! Others 16 | @@||baidu.com 17 | @@||xunlei.com 18 | @@||youdao.com 19 | @@||weibo.com 20 | @@||renren.com 21 | @@||youku.com 22 | @@||sina.com.cn 23 | @@||163.com 24 | @@||126.com 25 | @@||qq.com 26 | @@||taobao.com 27 | @@||tmall.com 28 | @@||jd.com -------------------------------------------------------------------------------- /src/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Data; 5 | using System.Diagnostics; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Windows; 9 | using System.Deployment; 10 | using XWall.Properties; 11 | using System.Globalization; 12 | using System.Text.RegularExpressions; 13 | using System.Reflection; 14 | using Microsoft.Win32; 15 | using System.Net; 16 | using System.Web; 17 | 18 | namespace XWall { 19 | /// 20 | /// Interaction logic for App.xaml 21 | /// 22 | public partial class App : Application { 23 | public static bool IsShutDown = false; 24 | public static string AppDataDirectory = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) + @"\X-Wall\"; 25 | public static bool Updated = false; 26 | public static bool FirstRun = false; 27 | 28 | protected override void OnStartup(StartupEventArgs eventArgs) { 29 | base.OnStartup(eventArgs); 30 | LoadLanguage(); 31 | var resources = App.Current.Resources; 32 | 33 | var executablePath = System.Windows.Forms.Application.ExecutablePath; 34 | Environment.CurrentDirectory = Path.GetDirectoryName(executablePath); 35 | Microsoft.Win32.SystemEvents.SessionEnding += (sender, e) => { 36 | try { 37 | IsShutDown = true; 38 | App.Current.Shutdown(); 39 | } 40 | catch { } 41 | }; 42 | 43 | var settings = Settings.Default; 44 | 45 | Directory.CreateDirectory(AppDataDirectory); 46 | Directory.CreateDirectory(AppDataDirectory + settings.ConfigsFolderName); 47 | Directory.CreateDirectory(AppDataDirectory + settings.ResourcesFolderName); 48 | 49 | var ignoreRunningInstance = false; 50 | 51 | if (eventArgs.Args.Length > 0) { 52 | var commandStr = eventArgs.Args[0]; 53 | var match = new Regex(@"^(.*?)(?:/(.*))?$").Match(commandStr); 54 | var command = match.Groups[1].Value; 55 | var commandArg = match.Groups[2].Value; 56 | 57 | switch (command) { 58 | case "uninstall": 59 | Operation.KillProcess(executablePath); 60 | Operation.KillProcess(settings.PrivoxyFileName); 61 | Operation.KillProcess(settings.PlinkFileName); 62 | if (settings.SetProxyAutomatically) { 63 | Operation.Proxies.RestoreProxy(); 64 | } 65 | Operation.SetAutoStart(false); 66 | //Operation.RegisterXWallProtocol(false); 67 | IsShutDown = true; 68 | App.Current.Shutdown(); 69 | return; 70 | case "restart": 71 | ignoreRunningInstance = true; 72 | break; 73 | //case "xwall:new-rule": 74 | // File.WriteAllText(settings.ConfigsFolderName + settings.NewRuleFileName, commandArg); 75 | // IsShutDown = true; 76 | // App.Current.Shutdown(); 77 | // return; 78 | //case "xwall:del-rule": 79 | // File.WriteAllText(settings.ConfigsFolderName + settings.DeleteRuleFileName, commandArg); 80 | // IsShutDown = true; 81 | // App.Current.Shutdown(); 82 | // return; 83 | default: 84 | break; 85 | } 86 | } 87 | 88 | if (!ignoreRunningInstance) { 89 | Process current = Process.GetCurrentProcess(); 90 | MessageBoxResult? result = null; 91 | foreach (Process process in Process.GetProcessesByName(current.ProcessName)) { 92 | if (process.Id != current.Id) { 93 | if (result == null) 94 | result = MessageBox.Show(resources["XWallAlreadyStartedDescription"] as string, resources["XWallTitle"] as string, MessageBoxButton.OKCancel); 95 | if (result == MessageBoxResult.OK) { 96 | try { 97 | process.Kill(); 98 | } 99 | catch { } 100 | } 101 | else { 102 | IsShutDown = true; 103 | App.Current.Shutdown(); 104 | return; 105 | } 106 | } 107 | } 108 | } 109 | 110 | if (settings.UpgradeRequired) { 111 | settings.Upgrade(); 112 | settings.UpgradeRequired = false; 113 | 114 | if (!settings.FirstRun) { 115 | Updated = true; 116 | } 117 | } 118 | 119 | if (settings.FirstRun || settings.ToUseGoAgent) { 120 | if (settings.ToUseGoAgent) { 121 | settings.ToUseGoAgent = false; 122 | } 123 | 124 | if (Directory.Exists(AppDataDirectory + settings.GaFolderName)) { 125 | settings.ProxyType = "GA"; 126 | } 127 | } 128 | 129 | if (settings.ProxyType == "GA" && !Directory.Exists(AppDataDirectory + settings.GaFolderName)) { 130 | settings.ProxyType = "SSH"; 131 | } 132 | 133 | if (settings.FirstRun) { 134 | settings.FirstRun = false; 135 | FirstRun = true; 136 | 137 | //first time stuffs. 138 | Operation.SetAvailablePorts(); 139 | } 140 | 141 | //* DEBUG CODE 142 | var autoStart = Operation.SetAutoStart(settings.AutoStart); 143 | if (autoStart != settings.AutoStart) 144 | settings.AutoStart = autoStart; 145 | 146 | if (settings.SetProxyAutomatically) { 147 | Operation.Proxies.SetXWallProxy(); 148 | } 149 | //Operation.RegisterXWallProtocol(true); 150 | 151 | settings.PropertyChanged += (sender, e) => { 152 | switch (e.PropertyName) { 153 | case "ProxyPort": break; 154 | default: return; 155 | } 156 | 157 | if (settings.SetProxyAutomatically) { 158 | Operation.Proxies.SetXWallProxy(); 159 | } 160 | }; 161 | 162 | settings.PropertyChanged += (sender, e) => { 163 | switch (e.PropertyName) { 164 | case "AutoStart": break; 165 | default: return; 166 | } 167 | 168 | var rst = Operation.SetAutoStart(settings.AutoStart); 169 | if (rst != settings.AutoStart) 170 | settings.AutoStart = rst; 171 | }; 172 | 173 | //Operation.SetAvailablePorts(); 174 | 175 | App.Current.Exit += (sender, e) => { 176 | if (settings.SetProxyAutomatically) { 177 | Operation.Proxies.RestoreProxy(); 178 | } 179 | }; 180 | 181 | SystemEvents.SessionEnded += (sender, e) => { 182 | try { 183 | App.Current.Shutdown(); 184 | } 185 | catch { } 186 | }; 187 | 188 | Dispatcher.UnhandledException += (sender, e) => { 189 | var query = HttpUtility.ParseQueryString(""); 190 | query["data"] = Assembly.GetExecutingAssembly().GetName().Version.ToString() + "\r\n" + e.Exception.ToString(); 191 | 192 | var client = new WebClient(); 193 | client.UploadValuesAsync(new Uri(settings.ErrorReportUrl), query); 194 | 195 | var msg = (resources["UnhandledExceptionMessage"] as string).Replace("%n", Environment.NewLine); 196 | MessageBox.Show(msg+e.Exception.ToString(), resources["XWall"] as string, MessageBoxButton.OK, MessageBoxImage.Error); 197 | 198 | e.Handled = true; 199 | }; 200 | //*/ 201 | } 202 | 203 | private void LoadLanguage() { 204 | CultureInfo currentCultureInfo = CultureInfo.CurrentCulture; 205 | 206 | var files = new string[] { 207 | //@"Langs\zh.xaml", 208 | @"Langs\" + currentCultureInfo.TwoLetterISOLanguageName + ".xaml", 209 | @"Langs\" + currentCultureInfo.Name + ".xaml" 210 | }; 211 | 212 | foreach (var file in files) { 213 | try { 214 | var uri = new Uri(file, UriKind.Relative); 215 | var dictionary = Application.LoadComponent(uri) as ResourceDictionary; 216 | this.Resources.MergedDictionaries.Add(dictionary); 217 | } catch { } 218 | } 219 | } 220 | } 221 | } 222 | -------------------------------------------------------------------------------- /src/Classes/AppSetting.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Configuration; 7 | using XWall.Properties; 8 | using System.IO; 9 | using System.Xml.Linq; 10 | using System.Xml; 11 | using System.Windows; 12 | using System.Diagnostics; 13 | 14 | namespace XWall 15 | { 16 | public class AppSetting 17 | { 18 | static Settings mysettings = XWall.Properties.Settings.Default; 19 | static string[] userSettings = {"ProxyType","SshServer","SshPort","SshUsername","SshPassword","HttpServer","HttpPort","AutoStart","ListenToLocalOnly","ProxyPort","SshCompression","SshSocksPort","CustomRulesAddSubdomains","UpgradeRequired","SshAutoReconnect","OnlineRulesLastUpdateTime","UseOnlineRules","CustomRules","FirstRun","OriginalProxies","DismissedUpdateVersion","SshNotification","SubmitNewRule","SubmitNewRuleAsked","SshUsePlonk","SshPlonkKeyword","SshReconnectAnyCondition","SshProfiles","SshSelectedProfileIndex","ForwardAll","SetProxyAutomatically","SocksServer","SocksPort","UseIntranetProxy","IntranetProxyServer","IntranetProxyPort","GaAppIds","GaPort","GaProfile","ToUseGoAgent","GaLastServerVersion" }; 20 | readonly static string confFile = Environment.CurrentDirectory + "\\Application.conf"; 21 | public static void SettingUpgrade(){ 22 | XElement xElement = new XElement(new XElement("XWall.SettingsXML")); 23 | foreach (string sp in userSettings) 24 | { 25 | xElement.Add(new XElement(sp, Settings.Default[sp].ToString())); 26 | } 27 | XmlWriterSettings settings = new XmlWriterSettings(); 28 | settings.Encoding = ASCIIEncoding.UTF8; 29 | settings.Indent = true; 30 | XmlWriter writer = XmlWriter.Create(confFile, settings); 31 | xElement.Save(writer); 32 | writer.Flush(); 33 | writer.Close(); 34 | Process.Start(System.Windows.Forms.Application.ExecutablePath, "restart"); 35 | App.Current.Shutdown(); 36 | } 37 | public static string ReadSetting(string settingName) 38 | { 39 | if (IsFileExist()) 40 | { 41 | XmlDocument xmlDoc = new XmlDocument(); 42 | xmlDoc.Load(confFile); 43 | try 44 | { 45 | return xmlDoc.SelectSingleNode("Xwall.SettingsXML//" + settingName).InnerText; 46 | } 47 | catch 48 | { 49 | return null; 50 | } 51 | } 52 | else 53 | { 54 | return null; 55 | } 56 | 57 | } 58 | public static bool IsFileExist() 59 | { 60 | if (System.IO.File.Exists(confFile)) 61 | { 62 | return true; 63 | } 64 | else 65 | { 66 | return false; 67 | } 68 | } 69 | public static bool WriteSetting(string settingName, string settingValue) 70 | { 71 | if (IsFileExist()) 72 | { 73 | try 74 | { 75 | XmlDocument xmlDoc = new XmlDocument(); 76 | xmlDoc.Load(confFile); 77 | XmlElement element = (XmlElement)xmlDoc.SelectSingleNode("Xwall.SettingsXML//" + settingName); 78 | element.InnerText = settingValue; 79 | xmlDoc.Save(confFile); 80 | } 81 | catch 82 | { 83 | return false; 84 | } 85 | return true; 86 | } 87 | else 88 | { 89 | return false; 90 | } 91 | } 92 | public static void MoveOldConfig() 93 | { 94 | string groinupDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\Groinup"; 95 | if (System.IO.Directory.Exists(groinupDir)) 96 | { 97 | if (!File.Exists(groinupDir + "\\Updated")) 98 | { 99 | DirectoryInfo directoryInfo = new DirectoryInfo(groinupDir); 100 | DirectoryInfo[] arrayDir = directoryInfo.GetDirectories(); 101 | SortAsFolderModifyTime(ref arrayDir); 102 | string lastversionAppdir = groinupDir + "\\" + arrayDir[0].Name; 103 | directoryInfo = new DirectoryInfo(lastversionAppdir); 104 | arrayDir = directoryInfo.GetDirectories(); 105 | SortAsFolderModifyTime(ref arrayDir); 106 | string lastversionCFGdir = lastversionAppdir + "\\" + arrayDir[0].Name; 107 | var result = mysettings.Import(lastversionCFGdir + "\\user.config"); 108 | if (!result) 109 | { 110 | MessageBox.Show(App.Current.Resources["FailedImportSettings"] as string); 111 | } 112 | else 113 | { 114 | File.WriteAllText(groinupDir + "\\Updated", null); 115 | MessageBox.Show(App.Current.Resources["UpdateSuccessDetails"] as string, App.Current.Resources["UpdateSuccessTitle"] as string, MessageBoxButton.OK, MessageBoxImage.Information); 116 | Process.Start(System.Windows.Forms.Application.ExecutablePath, "restart"); 117 | App.Current.Shutdown(); 118 | } 119 | } 120 | } 121 | } 122 | private static void SortAsFolderModifyTime(ref DirectoryInfo[] dirs) 123 | { 124 | Array.Sort(dirs, delegate(DirectoryInfo x, DirectoryInfo y) { return y.LastWriteTime.CompareTo(x.LastWriteTime); }); 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/Classes/GoAgent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Security.Principal; 7 | using System.Text; 8 | using System.Threading; 9 | using System.Windows; 10 | using XWall.Properties; 11 | 12 | namespace XWall { 13 | class GoAgent { 14 | static Settings settings = Settings.Default; 15 | static ResourceDictionary resources = App.Current.Resources; 16 | Process process; 17 | bool stop; 18 | static string configTpl; 19 | bool startPending = false; 20 | 21 | public GoAgent() { 22 | Operation.KillProcess(App.AppDataDirectory + settings.GaPython27FileName); 23 | App.Current.Exit += (sender, e) => { 24 | Stop(); 25 | }; 26 | 27 | settings.PropertyChanged += (sender, e) => { 28 | switch (e.PropertyName) { 29 | case "ProxyType": break; 30 | case "GaPort": break; 31 | case "GaProfile": break; 32 | case "GaAppIds": break; 33 | default: return; 34 | } 35 | 36 | if (settings.ProxyType == "GA") { 37 | GenerateConfigFile(); 38 | } 39 | }; 40 | 41 | if (settings.ProxyType == "GA") { 42 | GenerateConfigFile(); 43 | } 44 | } 45 | 46 | public static void GenerateConfigFile() { 47 | if (String.IsNullOrEmpty(configTpl)) { 48 | configTpl = File.ReadAllText(App.AppDataDirectory + settings.GaConfigTemplateFileName); 49 | } 50 | 51 | var configText = 52 | configTpl.Replace("$port$", settings.GaPort.ToString()) 53 | .Replace("$profile$", settings.GaProfile) 54 | .Replace("$app-ids$", settings.GaAppIds); 55 | 56 | File.WriteAllText(App.AppDataDirectory + settings.GaConfigFileName, configText); 57 | Operation.GrantAccessControl(App.AppDataDirectory + settings.GaConfigFileName); 58 | } 59 | 60 | public event Action Started = () => { }; 61 | public event Action Stopped = () => { }; 62 | public event Action RequireRunas = () => { }; 63 | 64 | void startProcess() { 65 | if (Environment.HasShutdownStarted) return; 66 | 67 | stop = false; 68 | process = new Process(); 69 | 70 | var si = process.StartInfo; 71 | 72 | si.FileName = App.AppDataDirectory + settings.GaPython27FileName; 73 | si.Arguments = '"' + App.AppDataDirectory + settings.GaScriptFileName + '"'; 74 | si.CreateNoWindow = true; 75 | si.UseShellExecute = false; 76 | 77 | process.Start(); 78 | 79 | Started(); 80 | 81 | process.WaitForExit(); 82 | 83 | Stopped(); 84 | 85 | if (!stop) { 86 | new Action(() => { 87 | Thread.Sleep(2000); 88 | if ((process == null || process.HasExited) && !startPending) { 89 | startProcess(); 90 | } 91 | }).BeginInvoke(null, null); 92 | } 93 | } 94 | 95 | public void Start() { 96 | Stop(); 97 | if (settings.GaAppIds != "" && settings.GaAppIds != "goagent") { 98 | new Action(() => { 99 | startPending = true; 100 | Thread.Sleep(100); 101 | startProcess(); 102 | startPending = false; 103 | }).BeginInvoke(null, null); 104 | } 105 | } 106 | 107 | public void Stop() { 108 | stop = true; 109 | try { 110 | process.Kill(); 111 | } 112 | catch { } 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/Classes/NotificationController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Windows.Forms; 6 | using System.Drawing; 7 | using System.Diagnostics; 8 | 9 | namespace XWall { 10 | partial class MainWindow { 11 | class NotificationController { 12 | NotifyIcon icon; 13 | MainWindow window; 14 | public enum Status { Stopped = 0, Processing = 1, OK = 2, Error = 3 } 15 | public NotifyIcon Tray { get { return icon; } } 16 | 17 | static Icon[] statusIcons = new Icon[] { 18 | resourceManager.GetObject("TrayStoppedIcon") as Icon, 19 | resourceManager.GetObject("TrayProcessingIcon") as Icon, 20 | resourceManager.GetObject("TrayOKIcon") as Icon, 21 | resourceManager.GetObject("TrayErrorIcon") as Icon 22 | }; 23 | 24 | public NotificationController(MainWindow window) { 25 | this.window = window; 26 | icon = new NotifyIcon(); 27 | icon.Visible = true; 28 | 29 | icon.DoubleClick += (sender, e) => { 30 | window.WindowState = System.Windows.WindowState.Normal; 31 | window.Activate(); 32 | }; 33 | 34 | icon.BalloonTipClicked += (sender, e) => { 35 | window.WindowState = System.Windows.WindowState.Normal; 36 | window.Activate(); 37 | }; 38 | 39 | var menu = new ContextMenu(); 40 | 41 | // Add Rules 42 | 43 | menu.MenuItems.Add(resources["AddRules"] as string, (sender, e) => { 44 | Rules.OpenEditor(false); 45 | }); 46 | 47 | // Proxy Type 48 | 49 | menu.MenuItems.Add(window.proxyTypeContextMenu); 50 | 51 | // Proxy Mode 52 | 53 | var proxyModeNormalItem = new MenuItem(resources["Normal"] as string); 54 | var proxyModeForwardAllItem=new MenuItem(resources["ForwardAll"] as string); 55 | 56 | var proxyModeCheckSwitcher = new Action(() => { 57 | proxyModeNormalItem.Checked = !settings.ForwardAll; 58 | proxyModeForwardAllItem.Checked = settings.ForwardAll; 59 | }); 60 | 61 | proxyModeCheckSwitcher(); 62 | 63 | settings.PropertyChanged += (sender, e) => { 64 | if (e.PropertyName == "ForwardAll") { 65 | proxyModeCheckSwitcher(); 66 | } 67 | }; 68 | 69 | proxyModeNormalItem.Click += (sender, e) => { 70 | if (settings.ForwardAll) { 71 | settings.ForwardAll = false; 72 | } 73 | }; 74 | 75 | proxyModeForwardAllItem.Click += (sender, e) => { 76 | if (!settings.ForwardAll) { 77 | settings.ForwardAll = true; 78 | } 79 | }; 80 | 81 | proxyModeNormalItem.RadioCheck = true; 82 | proxyModeForwardAllItem.RadioCheck = true; 83 | 84 | var proxyModeMenuItem = new MenuItem(resources["ProxyMode"] as string, new MenuItem[]{ proxyModeNormalItem, proxyModeForwardAllItem }); 85 | 86 | menu.MenuItems.Add(proxyModeMenuItem); 87 | 88 | // Profiles 89 | 90 | menu.MenuItems.Add(window.profileContextMenu); 91 | 92 | // Restart Application 93 | menu.MenuItems.Add(resources["Restart_Text"] as string, (sender, e) => 94 | { 95 | Process.Start(System.Windows.Forms.Application.ExecutablePath, "restart"); 96 | App.Current.Shutdown(); 97 | }); 98 | 99 | // Exit 100 | 101 | menu.MenuItems.Add(resources["Exit"] as string, (sender, e) => { 102 | System.Windows.Application.Current.Shutdown(); 103 | }); 104 | 105 | 106 | // End 107 | 108 | icon.ContextMenu = menu; 109 | 110 | SetStatus(settings.ProxyType, Status.Stopped, resources["NotConnected"] as string); 111 | System.Windows.Application.Current.Exit += (sender, e) => { 112 | icon.Dispose(); 113 | }; 114 | } 115 | 116 | public void SendMessage(string title, string details, ToolTipIcon tipIcon = ToolTipIcon.Info) { 117 | icon.ShowBalloonTip(0, title, details, tipIcon); 118 | } 119 | 120 | public void SetStatus(string type, Status status, string message = null, string tip = null, ToolTipIcon tipIcon = ToolTipIcon.Info) { 121 | try { 122 | if (message != null) { 123 | window.sshStatusTextBlock.Text = message; 124 | } 125 | 126 | if (type == settings.ProxyType) { 127 | icon.Icon = statusIcons[(int)status]; 128 | icon.Text = settings.ProxyType == "SSH" && message != null ? resources["XWall"] as string + " - " + message : resources["XWall"] as string; 129 | } 130 | 131 | if (tip != null) 132 | icon.ShowBalloonTip(0, message, tip, tipIcon); 133 | } 134 | catch { } 135 | } 136 | } 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/Classes/Plink.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Net; 7 | using System.Text; 8 | using System.Text.RegularExpressions; 9 | using System.Threading; 10 | using System.Windows; 11 | using XWall.Properties; 12 | 13 | namespace XWall { 14 | class Plink { 15 | static Settings settings = Settings.Default; 16 | static ResourceDictionary resources = App.Current.Resources; 17 | Process process; 18 | int reconnectPeriod; 19 | bool isLastSuccess; 20 | bool toReconnect; 21 | int portCloseCount; 22 | Timer processCheckTimer; 23 | public bool IsReconnecting = false; 24 | public bool IsConnecting = false; 25 | public bool IsConnected = false; 26 | public bool IsNormallyStopped = false; 27 | Action stopReconnect; 28 | 29 | public Plink() { 30 | Operation.KillProcess(settings.PlinkFileName); 31 | App.Current.Exit += (sender, e) => { 32 | Stop(); 33 | }; 34 | } 35 | 36 | void startProcess() { 37 | startProcess(false); 38 | } 39 | 40 | public static bool CheckSettings() { 41 | return 42 | settings.SshServer != "" && 43 | settings.SshPort > 0 && 44 | settings.SshUsername != "" && 45 | settings.SshPassword != "" && 46 | settings.SshSocksPort > 0; 47 | } 48 | 49 | void startProcess(bool isReconnect) { 50 | if (Environment.HasShutdownStarted) return; 51 | 52 | Thread.Sleep(10); 53 | 54 | isLastSuccess = false; 55 | toReconnect = true; 56 | IsConnecting = true; 57 | IsNormallyStopped = false; 58 | portCloseCount = 0; 59 | 60 | Started(); 61 | process = new Process(); 62 | 63 | var si = process.StartInfo; 64 | si.FileName = settings.SshUsePlonk ? settings.PlonkFileName : settings.PlinkFileName; 65 | if (settings.SshUsePrivateKeyLogin == true){ 66 | si.Arguments = String.Format( 67 | "-v -x -a -T -N{0}{1} -l {2} -i {3} -P {4} -D {5} {6}", 68 | settings.SshCompression ? " -C" : "", 69 | settings.SshUsePlonk ? " -z" + (settings.SshPlonkKeyword.Trim() != "" ? " -Z " + settings.SshPlonkKeyword : "") : "", 70 | settings.SshUsername, 71 | settings.SshPassword, 72 | settings.SshPort, 73 | "127.0.0.1:" + settings.SshSocksPort, 74 | settings.SshServer 75 | ); 76 | } 77 | else 78 | { 79 | si.Arguments = String.Format( 80 | "-v -x -a -T -N{0}{1} -l {2} -pw {3} -P {4} -D {5} {6}", 81 | settings.SshCompression ? " -C" : "", 82 | settings.SshUsePlonk ? " -z" + (settings.SshPlonkKeyword.Trim() != "" ? " -Z " + settings.SshPlonkKeyword : "") : "", 83 | settings.SshUsername, 84 | settings.SshPassword, 85 | settings.SshPort, 86 | "127.0.0.1:" + settings.SshSocksPort, 87 | settings.SshServer 88 | ); 89 | } 90 | 91 | 92 | si.RedirectStandardOutput = true; 93 | si.RedirectStandardInput = true; 94 | si.RedirectStandardError = true; 95 | si.CreateNoWindow = true; 96 | si.UseShellExecute = false; 97 | 98 | process.OutputDataReceived += onOutputDataReceived; 99 | process.ErrorDataReceived += onErrorDataReceived; 100 | 101 | Error = null; 102 | try { 103 | process.Start(); 104 | process.BeginOutputReadLine(); 105 | process.BeginErrorReadLine(); 106 | 107 | processCheckTimer = new Timer((o) => { 108 | if (process == null || process.HasExited) { 109 | IsConnected = false; 110 | IsConnecting = false; 111 | Disconnected(isLastSuccess, isReconnect); 112 | disposeProcessCheckTimer(); 113 | } 114 | }, null, 0, 1000); 115 | 116 | process.WaitForExit(settings.PlinkConnectTimeout * 1000); 117 | if (process != null && !process.HasExited) { 118 | if (IsConnected) { 119 | process.WaitForExit(); 120 | } 121 | else { 122 | try { 123 | process.Kill(); 124 | } 125 | catch { } 126 | } 127 | } 128 | } 129 | catch { } 130 | 131 | IsConnected = false; 132 | IsConnecting = false; 133 | Disconnected(isLastSuccess, isReconnect); 134 | processCheckTimer.Dispose(); 135 | 136 | if (toReconnect) { 137 | var stopReconnectingHandler = reconnect(); 138 | if (stopReconnectingHandler != null) { 139 | stopReconnect = stopReconnectingHandler; 140 | } 141 | } 142 | } 143 | 144 | void disposeProcessCheckTimer() { 145 | if (processCheckTimer != null) { 146 | processCheckTimer.Dispose(); 147 | } 148 | } 149 | 150 | public void Start() { 151 | reconnectPeriod = 1; 152 | Stop(); 153 | if (!CheckSettings()) return; 154 | new Action(() => { 155 | Thread.Sleep(100); 156 | startProcess(); 157 | }).BeginInvoke(null, null); 158 | } 159 | 160 | public void Stop(bool toReconnect = false) { 161 | IsNormallyStopped = true; 162 | this.toReconnect = toReconnect; 163 | 164 | if (IsReconnecting) { 165 | stopReconnect(); 166 | } 167 | 168 | try { 169 | process.Kill(); 170 | } 171 | catch { } 172 | } 173 | 174 | Action reconnect() { 175 | if (IsReconnecting) { 176 | //new Action(() => { 177 | // Thread.Sleep(1000); 178 | // reconnect(); 179 | //}).BeginInvoke(null, null); 180 | return null; 181 | } 182 | 183 | 184 | if (settings.SshAutoReconnect && (settings.SshReconnectAnyCondition || Error == null)) { 185 | var stopReconnect = false; 186 | IsReconnecting = true; 187 | //StopReconnect = false; 188 | 189 | new Action(() => { 190 | Thread.Sleep(500); 191 | 192 | if (stopReconnect) { 193 | return; 194 | } 195 | 196 | var time = reconnectPeriod; 197 | 198 | if (reconnectPeriod < settings.MaxReconnectPeriod) 199 | reconnectPeriod *= 2; 200 | 201 | while (time > 0) { 202 | ReconnectCountingDown(time--); 203 | Thread.Sleep(1000); 204 | if (stopReconnect) { 205 | return; 206 | } 207 | //if started by user or something elses while counting. 208 | if (process != null && !process.HasExited || !toReconnect) { 209 | IsReconnecting = false; 210 | return; 211 | } 212 | } 213 | 214 | IsReconnecting = false; 215 | 216 | if (!CheckSettings()) { 217 | Disconnected(false, true); 218 | return; 219 | } 220 | 221 | startProcess(true); 222 | }).BeginInvoke(null, null); 223 | 224 | return () => { 225 | stopReconnect = true; 226 | IsReconnecting = false; 227 | Disconnected(false, true); 228 | }; 229 | } 230 | else { 231 | return null; 232 | } 233 | } 234 | 235 | void onOutputDataReceived(object sender, DataReceivedEventArgs e) { 236 | //Console.WriteLine("D: " + e.Data); 237 | } 238 | 239 | DateTime lastPortCloseTime; 240 | 241 | void onErrorDataReceived(object sender, DataReceivedEventArgs e) { 242 | var line = e.Data; 243 | if (line == null) return; 244 | 245 | Console.WriteLine("E: " + line); 246 | 247 | if (new Regex(@"^Local port .+ SOCKS dynamic forwarding").IsMatch(line)) { 248 | reconnectPeriod = 1; 249 | isLastSuccess = true; 250 | IsConnected = true; 251 | IsConnecting = false; 252 | Connected(); 253 | } 254 | else if (line.StartsWith("Nothing left to send, closing channel")) { 255 | portCloseCount = Math.Min(1, portCloseCount + 1); 256 | } 257 | else if (line.StartsWith("Forwarded port closed")) { 258 | var now = DateTime.Now; 259 | 260 | if (lastPortCloseTime == null || now - lastPortCloseTime >= new TimeSpan(2000000)) { 261 | lastPortCloseTime = now; 262 | if (--portCloseCount < -settings.SshAbortionBeforeReconnect && settings.SshAutoReconnect) { 263 | Stop(true); 264 | } 265 | } 266 | } 267 | else if (line.StartsWith("The server's host key is not cached in the registry.")) { 268 | process.StandardInput.WriteLine("y"); 269 | } 270 | else if (line.StartsWith("Password authentication failed")) { 271 | Error = resources["PlinkAuthFailed"] as string; 272 | Stop(settings.SshReconnectAnyCondition); 273 | } 274 | else if (line.StartsWith("Server refused our key")) 275 | { 276 | Error = resources["SshPrivKeyRefused"] as string; 277 | Stop(settings.SshReconnectAnyCondition); 278 | 279 | } 280 | else { 281 | var match = new Regex(@"Failed to connect to (.+?): Network error: No route to host").Match(line); 282 | if (match.Success) { 283 | var ip = match.Groups[1].Value; 284 | var si = new ProcessStartInfo("arp", "-d " + ip); 285 | si.CreateNoWindow = true; 286 | si.UseShellExecute = false; 287 | Process.Start(si); 288 | } 289 | match = new Regex(@"Unable to use key file (.+?)").Match(line); 290 | if (match.Success) 291 | { 292 | Error = resources["SshPrivKeyFormatError"] as string; 293 | Stop(settings.SshReconnectAnyCondition); 294 | } 295 | } 296 | //else if (line.StartsWith("FATAL ERROR:")) { 297 | // Stop(settings.SshReconnectAnyCondition); 298 | //} 299 | } 300 | 301 | public string Error; 302 | 303 | public event Action Started = () => { }; 304 | public event Action Connected = () => { }; 305 | 306 | public delegate void DisconnectHandler(bool isLastSuccess, bool isReconnect); 307 | public event DisconnectHandler Disconnected = (isLastSuccess, isReconnect) => { }; 308 | 309 | public delegate void CountingDownHandler(int seconds); 310 | public event CountingDownHandler ReconnectCountingDown = (seconds) => { }; 311 | } 312 | } 313 | -------------------------------------------------------------------------------- /src/Classes/Privoxy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using System.Threading; 8 | using System.Windows; 9 | using XWall.Properties; 10 | 11 | namespace XWall { 12 | class Privoxy { 13 | static Settings settings = Settings.Default; 14 | static ResourceDictionary resources = App.Current.Resources; 15 | Process process; 16 | bool stop; 17 | bool lastStopWithError = false; 18 | 19 | public Privoxy() { 20 | Operation.KillProcess(settings.PrivoxyFileName); 21 | App.Current.Exit += (sender, e) => { 22 | Stop(); 23 | }; 24 | 25 | settings.PropertyChanged += (sender, e) => { 26 | switch (e.PropertyName) { 27 | case "ProxyPort": break; 28 | case "ListenToLocalOnly": break; 29 | case "UseIntranetProxy": break; 30 | case "IntranetProxyServer": break; 31 | case "IntranetProxyPort": break; 32 | default: return; 33 | } 34 | 35 | GenerateConfigFile(); 36 | }; 37 | 38 | //if (!File.Exists(settings.PrivoxyConfigFileName)) 39 | GenerateConfigFile(); 40 | } 41 | 42 | public static void GenerateConfigFile() { 43 | /* !DEBUG CODE 44 | return; 45 | //*/ 46 | //var defaultProxy = Operation.Proxies.DefaultProxy; 47 | var text = 48 | "listen-address " + (settings.ListenToLocalOnly ? "127.0.0.1:" : ":") + settings.ProxyPort + "\r\n" + 49 | "forwarded-connect-retries " + settings.ForwardConnectionRetries + "\r\n" + 50 | "forward / " + (settings.UseIntranetProxy ? (String.IsNullOrEmpty(settings.IntranetProxyServer) ? "127.0.0.1" : settings.IntranetProxyServer) + ":" + settings.IntranetProxyPort : ".") + "\r\n" + 51 | "keep-alive-timeout " + settings.PrivoxyKeepAliveTimeout + "\r\n" + 52 | "actionsfile " + App.AppDataDirectory + settings.ConfigsFolderName + settings.PrivoxyOnlineForwardActionFileName + "\r\n" + 53 | "actionsfile " + App.AppDataDirectory + settings.ConfigsFolderName + settings.PrivoxyOnlineDefaultActionFileName + "\r\n" + 54 | "actionsfile " + App.AppDataDirectory + settings.ConfigsFolderName + settings.PrivoxyCustomForwardActionFileName + "\r\n" + 55 | "actionsfile " + App.AppDataDirectory + settings.ConfigsFolderName + settings.PrivoxyCustomDefaultActionFileName + "\r\n" + 56 | "templdir " + App.AppDataDirectory + settings.ResourcesFolderName + settings.PrivoxyTemplatesFolderName + "\r\n"; 57 | File.WriteAllText(App.AppDataDirectory + settings.ConfigsFolderName + settings.PrivoxyConfigFileName, text); 58 | Operation.GrantAccessControl(App.AppDataDirectory + settings.ConfigsFolderName + settings.PrivoxyConfigFileName); 59 | } 60 | 61 | void startProcess() { 62 | if (Environment.HasShutdownStarted) return; 63 | 64 | stop = false; 65 | process = new Process(); 66 | 67 | var si = process.StartInfo; 68 | si.FileName = settings.PrivoxyFileName; 69 | si.Arguments = '"' + App.AppDataDirectory + settings.ConfigsFolderName + settings.PrivoxyConfigFileName + '"'; 70 | si.CreateNoWindow = true; 71 | si.UseShellExecute = false; 72 | process.Start(); 73 | process.WaitForExit(); 74 | 75 | var code = process.HasExited ? process.ExitCode : 0; 76 | if (code == 1) { 77 | if (!lastStopWithError) { 78 | lastStopWithError = true; 79 | new Action(() => { 80 | Thread.Sleep(1000); 81 | MessageBox.Show(resources["PrivoxyErrorExitMessage"] as string); 82 | }).BeginInvoke(null, null); 83 | } 84 | } 85 | else lastStopWithError = false; 86 | 87 | if (!stop) { 88 | new Action(() => { 89 | Thread.Sleep(2000); 90 | if (process == null || process.HasExited) 91 | startProcess(); 92 | }).BeginInvoke(null, null); 93 | } 94 | } 95 | 96 | public void Start() { 97 | Stop(); 98 | new Action(startProcess).BeginInvoke(null, null); 99 | } 100 | 101 | public void Stop() { 102 | stop = true; 103 | try { 104 | process.Kill(); 105 | } 106 | catch { } 107 | } 108 | 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/Classes/Profiles.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Linq; 5 | using System.Text; 6 | using XWall.Properties; 7 | 8 | namespace XWall { 9 | class Profile { 10 | static Settings settings = Settings.Default; 11 | 12 | public abstract class DefaultProfile { 13 | public string Name; 14 | public override string ToString() { 15 | return Name; 16 | } 17 | public abstract string ToSettingString(); 18 | } 19 | 20 | public class SshProfilesCollection { 21 | public BindingList Items; 22 | 23 | public SshProfilesCollection(string settingName) { 24 | Items = new BindingList(); 25 | 26 | var str = settings[settingName] as string; 27 | 28 | if (str != "") { 29 | var profileStrs = str.Split('\n'); 30 | for (int i = 0; i < profileStrs.Length; i++) { 31 | var profile = new SshProfile(profileStrs[i]); 32 | Items.Add(profile); 33 | } 34 | } 35 | 36 | Items.ListChanged += (sender, e) => { 37 | var profileStrs = new List(); 38 | for (int i = 0; i < Items.Count; i++) { 39 | profileStrs.Add(Items[i].ToSettingString()); 40 | } 41 | var newSetting = String.Join("\n", profileStrs.ToArray()); 42 | 43 | if (settings[settingName] as string != newSetting) { 44 | settings[settingName] = newSetting; 45 | } 46 | }; 47 | } 48 | } 49 | 50 | public class SshProfile : DefaultProfile { 51 | public string Server; 52 | public int Port; 53 | public string Username; 54 | public string Password; 55 | public SshProfile(string info = "") { 56 | if (String.IsNullOrEmpty(info)) { 57 | Name = ""; 58 | Server = ""; 59 | Port = 22; 60 | Username = ""; 61 | Password = ""; 62 | } 63 | else { 64 | var infos = info.Split('\t'); 65 | Name = infos[0]; 66 | Server = infos[1]; 67 | Port = int.Parse(infos[2]); 68 | Username = infos[3]; 69 | Password = infos[4]; 70 | } 71 | } 72 | public SshProfile(SshProfile profile) { 73 | Name = profile.Name; 74 | Server = profile.Server; 75 | Port = profile.Port; 76 | Username = profile.Username; 77 | Password = profile.Password; 78 | } 79 | public override string ToSettingString() { 80 | return String.Join("\t", new string[] { Name, Server, Port.ToString(), Username, Password }); 81 | } 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/Classes/Settings.cs: -------------------------------------------------------------------------------- 1 | using System.Configuration; 2 | using System.Diagnostics; 3 | using System.IO; 4 | using System.Text.RegularExpressions; 5 | using System.Windows; 6 | namespace XWall.Properties { 7 | 8 | 9 | // This class allows you to handle specific events on the settings class: 10 | // The SettingChanging event is raised before a setting's value is changed. 11 | // The PropertyChanged event is raised after a setting's value is changed. 12 | // The SettingsLoaded event is raised after the setting values are loaded. 13 | // The SettingsSaving event is raised before the setting values are saved. 14 | internal sealed partial class Settings { 15 | 16 | public bool AutoSave { get; set; } 17 | 18 | public Settings() { 19 | // // To add event handlers for saving and changing settings, uncomment the lines below: 20 | // 21 | // this.SettingChanging += this.SettingChangingEventHandler; 22 | // 23 | // this.SettingsSaving += this.SettingsSavingEventHandler; 24 | // 25 | 26 | AutoSave = true; 27 | 28 | this.PropertyChanged += (sender, e) => { 29 | if (AutoSave) { 30 | Settings.Default.Save(); 31 | } 32 | }; 33 | } 34 | 35 | public bool Export(string path) { 36 | try { 37 | File.Copy(GetDefaultExeConfigPath(ConfigurationUserLevel.PerUserRoamingAndLocal), path, true); 38 | return true; 39 | } 40 | catch { 41 | return false; 42 | } 43 | } 44 | 45 | public bool Import(string path) { 46 | AutoSave = false; 47 | try { 48 | File.Copy(path, GetDefaultExeConfigPath(ConfigurationUserLevel.PerUserRoamingAndLocal), true); 49 | return true; 50 | } 51 | catch { 52 | return false; 53 | } 54 | } 55 | 56 | public static string GetDefaultExeConfigPath(ConfigurationUserLevel userLevel) { 57 | try { 58 | var UserConfig = ConfigurationManager.OpenExeConfiguration(userLevel); 59 | return UserConfig.FilePath; 60 | } 61 | catch (ConfigurationException e) { 62 | return e.Filename; 63 | } 64 | } 65 | 66 | private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e) { 67 | // Add code to handle the SettingChangingEvent event here. 68 | } 69 | 70 | private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) { 71 | // Add code to handle the SettingsSaving event here. 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/CustomRulesEditor.xaml: -------------------------------------------------------------------------------- 1 |  12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |