├── .gitignore
├── Cartfile
├── CryptoSwift.framework
├── CryptoSwift
├── Headers
├── Modules
├── Resources
└── Versions
│ ├── A
│ ├── CryptoSwift
│ ├── Headers
│ │ └── CryptoSwift.h
│ ├── Modules
│ │ ├── CryptoSwift.swiftmodule
│ │ │ ├── x86_64.swiftdoc
│ │ │ └── x86_64.swiftmodule
│ │ └── module.modulemap
│ └── Resources
│ │ └── Info.plist
│ └── Current
├── LICENSE
├── LightSwordPlayground.playground
├── Contents.swift
├── contents.xcplayground
├── playground.xcworkspace
│ └── contents.xcworkspacedata
└── timeline.xctimeline
├── LightSwordX.xcodeproj
├── project.pbxproj
└── project.xcworkspace
│ └── contents.xcworkspacedata
├── LightSwordX
├── AppDelegate.swift
├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ ├── Contents.json
│ │ ├── happy_128.png
│ │ ├── happy_16.png
│ │ ├── happy_256.png
│ │ ├── happy_32.png
│ │ ├── happy_512.png
│ │ ├── icon_128x128@2x.png
│ │ ├── icon_16x16@2x.png
│ │ ├── icon_256x256@2x.png
│ │ ├── icon_32x32@2x.png
│ │ └── icon_512x512@2x.png
│ ├── Contents.json
│ ├── TrayIcon.imageset
│ │ ├── Contents.json
│ │ ├── icon_16x16@2x.png
│ │ └── sword_16.png
│ └── TrayIconHighlight.imageset
│ │ ├── Contents.json
│ │ ├── alter_sword_16.png
│ │ └── icon_16x16@2x.png
├── Base.lproj
│ ├── Localizable.strings
│ └── Main.storyboard
├── Common
│ └── AppKeys.swift
├── Info.plist
├── Lib
│ ├── Constants.swift
│ ├── Crypto.swift
│ ├── Json.swift
│ ├── Regex.swift
│ ├── SettingsHelper.swift
│ ├── StatisticsHelper.swift
│ └── String.swift
├── LightSwordX-Bridging-Header.h
├── LightSwordX.entitlements
├── Models
│ └── UserServer.swift
├── Socket
│ ├── ysocket.swift
│ ├── ytcpsocket.c
│ ├── ytcpsocket.swift
│ ├── yudpsocket.c
│ └── yudpsocket.swift
├── Socket6
│ ├── Socket.swift
│ └── TCPSocket.c
├── Socks5
│ ├── Socks5Constants.swift
│ ├── Socks5Helper.swift
│ └── Socks5Server.swift
├── TCPSocket.swift
├── ViewController.Servers.swift
├── ViewController.Settings.swift
├── ViewController.Websites.swift
├── ViewController.swift
├── black.txt
├── white.txt
└── zh-Hans.lproj
│ ├── Localizable.strings
│ └── Main.strings
├── LightSwordXHelper
├── AppDelegate.swift
├── Assets.xcassets
│ └── AppIcon.appiconset
│ │ ├── 1451660318_game-fighting-sword-shooter.png
│ │ ├── 1451660323_game-fighting-sword-shooter.png
│ │ ├── 1451660327_game-fighting-sword-shooter.png
│ │ ├── 1451660336_game-fighting-sword-shooter.png
│ │ ├── Contents.json
│ │ ├── icon_128x128@2x.png
│ │ ├── icon_16x16@2x.png
│ │ ├── icon_256x256@2x.png
│ │ ├── icon_32x32@2x.png
│ │ ├── icon_512x512@2x.png
│ │ └── sword_16.png
├── Base.lproj
│ └── Main.storyboard
├── Info.plist
├── LightSwordXHelper.entitlements
└── zh-Hans.lproj
│ └── Main.strings
├── LightSwordXTests
├── Info.plist
└── LightSwordXTests.swift
├── README.md
├── README_zh.md
└── SINQ.framework
├── Headers
├── Modules
├── Resources
├── SINQ
└── Versions
├── A
├── Headers
│ ├── SINQ-Swift.h
│ └── SINQ.h
├── Modules
│ ├── SINQ.swiftmodule
│ │ ├── x86_64.swiftdoc
│ │ └── x86_64.swiftmodule
│ └── module.modulemap
├── Resources
│ └── Info.plist
└── SINQ
└── Current
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | xcuserdata/
3 | Cartfile.resolved
4 |
5 | # Xcode
6 | #
7 | build/
8 | *.pbxuser
9 | !default.pbxuser
10 | *.mode1v3
11 | !default.mode1v3
12 | *.mode2v3
13 | !default.mode2v3
14 | *.perspectivev3
15 | !default.perspectivev3
16 | xcuserdata
17 | *.xccheckout
18 | *.moved-aside
19 | DerivedData
20 | *.hmap
21 | *.ipa
22 | *.xcuserstate
23 |
24 | # CocoaPods
25 | #
26 | # We recommend against adding the Pods directory to your .gitignore. However
27 | # you should judge for yourself, the pros and cons are mentioned at:
28 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
29 | #
30 | # Pods/
31 |
32 | # Carthage
33 | #
34 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
35 | Carthage/Checkouts
36 |
37 | Carthage/Build
38 |
--------------------------------------------------------------------------------
/Cartfile:
--------------------------------------------------------------------------------
1 | github "slazyk/SINQ"
2 | github "krzyzanowskim/CryptoSwift"
3 |
--------------------------------------------------------------------------------
/CryptoSwift.framework/CryptoSwift:
--------------------------------------------------------------------------------
1 | Versions/Current/CryptoSwift
--------------------------------------------------------------------------------
/CryptoSwift.framework/Headers:
--------------------------------------------------------------------------------
1 | Versions/Current/Headers
--------------------------------------------------------------------------------
/CryptoSwift.framework/Modules:
--------------------------------------------------------------------------------
1 | Versions/Current/Modules
--------------------------------------------------------------------------------
/CryptoSwift.framework/Resources:
--------------------------------------------------------------------------------
1 | Versions/Current/Resources
--------------------------------------------------------------------------------
/CryptoSwift.framework/Versions/A/CryptoSwift:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UnsignedInt8/LightSwordX/98eea71721ae22a65446b9d56f45aa2a689f5266/CryptoSwift.framework/Versions/A/CryptoSwift
--------------------------------------------------------------------------------
/CryptoSwift.framework/Versions/A/Headers/CryptoSwift.h:
--------------------------------------------------------------------------------
1 | //
2 | // CryptoSwift.h
3 | // CryptoSwift
4 | //
5 | // Created by Sam Soffes on 11/29/15.
6 | // Copyright © 2015 Marcin Krzyzanowski. All rights reserved.
7 | //
8 |
9 | @import Foundation;
10 |
11 | //! Project version number for CryptoSwift.
12 | FOUNDATION_EXPORT double CryptoSwiftVersionNumber;
13 |
14 | //! Project version string for CryptoSwift.
15 | FOUNDATION_EXPORT const unsigned char CryptoSwiftVersionString[];
16 |
--------------------------------------------------------------------------------
/CryptoSwift.framework/Versions/A/Modules/CryptoSwift.swiftmodule/x86_64.swiftdoc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UnsignedInt8/LightSwordX/98eea71721ae22a65446b9d56f45aa2a689f5266/CryptoSwift.framework/Versions/A/Modules/CryptoSwift.swiftmodule/x86_64.swiftdoc
--------------------------------------------------------------------------------
/CryptoSwift.framework/Versions/A/Modules/CryptoSwift.swiftmodule/x86_64.swiftmodule:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UnsignedInt8/LightSwordX/98eea71721ae22a65446b9d56f45aa2a689f5266/CryptoSwift.framework/Versions/A/Modules/CryptoSwift.swiftmodule/x86_64.swiftmodule
--------------------------------------------------------------------------------
/CryptoSwift.framework/Versions/A/Modules/module.modulemap:
--------------------------------------------------------------------------------
1 | framework module CryptoSwift {
2 | umbrella header "CryptoSwift.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/CryptoSwift.framework/Versions/A/Resources/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | BuildMachineOSBuild
6 | 15D21
7 | CFBundleDevelopmentRegion
8 | en
9 | CFBundleExecutable
10 | CryptoSwift
11 | CFBundleIdentifier
12 | com.hakore.CryptoSwift
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | CryptoSwift
17 | CFBundlePackageType
18 | FMWK
19 | CFBundleShortVersionString
20 | 0.2.3
21 | CFBundleSignature
22 | ????
23 | CFBundleSupportedPlatforms
24 |
25 | MacOSX
26 |
27 | CFBundleVersion
28 | 1
29 | DTCompiler
30 | com.apple.compilers.llvm.clang.1_0
31 | DTPlatformBuild
32 | 7C1002
33 | DTPlatformVersion
34 | GM
35 | DTSDKBuild
36 | 15C43
37 | DTSDKName
38 | macosx10.11
39 | DTXcode
40 | 0721
41 | DTXcodeBuild
42 | 7C1002
43 | UIDeviceFamily
44 |
45 | 1
46 | 2
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/CryptoSwift.framework/Versions/Current:
--------------------------------------------------------------------------------
1 | A
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Lesser General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 | {description}
294 | Copyright (C) {year} {fullname}
295 |
296 | This program is free software; you can redistribute it and/or modify
297 | it under the terms of the GNU General Public License as published by
298 | the Free Software Foundation; either version 2 of the License, or
299 | (at your option) any later version.
300 |
301 | This program is distributed in the hope that it will be useful,
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 | GNU General Public License for more details.
305 |
306 | You should have received a copy of the GNU General Public License along
307 | with this program; if not, write to the Free Software Foundation, Inc.,
308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309 |
310 | Also add information on how to contact you by electronic and paper mail.
311 |
312 | If the program is interactive, make it output a short notice like this
313 | when it starts in an interactive mode:
314 |
315 | Gnomovision version 69, Copyright (C) year name of author
316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 | This is free software, and you are welcome to redistribute it
318 | under certain conditions; type `show c' for details.
319 |
320 | The hypothetical commands `show w' and `show c' should show the appropriate
321 | parts of the General Public License. Of course, the commands you use may
322 | be called something other than `show w' and `show c'; they could even be
323 | mouse-clicks or menu items--whatever suits your program.
324 |
325 | You should also get your employer (if you work as a programmer) or your
326 | school, if any, to sign a "copyright disclaimer" for the program, if
327 | necessary. Here is a sample; alter the names:
328 |
329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
331 |
332 | {signature of Ty Coon}, 1 April 1989
333 | Ty Coon, President of Vice
334 |
335 | This General Public License does not permit incorporating your program into
336 | proprietary programs. If your program is a subroutine library, you may
337 | consider it more useful to permit linking proprietary applications with the
338 | library. If this is what you want to do, use the GNU Lesser General
339 | Public License instead of this License.
340 |
341 |
--------------------------------------------------------------------------------
/LightSwordPlayground.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Cocoa
4 |
5 | var status: Int32 = 0
6 |
7 | // Protocol configuration
8 |
9 | var hints = addrinfo(
10 | ai_flags: AI_PASSIVE, // Assign the address of my local host to the socket structures
11 | ai_family: AF_UNSPEC, // Either IPv4 or IPv6
12 | ai_socktype: SOCK_STREAM, // TCP
13 | ai_protocol: 0,
14 | ai_addrlen: 0,
15 | ai_canonname: nil,
16 | ai_addr: nil,
17 | ai_next: nil)
18 |
19 |
20 | // For the result from the getaddrinfo
21 |
22 | var servinfo = UnsafeMutablePointer.init()
23 |
24 |
25 | // Get the info we need to create our socket descriptor
26 |
27 | status = getaddrinfo("ip.cn", "", &hints, &servinfo)
28 |
29 | print(status)
30 |
31 | print(servinfo.memory.ai_addr)
--------------------------------------------------------------------------------
/LightSwordPlayground.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/LightSwordPlayground.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/LightSwordPlayground.playground/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/LightSwordX.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/LightSwordX/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // LightSwordX
4 | //
5 | // Created by Neko on 12/17/15.
6 | // Copyright © 2015 Neko. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 |
11 | @NSApplicationMain
12 | class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDelegate {
13 |
14 | func applicationDidFinishLaunching(aNotification: NSNotification) {
15 |
16 | if SettingsHelper.loadValue(defaultValue: "", forKey: "Servers").length > 0 {
17 | NSApplication.sharedApplication().windows.last!.close()
18 | }
19 |
20 | if let button = statusItem.button {
21 | button.image = NSImage(named: "TrayIcon")
22 | button.image?.template = true
23 | button.alternateImage = NSImage(named: "TrayIconHighlight")
24 | }
25 |
26 | let menu = NSMenu()
27 | menu.addItem(NSMenuItem(title: NSLocalizedString("Preferences", comment: ""), action: Selector("openPreferences:"), keyEquivalent: ""))
28 | menu.addItem(NSMenuItem(title: NSLocalizedString("Quit", comment: ""), action: Selector("quit:"), keyEquivalent: ""))
29 |
30 | statusItem.menu = menu
31 |
32 | NSUserNotificationCenter.defaultUserNotificationCenter().delegate = self
33 | }
34 |
35 | func userNotificationCenter(center: NSUserNotificationCenter, shouldPresentNotification notification: NSUserNotification) -> Bool {
36 | return true
37 | }
38 |
39 | func applicationWillTerminate(aNotification: NSNotification) {
40 | // Insert code here to tear down your application
41 | }
42 |
43 | let statusItem = NSStatusBar.systemStatusBar().statusItemWithLength(NSSquareStatusItemLength)
44 |
45 | func openPreferences(sender: NSMenuItem) {
46 | NSApplication.sharedApplication().windows.last!.makeKeyAndOrderFront(nil)
47 | NSApplication.sharedApplication().activateIgnoringOtherApps(true)
48 | }
49 |
50 | func quit(sender: NSMenuItem) {
51 | NSApplication.sharedApplication().terminate(self)
52 | }
53 | }
54 |
55 |
--------------------------------------------------------------------------------
/LightSwordX/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "16x16",
5 | "idiom" : "mac",
6 | "filename" : "happy_16.png",
7 | "scale" : "1x"
8 | },
9 | {
10 | "size" : "16x16",
11 | "idiom" : "mac",
12 | "filename" : "icon_16x16@2x.png",
13 | "scale" : "2x"
14 | },
15 | {
16 | "size" : "32x32",
17 | "idiom" : "mac",
18 | "filename" : "happy_32.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "32x32",
23 | "idiom" : "mac",
24 | "filename" : "icon_32x32@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "128x128",
29 | "idiom" : "mac",
30 | "filename" : "happy_128.png",
31 | "scale" : "1x"
32 | },
33 | {
34 | "size" : "128x128",
35 | "idiom" : "mac",
36 | "filename" : "icon_128x128@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "256x256",
41 | "idiom" : "mac",
42 | "filename" : "happy_256.png",
43 | "scale" : "1x"
44 | },
45 | {
46 | "size" : "256x256",
47 | "idiom" : "mac",
48 | "filename" : "icon_256x256@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "512x512",
53 | "idiom" : "mac",
54 | "filename" : "happy_512.png",
55 | "scale" : "1x"
56 | },
57 | {
58 | "size" : "512x512",
59 | "idiom" : "mac",
60 | "filename" : "icon_512x512@2x.png",
61 | "scale" : "2x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
--------------------------------------------------------------------------------
/LightSwordX/Assets.xcassets/AppIcon.appiconset/happy_128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UnsignedInt8/LightSwordX/98eea71721ae22a65446b9d56f45aa2a689f5266/LightSwordX/Assets.xcassets/AppIcon.appiconset/happy_128.png
--------------------------------------------------------------------------------
/LightSwordX/Assets.xcassets/AppIcon.appiconset/happy_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UnsignedInt8/LightSwordX/98eea71721ae22a65446b9d56f45aa2a689f5266/LightSwordX/Assets.xcassets/AppIcon.appiconset/happy_16.png
--------------------------------------------------------------------------------
/LightSwordX/Assets.xcassets/AppIcon.appiconset/happy_256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UnsignedInt8/LightSwordX/98eea71721ae22a65446b9d56f45aa2a689f5266/LightSwordX/Assets.xcassets/AppIcon.appiconset/happy_256.png
--------------------------------------------------------------------------------
/LightSwordX/Assets.xcassets/AppIcon.appiconset/happy_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UnsignedInt8/LightSwordX/98eea71721ae22a65446b9d56f45aa2a689f5266/LightSwordX/Assets.xcassets/AppIcon.appiconset/happy_32.png
--------------------------------------------------------------------------------
/LightSwordX/Assets.xcassets/AppIcon.appiconset/happy_512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UnsignedInt8/LightSwordX/98eea71721ae22a65446b9d56f45aa2a689f5266/LightSwordX/Assets.xcassets/AppIcon.appiconset/happy_512.png
--------------------------------------------------------------------------------
/LightSwordX/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UnsignedInt8/LightSwordX/98eea71721ae22a65446b9d56f45aa2a689f5266/LightSwordX/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png
--------------------------------------------------------------------------------
/LightSwordX/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UnsignedInt8/LightSwordX/98eea71721ae22a65446b9d56f45aa2a689f5266/LightSwordX/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png
--------------------------------------------------------------------------------
/LightSwordX/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UnsignedInt8/LightSwordX/98eea71721ae22a65446b9d56f45aa2a689f5266/LightSwordX/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png
--------------------------------------------------------------------------------
/LightSwordX/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UnsignedInt8/LightSwordX/98eea71721ae22a65446b9d56f45aa2a689f5266/LightSwordX/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png
--------------------------------------------------------------------------------
/LightSwordX/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UnsignedInt8/LightSwordX/98eea71721ae22a65446b9d56f45aa2a689f5266/LightSwordX/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png
--------------------------------------------------------------------------------
/LightSwordX/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/LightSwordX/Assets.xcassets/TrayIcon.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "filename" : "sword_16.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "filename" : "icon_16x16@2x.png",
11 | "scale" : "2x"
12 | }
13 | ],
14 | "info" : {
15 | "version" : 1,
16 | "author" : "xcode"
17 | }
18 | }
--------------------------------------------------------------------------------
/LightSwordX/Assets.xcassets/TrayIcon.imageset/icon_16x16@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UnsignedInt8/LightSwordX/98eea71721ae22a65446b9d56f45aa2a689f5266/LightSwordX/Assets.xcassets/TrayIcon.imageset/icon_16x16@2x.png
--------------------------------------------------------------------------------
/LightSwordX/Assets.xcassets/TrayIcon.imageset/sword_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UnsignedInt8/LightSwordX/98eea71721ae22a65446b9d56f45aa2a689f5266/LightSwordX/Assets.xcassets/TrayIcon.imageset/sword_16.png
--------------------------------------------------------------------------------
/LightSwordX/Assets.xcassets/TrayIconHighlight.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "filename" : "alter_sword_16.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "mac",
10 | "filename" : "icon_16x16@2x.png",
11 | "scale" : "2x"
12 | }
13 | ],
14 | "info" : {
15 | "version" : 1,
16 | "author" : "xcode"
17 | }
18 | }
--------------------------------------------------------------------------------
/LightSwordX/Assets.xcassets/TrayIconHighlight.imageset/alter_sword_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UnsignedInt8/LightSwordX/98eea71721ae22a65446b9d56f45aa2a689f5266/LightSwordX/Assets.xcassets/TrayIconHighlight.imageset/alter_sword_16.png
--------------------------------------------------------------------------------
/LightSwordX/Assets.xcassets/TrayIconHighlight.imageset/icon_16x16@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UnsignedInt8/LightSwordX/98eea71721ae22a65446b9d56f45aa2a689f5266/LightSwordX/Assets.xcassets/TrayIconHighlight.imageset/icon_16x16@2x.png
--------------------------------------------------------------------------------
/LightSwordX/Base.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | // Connection Test
2 |
3 | "Test Connection Speed" = "Test Connection Speed";
4 | "Elapsed Time" = "Elapsed Time";
5 | "Connection Timeout" = "Connection Timeout";
6 |
7 | // Menu Bar
8 |
9 | "Preferences" = "Preferences";
10 | "Quit" = "Quit";
11 |
12 | // Status
13 |
14 | "Stopped" = "Stopped";
15 | "Running" = "Running";
16 |
17 | // Local Server
18 |
19 | "Start Failed" = "Start Failed";
20 | "Port is used" = "Port number: %d is used by other process or access denied";
--------------------------------------------------------------------------------
/LightSwordX/Common/AppKeys.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppKeys.swift
3 | // LightSwordX
4 | //
5 | // Created by Neko on 12/29/15.
6 | // Copyright © 2015 Neko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | class AppKeys {
12 | static let Servers = "Servers"
13 | static let WhiteList = "WhiteList"
14 | static let BlackList = "BlackList"
15 | static let LoginItem = "LoginItem"
16 | }
--------------------------------------------------------------------------------
/LightSwordX/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 3
25 | LSApplicationCategoryType
26 | public.app-category.utilities
27 | LSMinimumSystemVersion
28 | $(MACOSX_DEPLOYMENT_TARGET)
29 | LSUIElement
30 |
31 | NSHumanReadableCopyright
32 | Copyright © 2015 Project LightSword. All rights reserved.
33 | NSMainStoryboardFile
34 | Main
35 | NSPrincipalClass
36 | NSApplication
37 |
38 |
39 |
--------------------------------------------------------------------------------
/LightSwordX/Lib/Constants.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Constants.swift
3 | // LightSwordX
4 | //
5 | // Created by Neko on 12/20/15.
6 | // Copyright © 2015 Neko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | enum VPN_TYPE: UInt8 {
12 | case OSXCL5 = 0xa5
13 | }
--------------------------------------------------------------------------------
/LightSwordX/Lib/Crypto.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Crypto.swift
3 | // LightSwordX
4 | //
5 | // Created by Neko on 12/19/15.
6 | // Copyright © 2015 Neko. All rights reserved.
7 | //
8 |
9 | import SINQ
10 | import Foundation
11 | import CryptoSwift
12 |
13 | class Crypto {
14 |
15 | static let SupportedCiphers = [
16 | "aes-256-cfb": (info: [32, 16], blockMode: CipherBlockMode.CFB),
17 | "aes-192-cfb": (info: [24, 16], blockMode: CipherBlockMode.CFB),
18 | "aes-128-cfb": (info: [16, 16], blockMode: CipherBlockMode.CFB)
19 | ]
20 |
21 | static func createCipher(algorithm: String, password: String, iv: [UInt8]? = nil) -> (cipher: AES, iv: [UInt8]) {
22 | var tuple: (info: [Int], blockMode: CipherBlockMode)! = SupportedCiphers[algorithm.lowercaseString]
23 | if tuple == nil {
24 | tuple = (info: [32, 16], blockMode: CipherBlockMode.CFB)
25 | }
26 |
27 | var key = [UInt8](password.utf8)
28 | if key.count > tuple.info[0] {
29 | key = sinq(key).take(tuple.info[0]).toArray()
30 | } else {
31 | let longPw = String(count: (tuple.info[0] / password.length) + 1, byRepeatingString: password)!
32 | key = [UInt8](longPw.utf8)
33 | key = sinq(key).take(tuple.info[0]).toArray()
34 | }
35 |
36 | var civ: [UInt8]! = iv
37 | if civ == nil {
38 | civ = AES.randomIV(tuple.info[1])
39 | }
40 |
41 | let cipher = try! AES(key: key, iv: civ, blockMode: tuple.blockMode)
42 | return (cipher: cipher, iv: civ)
43 | }
44 | }
45 |
46 |
--------------------------------------------------------------------------------
/LightSwordX/Lib/Json.swift:
--------------------------------------------------------------------------------
1 | //
2 | // json.swift
3 | // json
4 | //
5 | // Created by Dan Kogai on 7/15/14.
6 | // Copyright (c) 2014 Dan Kogai. All rights reserved.
7 | //
8 | import Foundation
9 | /// init
10 | public class JSON {
11 | private let _value:AnyObject
12 | /// unwraps the JSON object
13 | public class func unwrap(obj:AnyObject) -> AnyObject {
14 | switch obj {
15 | case let json as JSON:
16 | return json._value
17 | case let ary as NSArray:
18 | var ret = [AnyObject]()
19 | for v in ary {
20 | ret.append(unwrap(v))
21 | }
22 | return ret
23 | case let dict as NSDictionary:
24 | var ret = [String:AnyObject]()
25 | for (ko, v) in dict {
26 | if let k = ko as? String {
27 | ret[k] = unwrap(v)
28 | }
29 | }
30 | return ret
31 | default:
32 | return obj
33 | }
34 | }
35 | /// pass the object that was returned from
36 | /// NSJSONSerialization
37 | public init(_ obj:AnyObject) { self._value = JSON.unwrap(obj) }
38 | /// pass the JSON object for another instance
39 | public init(_ json:JSON){ self._value = json._value }
40 | }
41 | /// class properties
42 | extension JSON {
43 | public typealias NSNull = Foundation.NSNull
44 | public typealias NSError = Foundation.NSError
45 | public class var null:NSNull { return NSNull() }
46 | /// constructs JSON object from data
47 | public convenience init(data:NSData) {
48 | var err:NSError?
49 | var obj:AnyObject?
50 | do {
51 | obj = try NSJSONSerialization.JSONObjectWithData(
52 | data, options:[])
53 | } catch let error as NSError {
54 | err = error
55 | obj = nil
56 | }
57 | self.init(err != nil ? err! : obj!)
58 | }
59 | /// constructs JSON object from string
60 | public convenience init(string:String) {
61 | let enc:NSStringEncoding = NSUTF8StringEncoding
62 | self.init(data: string.dataUsingEncoding(enc)!)
63 | }
64 | /// parses string to the JSON object
65 | /// same as JSON(string:String)
66 | public class func parse(string:String)->JSON {
67 | return JSON(string:string)
68 | }
69 | /// constructs JSON object from the content of NSURL
70 | public convenience init(nsurl:NSURL) {
71 | var enc:NSStringEncoding = NSUTF8StringEncoding
72 | do {
73 | let str = try NSString(contentsOfURL:nsurl, usedEncoding:&enc)
74 | self.init(string:str as String)
75 | } catch let err as NSError {
76 | self.init(err)
77 | }
78 | }
79 | /// fetch the JSON string from NSURL and parse it
80 | /// same as JSON(nsurl:NSURL)
81 | public class func fromNSURL(nsurl:NSURL) -> JSON {
82 | return JSON(nsurl:nsurl)
83 | }
84 | /// constructs JSON object from the content of URL
85 | public convenience init(url:String) {
86 | if let nsurl = NSURL(string:url) as NSURL? {
87 | self.init(nsurl:nsurl)
88 | } else {
89 | self.init(NSError(
90 | domain:"JSONErrorDomain",
91 | code:400,
92 | userInfo:[NSLocalizedDescriptionKey: "malformed URL"]
93 | )
94 | )
95 | }
96 | }
97 | /// fetch the JSON string from URL in the string
98 | public class func fromURL(url:String) -> JSON {
99 | return JSON(url:url)
100 | }
101 | /// does what JSON.stringify in ES5 does.
102 | /// when the 2nd argument is set to true it pretty prints
103 | public class func stringify(obj:AnyObject, pretty:Bool=false) -> String! {
104 | if !NSJSONSerialization.isValidJSONObject(obj) {
105 | let error = JSON(NSError(
106 | domain:"JSONErrorDomain",
107 | code:422,
108 | userInfo:[NSLocalizedDescriptionKey: "not an JSON object"]
109 | ))
110 | return JSON(error).toString(pretty)
111 | }
112 | return JSON(obj).toString(pretty)
113 | }
114 | }
115 | /// instance properties
116 | extension JSON {
117 | /// access the element like array
118 | public subscript(idx:Int) -> JSON {
119 | switch _value {
120 | case _ as NSError:
121 | return self
122 | case let ary as NSArray:
123 | if 0 <= idx && idx < ary.count {
124 | return JSON(ary[idx])
125 | }
126 | return JSON(NSError(
127 | domain:"JSONErrorDomain", code:404, userInfo:[
128 | NSLocalizedDescriptionKey:
129 | "[\(idx)] is out of range"
130 | ]))
131 | default:
132 | return JSON(NSError(
133 | domain:"JSONErrorDomain", code:500, userInfo:[
134 | NSLocalizedDescriptionKey: "not an array"
135 | ]))
136 | }
137 | }
138 | /// access the element like dictionary
139 | public subscript(key:String)->JSON {
140 | switch _value {
141 | case _ as NSError:
142 | return self
143 | case let dic as NSDictionary:
144 | if let val:AnyObject = dic[key] { return JSON(val) }
145 | return JSON(NSError(
146 | domain:"JSONErrorDomain", code:404, userInfo:[
147 | NSLocalizedDescriptionKey:
148 | "[\"\(key)\"] not found"
149 | ]))
150 | default:
151 | return JSON(NSError(
152 | domain:"JSONErrorDomain", code:500, userInfo:[
153 | NSLocalizedDescriptionKey: "not an object"
154 | ]))
155 | }
156 | }
157 | /// access json data object
158 | public var data:AnyObject? {
159 | return self.isError ? nil : self._value
160 | }
161 | /// Gives the type name as string.
162 | /// e.g. if it returns "Double"
163 | /// .asDouble returns Double
164 | public var type:String {
165 | switch _value {
166 | case is NSError: return "NSError"
167 | case is NSNull: return "NSNull"
168 | case let o as NSNumber:
169 | switch String.fromCString(o.objCType)! {
170 | case "c", "C": return "Bool"
171 | case "q", "l", "i", "s": return "Int"
172 | case "Q", "L", "I", "S": return "UInt"
173 | default: return "Double"
174 | }
175 | case is NSString: return "String"
176 | case is NSArray: return "Array"
177 | case is NSDictionary: return "Dictionary"
178 | default: return "NSError"
179 | }
180 | }
181 | /// check if self is NSError
182 | public var isError: Bool { return _value is NSError }
183 | /// check if self is NSNull
184 | public var isNull: Bool { return _value is NSNull }
185 | /// check if self is Bool
186 | public var isBool: Bool { return type == "Bool" }
187 | /// check if self is Int
188 | public var isInt: Bool { return type == "Int" }
189 | /// check if self is UInt
190 | public var isUInt: Bool { return type == "UInt" }
191 | /// check if self is Double
192 | public var isDouble: Bool { return type == "Double" }
193 | /// check if self is any type of number
194 | public var isNumber: Bool {
195 | if let o = _value as? NSNumber {
196 | let t = String.fromCString(o.objCType)!
197 | return t != "c" && t != "C"
198 | }
199 | return false
200 | }
201 | /// check if self is String
202 | public var isString: Bool { return _value is NSString }
203 | /// check if self is Array
204 | public var isArray: Bool { return _value is NSArray }
205 | /// check if self is Dictionary
206 | public var isDictionary: Bool { return _value is NSDictionary }
207 | /// check if self is a valid leaf node.
208 | public var isLeaf: Bool {
209 | return !(isArray || isDictionary || isError)
210 | }
211 | /// gives NSError if it holds the error. nil otherwise
212 | public var asError:NSError? {
213 | return _value as? NSError
214 | }
215 | /// gives NSNull if self holds it. nil otherwise
216 | public var asNull:NSNull? {
217 | return _value is NSNull ? JSON.null : nil
218 | }
219 | /// gives Bool if self holds it. nil otherwise
220 | public var asBool:Bool? {
221 | switch _value {
222 | case let o as NSNumber:
223 | switch String.fromCString(o.objCType)! {
224 | case "c", "C": return Bool(o.boolValue)
225 | default:
226 | return nil
227 | }
228 | default: return nil
229 | }
230 | }
231 | /// gives Int if self holds it. nil otherwise
232 | public var asInt:Int? {
233 | switch _value {
234 | case let o as NSNumber:
235 | switch String.fromCString(o.objCType)! {
236 | case "c", "C":
237 | return nil
238 | default:
239 | return Int(o.longLongValue)
240 | }
241 | default: return nil
242 | }
243 | }
244 | /// gives Int32 if self holds it. nil otherwise
245 | public var asInt32:Int32? {
246 | switch _value {
247 | case let o as NSNumber:
248 | switch String.fromCString(o.objCType)! {
249 | case "c", "C":
250 | return nil
251 | default:
252 | return Int32(o.longLongValue)
253 | }
254 | default: return nil
255 | }
256 | }
257 | /// gives Int64 if self holds it. nil otherwise
258 | public var asInt64:Int64? {
259 | switch _value {
260 | case let o as NSNumber:
261 | switch String.fromCString(o.objCType)! {
262 | case "c", "C":
263 | return nil
264 | default:
265 | return Int64(o.longLongValue)
266 | }
267 | default: return nil
268 | }
269 | }
270 | /// gives Float if self holds it. nil otherwise
271 | public var asFloat:Float? {
272 | switch _value {
273 | case let o as NSNumber:
274 | switch String.fromCString(o.objCType)! {
275 | case "c", "C":
276 | return nil
277 | default:
278 | return Float(o.floatValue)
279 | }
280 | default: return nil
281 | }
282 | }
283 | /// gives Double if self holds it. nil otherwise
284 | public var asDouble:Double? {
285 | switch _value {
286 | case let o as NSNumber:
287 | switch String.fromCString(o.objCType)! {
288 | case "c", "C":
289 | return nil
290 | default:
291 | return Double(o.doubleValue)
292 | }
293 | default: return nil
294 | }
295 | }
296 | // an alias to asDouble
297 | public var asNumber:Double? { return asDouble }
298 | /// gives String if self holds it. nil otherwise
299 | public var asString:String? {
300 | switch _value {
301 | case let o as NSString:
302 | return o as String
303 | default: return nil
304 | }
305 | }
306 | /// if self holds NSArray, gives a [JSON]
307 | /// with elements therein. nil otherwise
308 | public var asArray:[JSON]? {
309 | switch _value {
310 | case let o as NSArray:
311 | var result = [JSON]()
312 | for v:AnyObject in o { result.append(JSON(v)) }
313 | return result
314 | default:
315 | return nil
316 | }
317 | }
318 | /// if self holds NSDictionary, gives a [String:JSON]
319 | /// with elements therein. nil otherwise
320 | public var asDictionary:[String:JSON]? {
321 | switch _value {
322 | case let o as NSDictionary:
323 | var result = [String:JSON]()
324 | for (ko, v): (AnyObject, AnyObject) in o {
325 | if let k = ko as? String {
326 | result[k] = JSON(v)
327 | }
328 | }
329 | return result
330 | default: return nil
331 | }
332 | }
333 | /// Yields date from string
334 | public var asDate:NSDate? {
335 | if let dateString = _value as? String {
336 | let dateFormatter = NSDateFormatter()
337 | dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZ"
338 | return dateFormatter.dateFromString(dateString)
339 | }
340 | return nil
341 | }
342 | /// gives the number of elements if an array or a dictionary.
343 | /// you can use this to check if you can iterate.
344 | public var length:Int {
345 | switch _value {
346 | case let o as NSArray: return o.count
347 | case let o as NSDictionary: return o.count
348 | default: return 0
349 | }
350 | }
351 | // gives all values content in JSON object.
352 | public var allValues:JSON{
353 | if(self._value.allValues == nil) {
354 | return JSON([])
355 | }
356 | return JSON(self._value.allValues)
357 | }
358 | // gives all keys content in JSON object.
359 | public var allKeys:JSON{
360 | if(self._value.allObjects == nil) {
361 | return JSON([])
362 | }
363 | return JSON(self._value.allObjects)
364 | }
365 | }
366 | extension JSON : SequenceType {
367 | public func generate()->AnyGenerator<(AnyObject,JSON)> {
368 | switch _value {
369 | case let o as NSArray:
370 | var i = -1
371 | return anyGenerator {
372 | if ++i == o.count { return nil }
373 | return (i, JSON(o[i]))
374 | }
375 | case let o as NSDictionary:
376 | var ks = Array(o.allKeys.reverse())
377 | return anyGenerator {
378 | if ks.isEmpty { return nil }
379 | if let k = ks.removeLast() as? String {
380 | return (k, JSON(o.valueForKey(k)!))
381 | } else {
382 | return nil
383 | }
384 | }
385 | default:
386 | return anyGenerator{ nil }
387 | }
388 | }
389 | public func mutableCopyOfTheObject() -> AnyObject {
390 | return _value.mutableCopy()
391 | }
392 | }
393 | extension JSON : CustomStringConvertible {
394 | /// stringifies self.
395 | /// if pretty:true it pretty prints
396 | public func toString(pretty:Bool=false)->String {
397 | switch _value {
398 | case is NSError: return "\(_value)"
399 | case is NSNull: return "null"
400 | case let o as NSNumber:
401 | switch String.fromCString(o.objCType)! {
402 | case "c", "C":
403 | return o.boolValue.description
404 | case "q", "l", "i", "s":
405 | return o.longLongValue.description
406 | case "Q", "L", "I", "S":
407 | return o.unsignedLongLongValue.description
408 | default:
409 | switch o.doubleValue {
410 | case 0.0/0.0: return "0.0/0.0" // NaN
411 | case -1.0/0.0: return "-1.0/0.0" // -infinity
412 | case +1.0/0.0: return "+1.0/0.0" // infinity
413 | default:
414 | return o.doubleValue.description
415 | }
416 | }
417 | case let o as NSString:
418 | return o.debugDescription
419 | default:
420 | let opts = pretty ? NSJSONWritingOptions.PrettyPrinted : NSJSONWritingOptions()
421 | if let data = (try? NSJSONSerialization.dataWithJSONObject(
422 | _value, options:opts)) as NSData? {
423 | if let result = NSString(
424 | data:data, encoding:NSUTF8StringEncoding
425 | ) as? String {
426 | return result
427 | }
428 | }
429 | return "YOU ARE NOT SUPPOSED TO SEE THIS!"
430 | }
431 | }
432 | public var description:String { return toString() }
433 | }
--------------------------------------------------------------------------------
/LightSwordX/Lib/Regex.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Regex.swift
3 | // LightSwordX
4 | //
5 | // Created by Neko on 1/3/16.
6 | // Copyright © 2016 Neko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | class Regex {
12 | let internalExpression: NSRegularExpression
13 | let pattern: String
14 |
15 | init(_ pattern: String) {
16 | self.pattern = pattern
17 | self.internalExpression = try! NSRegularExpression(pattern: pattern, options: .CaseInsensitive)
18 | }
19 |
20 | func test(input: String) -> Bool {
21 | let matches = self.internalExpression.matchesInString(input, options: .ReportCompletion, range:NSMakeRange(0, input.length))
22 | return matches.count > 0
23 | }
24 | }
--------------------------------------------------------------------------------
/LightSwordX/Lib/SettingsHelper.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UserDefaultsHelper.swift
3 | // LightSwordX
4 | //
5 | // Created by Neko on 12/23/15.
6 | // Copyright © 2015 Neko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | public class SettingsHelper {
12 |
13 | private static let defaults = NSUserDefaults.standardUserDefaults()
14 |
15 | public class func saveValue(value: AnyObject, forKey key: String) {
16 | defaults.setValue(value, forKey: key)
17 | }
18 |
19 | public class func loadValue(defaultValue defaultValue: T, forKey key: String) -> T {
20 | let value: AnyObject? = defaults.objectForKey(key)
21 | if let v: AnyObject = value {
22 | return v as! T
23 | }
24 |
25 | return defaultValue
26 | }
27 |
28 | public class func loadValueForKey(key: String) -> T! {
29 | return loadValue(defaultValue: nil, forKey: key)
30 | }
31 |
32 | public class func removeValueForKey(key: String) {
33 | defaults.removeObjectForKey(key)
34 | }
35 |
36 | public class func reset() {
37 | defaults.removePersistentDomainForName(NSBundle.mainBundle().bundleIdentifier!)
38 | }
39 |
40 | public class func synchronize() {
41 | defaults.synchronize()
42 | }
43 | }
--------------------------------------------------------------------------------
/LightSwordX/Lib/StatisticsHelper.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Number.swift
3 | // LightSwordX
4 | //
5 | // Created by Neko on 12/27/15.
6 | // Copyright © 2015 Neko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | class StatisticsHelper {
12 |
13 | private static let KB: Double = 1024
14 | private static let MB = 1024 * KB
15 | private static let GB = 1024 * MB
16 | private static let TB = 1024 * GB
17 | private static var formatter: NSNumberFormatter!
18 |
19 | static func toStatisticsString(number: UInt64) -> (value: Double, formattedValue: String, unit: String) {
20 | if formatter == nil {
21 | formatter = NSNumberFormatter()
22 | formatter.numberStyle = .DecimalStyle
23 | }
24 |
25 | var value = Double(number)
26 | var unit = "Bytes"
27 | formatter.format = "0.0#"
28 |
29 | switch value {
30 | case let v where v > TB:
31 | value = value / TB
32 | unit = "TB"
33 | break
34 |
35 | case let v where v > GB && v <= TB:
36 | value = value / GB
37 | unit = "GB"
38 | break
39 |
40 | case let v where v > MB && v <= GB:
41 | value = value / MB
42 | unit = "MB"
43 | break
44 |
45 | case let v where v > KB && v <= MB:
46 | value = value / KB
47 | unit = "KB"
48 | break
49 |
50 | default:
51 | formatter.format = "0"
52 | break
53 | }
54 |
55 | return (value: value, formattedValue: formatter.stringFromNumber(value)!, unit: unit)
56 | }
57 |
58 | static func getUptimeInMilliseconds() -> UInt64 {
59 | let kOneMillion: UInt64 = 1000 * 1000;
60 | var s_timebase_info = mach_timebase_info_data_t();
61 |
62 | if (s_timebase_info.denom == 0) {
63 | mach_timebase_info(&s_timebase_info);
64 | }
65 |
66 | // mach_absolute_time() returns billionth of seconds,
67 | // so divide by one million to get milliseconds
68 | return mach_absolute_time() * UInt64(s_timebase_info.numer) / (kOneMillion * UInt64(s_timebase_info.denom))
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/LightSwordX/Lib/String.swift:
--------------------------------------------------------------------------------
1 | //
2 | // String.swift
3 | // LightSwordX
4 | //
5 | // Created by Neko on 12/19/15.
6 | // Copyright © 2015 Neko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | extension String {
12 |
13 | public init?(count: Int, byRepeatingString str: String) {
14 | var newString = ""
15 |
16 | for _ in 0 ..< count {
17 | newString += str
18 | }
19 |
20 | self.init(newString)
21 | }
22 |
23 | var length: Int {
24 | get {
25 | return self.characters.count
26 | }
27 | }
28 |
29 | func beginsWith (str: String) -> Bool {
30 | if let range = self.rangeOfString(str) {
31 | return range.startIndex == self.startIndex
32 | }
33 | return false
34 | }
35 |
36 | func endsWith (str: String) -> Bool {
37 | if let range = self.rangeOfString(str, options: .BackwardsSearch) {
38 | return range.endIndex == self.endIndex
39 | }
40 | return false
41 | }
42 |
43 | func indexOf(target: String) -> Int? {
44 | guard let range = self.rangeOfString(target) else {
45 | return nil
46 | }
47 |
48 | return startIndex.distanceTo(range.startIndex)
49 | }
50 |
51 | func lastIndexOf(target: String) -> Int {
52 | guard let range = self.rangeOfString(target, options: .BackwardsSearch) else {
53 | return -1
54 | }
55 |
56 | return startIndex.distanceTo(range.startIndex)
57 | }
58 | }
--------------------------------------------------------------------------------
/LightSwordX/LightSwordX-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | //
2 | // Use this file to import your target's public headers that you would like to expose to Swift.
3 | //
4 |
5 | #import
6 |
--------------------------------------------------------------------------------
/LightSwordX/LightSwordX.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 | com.apple.security.network.client
8 |
9 | com.apple.security.network.server
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/LightSwordX/Models/UserServer.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Server.swift
3 | // LightSwordX
4 | //
5 | // Created by Neko on 12/23/15.
6 | // Copyright © 2015 Neko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | class UserServer: Equatable {
12 | var address = "127.0.0.1"
13 | var port = 8900
14 | var listenAddr = "127.0.0.1"
15 | var listenPort = 1080
16 | var cipherAlgorithm = "aes-256-cfb"
17 | var password = "lightsword.neko"
18 | var keepConnection = false
19 | var proxyMode = ProxyMode.WHITE
20 | var id = 0
21 | }
22 |
23 | func ==(lhs: UserServer, rhs: UserServer) -> Bool {
24 | return lhs.address == rhs.address && lhs.port == rhs.port && lhs.listenPort == rhs.listenPort && lhs.listenAddr == rhs.listenAddr && lhs.cipherAlgorithm == rhs.cipherAlgorithm && lhs.password == rhs.password && lhs.keepConnection == rhs.keepConnection
25 | }
--------------------------------------------------------------------------------
/LightSwordX/Socket/ysocket.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) <2014>, skysent
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | 1. Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | 2. Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | 3. All advertising materials mentioning features or use of this software
13 | must display the following acknowledgement:
14 | This product includes software developed by skysent.
15 | 4. Neither the name of the skysent nor the
16 | names of its contributors may be used to endorse or promote products
17 | derived from this software without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY skysent ''AS IS'' AND ANY
20 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 | DISCLAIMED. IN NO EVENT SHALL skysent BE LIABLE FOR ANY
23 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | */
30 |
31 | import Foundation
32 | public class YSocket{
33 | var addr:String
34 | var port:Int
35 | var fd:Int32?
36 | init(){
37 | self.addr=""
38 | self.port=0
39 | }
40 | public init(addr a:String,port p:Int){
41 | self.addr=a
42 | self.port=p
43 | }
44 | }
--------------------------------------------------------------------------------
/LightSwordX/Socket/ytcpsocket.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) <2014>, skysent
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | 1. Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | 2. Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | 3. All advertising materials mentioning features or use of this software
13 | must display the following acknowledgement:
14 | This product includes software developed by skysent.
15 | 4. Neither the name of the skysent nor the
16 | names of its contributors may be used to endorse or promote products
17 | derived from this software without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY skysent ''AS IS'' AND ANY
20 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 | DISCLAIMED. IN NO EVENT SHALL skysent BE LIABLE FOR ANY
23 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | */
30 | #include
31 | #include
32 | #include
33 | #include
34 | #include
35 | #include
36 | #include
37 | #include
38 | #include
39 | #include
40 | #include
41 | #include
42 | #include
43 | #include
44 | #include
45 | void ytcpsocket_set_block(int socket,int on) {
46 | int flags;
47 | flags = fcntl(socket,F_GETFL,0);
48 | if (on==0) {
49 | fcntl(socket, F_SETFL, flags | O_NONBLOCK);
50 | }else{
51 | flags &= ~ O_NONBLOCK;
52 | fcntl(socket, F_SETFL, flags);
53 | }
54 | }
55 | int ytcpsocket_connect(const char *host,int port,int timeout){
56 | struct sockaddr_in sa;
57 | struct hostent *hp;
58 | int sockfd = -1;
59 | hp = gethostbyname(host);
60 | if(hp==NULL){
61 | return -1;
62 | }
63 | bcopy((char *)hp->h_addr, (char *)&sa.sin_addr, hp->h_length);
64 | sa.sin_family = hp->h_addrtype;
65 | sa.sin_port = htons(port);
66 | sockfd = socket(hp->h_addrtype, SOCK_STREAM, 0);
67 | ytcpsocket_set_block(sockfd,0);
68 | connect(sockfd, (struct sockaddr *)&sa, sizeof(sa));
69 | fd_set fdwrite;
70 | struct timeval tvSelect;
71 | FD_ZERO(&fdwrite);
72 | FD_SET(sockfd, &fdwrite);
73 | tvSelect.tv_sec = timeout;
74 | tvSelect.tv_usec = 0;
75 | int retval = select(sockfd + 1,NULL, &fdwrite, NULL, &tvSelect);
76 | if (retval<0) {
77 | close(sockfd);
78 | return -2;
79 | }else if(retval==0){//timeout
80 | close(sockfd);
81 | return -3;
82 | }else{
83 | int error=0;
84 | int errlen=sizeof(error);
85 | getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, (socklen_t *)&errlen);
86 | if(error!=0){
87 | close(sockfd);
88 | return -4;//connect fail
89 | }
90 | ytcpsocket_set_block(sockfd, 1);
91 | int set = 1;
92 | setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));
93 | return sockfd;
94 | }
95 | }
96 | int ytcpsocket_close(int socketfd){
97 | return close(socketfd);
98 | }
99 | int ytcpsocket_pull(int socketfd,char *data,int len,int timeout_sec){
100 | if (timeout_sec>0) {
101 | fd_set fdset;
102 | struct timeval timeout;
103 | timeout.tv_usec = 0;
104 | timeout.tv_sec = timeout_sec;
105 | FD_ZERO(&fdset);
106 | FD_SET(socketfd, &fdset);
107 | int ret = select(socketfd+1, &fdset, NULL, NULL, &timeout);
108 | if (ret<=0) {
109 | return ret; // select-call failed or timeout occurred (before anything was sent)
110 | }
111 | }
112 | int readlen=(int)read(socketfd,data,len);
113 | return readlen;
114 | }
115 | int ytcpsocket_send(int socketfd,const char *data,int len){
116 | int byteswrite=0;
117 | while (len-byteswrite>0) {
118 | int writelen=(int)write(socketfd, data+byteswrite, len-byteswrite);
119 | if (writelen<0) {
120 | return -1;
121 | }
122 | byteswrite+=writelen;
123 | }
124 | return byteswrite;
125 | }
126 | //return socket fd
127 | int ytcpsocket_listen(const char *addr,int port){
128 | //create socket
129 | int socketfd=socket(AF_INET, SOCK_STREAM, 0);
130 | int reuseon = 1;
131 | setsockopt( socketfd, SOL_SOCKET, SO_REUSEADDR, &reuseon, sizeof(reuseon) );
132 | //bind
133 | struct sockaddr_in serv_addr;
134 | memset( &serv_addr, '\0', sizeof(serv_addr));
135 | serv_addr.sin_family = AF_INET;
136 | serv_addr.sin_addr.s_addr = inet_addr(addr);
137 | serv_addr.sin_port = htons(port);
138 | int r=bind(socketfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
139 | if(r==0){
140 | if (listen(socketfd, 128)==0) {
141 | return socketfd;
142 | }else{
143 | return -2;//listen error
144 | }
145 | }else{
146 | return -1;//bind error
147 | }
148 | }
149 | //return client socket fd
150 | int ytcpsocket_accept(int onsocketfd,char *remoteip,int* remoteport){
151 | socklen_t clilen;
152 | struct sockaddr_in cli_addr;
153 | clilen = sizeof(cli_addr);
154 | int newsockfd = accept(onsocketfd, (struct sockaddr *) &cli_addr, &clilen);
155 | char *clientip=inet_ntoa(cli_addr.sin_addr);
156 | memcpy(remoteip, clientip, strlen(clientip));
157 | *remoteport=cli_addr.sin_port;
158 | if(newsockfd>0){
159 | return newsockfd;
160 | }else{
161 | return -1;
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/LightSwordX/Socket/ytcpsocket.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) <2014>, skysent
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | 1. Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | 2. Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | 3. All advertising materials mentioning features or use of this software
13 | must display the following acknowledgement:
14 | This product includes software developed by skysent.
15 | 4. Neither the name of the skysent nor the
16 | names of its contributors may be used to endorse or promote products
17 | derived from this software without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY skysent ''AS IS'' AND ANY
20 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 | DISCLAIMED. IN NO EVENT SHALL skysent BE LIABLE FOR ANY
23 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | */
30 | import Foundation
31 |
32 | @asmname("ytcpsocket_connect") func c_ytcpsocket_connect(host:UnsafePointer,port:Int32,timeout:Int32) -> Int32
33 | @asmname("ytcpsocket_close") func c_ytcpsocket_close(fd:Int32) -> Int32
34 | @asmname("ytcpsocket_send") func c_ytcpsocket_send(fd:Int32,buff:UnsafePointer,len:Int32) -> Int32
35 | @asmname("ytcpsocket_pull") func c_ytcpsocket_pull(fd:Int32,buff:UnsafePointer,len:Int32,timeout:Int32) -> Int32
36 | @asmname("ytcpsocket_listen") func c_ytcpsocket_listen(addr:UnsafePointer,port:Int32)->Int32
37 | @asmname("ytcpsocket_accept") func c_ytcpsocket_accept(onsocketfd:Int32,ip:UnsafePointer,port:UnsafePointer) -> Int32
38 |
39 | public class TCPClient:YSocket{
40 | /*
41 | * connect to server
42 | * return success or fail with message
43 | */
44 | public func connect(timeout t:Int)->(Bool,String){
45 | let rs:Int32=c_ytcpsocket_connect(self.addr, port: Int32(self.port), timeout: Int32(t))
46 | if rs>0{
47 | self.fd=rs
48 | return (true,"connect success")
49 | }else{
50 | switch rs{
51 | case -1:
52 | return (false,"query server fail")
53 | case -2:
54 | return (false,"connection closed")
55 | case -3:
56 | return (false,"connect timeout")
57 | default:
58 | return (false,"unknow err.")
59 | }
60 | }
61 | }
62 | /*
63 | * close socket
64 | * return success or fail with message
65 | */
66 | public func close()->(Bool,String){
67 | if let fd:Int32=self.fd{
68 | c_ytcpsocket_close(fd)
69 | self.fd=nil
70 | return (true,"close success")
71 | }else{
72 | return (false,"socket not open")
73 | }
74 | }
75 | /*
76 | * send data
77 | * return success or fail with message
78 | */
79 | public func send(data d:[UInt8])->(Bool,String){
80 | if let fd:Int32=self.fd{
81 | let sendsize:Int32=c_ytcpsocket_send(fd, buff: d, len: Int32(d.count))
82 | if Int(sendsize)==d.count{
83 | return (true,"send success")
84 | }else{
85 | return (false,"send error")
86 | }
87 | }else{
88 | return (false,"socket not open")
89 | }
90 | }
91 | /*
92 | * send string
93 | * return success or fail with message
94 | */
95 | public func send(str s:String)->(Bool,String){
96 | if let fd:Int32=self.fd{
97 | let sendsize:Int32=c_ytcpsocket_send(fd, buff: s, len: Int32(strlen(s)))
98 | if sendsize==Int32(strlen(s)){
99 | return (true,"send success")
100 | }else{
101 | return (false,"send error")
102 | }
103 | }else{
104 | return (false,"socket not open")
105 | }
106 | }
107 | /*
108 | *
109 | * send nsdata
110 | */
111 | public func send(data d:NSData)->(Bool,String){
112 | if let fd:Int32=self.fd{
113 | var buff:[UInt8] = [UInt8](count:d.length,repeatedValue:0x0)
114 | d.getBytes(&buff, length: d.length)
115 | let sendsize:Int32=c_ytcpsocket_send(fd, buff: buff, len: Int32(d.length))
116 | if sendsize==Int32(d.length){
117 | return (true,"send success")
118 | }else{
119 | return (false,"send error")
120 | }
121 | }else{
122 | return (false,"socket not open")
123 | }
124 | }
125 | /*
126 | * read data with expect length
127 | * return success or fail with message
128 | */
129 | public func read(expectlen:Int, timeout:Int = -1)->[UInt8]?{
130 | if let fd:Int32 = self.fd{
131 | var buff:[UInt8] = [UInt8](count:expectlen,repeatedValue:0x0)
132 | let readLen:Int32=c_ytcpsocket_pull(fd, buff: &buff, len: Int32(expectlen), timeout: Int32(timeout))
133 | if readLen<=0{
134 | return nil
135 | }
136 | let rs=buff[0...Int(readLen-1)]
137 | let data:[UInt8] = Array(rs)
138 | return data
139 | }
140 | return nil
141 | }
142 | }
143 |
144 | public class TCPServer:YSocket{
145 |
146 | public func listen()->(Bool,String){
147 |
148 | let fd:Int32=c_ytcpsocket_listen(self.addr, port: Int32(self.port))
149 | if fd>0{
150 | self.fd=fd
151 | return (true,"listen success")
152 | }else{
153 | return (false,"listen fail")
154 | }
155 | }
156 | public func accept()->TCPClient?{
157 | if let serferfd=self.fd{
158 | var buff:[Int8] = [Int8](count:16,repeatedValue:0x0)
159 | var port:Int32=0
160 | let clientfd:Int32=c_ytcpsocket_accept(serferfd, ip: &buff,port: &port)
161 | if clientfd<0{
162 | return nil
163 | }
164 | let tcpClient:TCPClient=TCPClient()
165 | tcpClient.fd=clientfd
166 | tcpClient.port=Int(port)
167 | if let addr=String(CString: buff, encoding: NSUTF8StringEncoding){
168 | tcpClient.addr=addr
169 | }
170 | return tcpClient
171 | }
172 | return nil
173 | }
174 | public func close()->(Bool,String){
175 | if let fd:Int32=self.fd{
176 | c_ytcpsocket_close(fd)
177 | self.fd=nil
178 | return (true,"close success")
179 | }else{
180 | return (false,"socket not open")
181 | }
182 | }
183 | }
184 |
185 |
186 |
--------------------------------------------------------------------------------
/LightSwordX/Socket/yudpsocket.c:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) <2014>, skysent
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | 1. Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | 2. Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | 3. All advertising materials mentioning features or use of this software
13 | must display the following acknowledgement:
14 | This product includes software developed by skysent.
15 | 4. Neither the name of the skysent nor the
16 | names of its contributors may be used to endorse or promote products
17 | derived from this software without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY skysent ''AS IS'' AND ANY
20 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 | DISCLAIMED. IN NO EVENT SHALL skysent BE LIABLE FOR ANY
23 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | */
30 |
31 | #include
32 | #include
33 | #include
34 | #include
35 | #include
36 | #include
37 | #include
38 | #include
39 | #define yudpsocket_buff_len 8192
40 |
41 | //return socket fd
42 | int yudpsocket_server(const char *addr,int port){
43 | //create socket
44 | int socketfd=socket(AF_INET, SOCK_DGRAM, 0);
45 | int reuseon = 1;
46 | setsockopt( socketfd, SOL_SOCKET, SO_REUSEADDR, &reuseon, sizeof(reuseon) );
47 | //bind
48 | struct sockaddr_in serv_addr;
49 | memset( &serv_addr, '\0', sizeof(serv_addr));
50 | serv_addr.sin_family = AF_INET;
51 | serv_addr.sin_addr.s_addr = inet_addr(addr);
52 | serv_addr.sin_port = htons(port);
53 | int r=bind(socketfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
54 | if(r==0){
55 | return socketfd;
56 | }else{
57 | return -1;
58 | }
59 | }
60 | int yudpsocket_recive(int socket_fd,char *outdata,int expted_len,char *remoteip,int* remoteport){
61 | struct sockaddr_in cli_addr;
62 | socklen_t clilen=sizeof(cli_addr);
63 | memset(&cli_addr, 0x0, sizeof(struct sockaddr_in));
64 | int len=(int)recvfrom(socket_fd, outdata, expted_len, 0, (struct sockaddr *)&cli_addr, &clilen);
65 | char *clientip=inet_ntoa(cli_addr.sin_addr);
66 | memcpy(remoteip, clientip, strlen(clientip));
67 | *remoteport=cli_addr.sin_port;
68 | return len;
69 | }
70 | int yudpsocket_close(int socket_fd){
71 | return close(socket_fd);
72 | }
73 | //return socket fd
74 | int yudpsocket_client(){
75 | //create socket
76 | int socketfd=socket(AF_INET, SOCK_DGRAM, 0);
77 | int reuseon = 1;
78 | setsockopt( socketfd, SOL_SOCKET, SO_REUSEADDR, &reuseon, sizeof(reuseon) );
79 | return socketfd;
80 | }
81 | int yudpsocket_get_server_ip(char *host,char *ip){
82 | struct hostent *hp;
83 | struct sockaddr_in addr;
84 | hp = gethostbyname(host);
85 | if(hp==NULL){
86 | return -1;
87 | }
88 | bcopy((char *)hp->h_addr, (char *)&addr.sin_addr, hp->h_length);
89 | char *clientip=inet_ntoa(addr.sin_addr);
90 | memcpy(ip, clientip, strlen(clientip));
91 | return 0;
92 | }
93 | //send message to addr and port
94 | int yudpsocket_sentto(int socket_fd,char *msg,int len, char *toaddr, int topotr){
95 | struct sockaddr_in addr;
96 | socklen_t addrlen=sizeof(addr);
97 | memset(&addr, 0x0, sizeof(struct sockaddr_in));
98 | addr.sin_family=AF_INET;
99 | addr.sin_port=htons(topotr);
100 | addr.sin_addr.s_addr=inet_addr(toaddr);
101 | int sendlen=(int)sendto(socket_fd, msg, len, 0, (struct sockaddr *)&addr, addrlen);
102 | return sendlen;
103 | }
104 |
105 |
106 |
--------------------------------------------------------------------------------
/LightSwordX/Socket/yudpsocket.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) <2014>, skysent
3 | All rights reserved.
4 |
5 | Redistribution and use in source and binary forms, with or without
6 | modification, are permitted provided that the following conditions are met:
7 | 1. Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | 2. Redistributions in binary form must reproduce the above copyright
10 | notice, this list of conditions and the following disclaimer in the
11 | documentation and/or other materials provided with the distribution.
12 | 3. All advertising materials mentioning features or use of this software
13 | must display the following acknowledgement:
14 | This product includes software developed by skysent.
15 | 4. Neither the name of the skysent nor the
16 | names of its contributors may be used to endorse or promote products
17 | derived from this software without specific prior written permission.
18 |
19 | THIS SOFTWARE IS PROVIDED BY skysent ''AS IS'' AND ANY
20 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 | DISCLAIMED. IN NO EVENT SHALL skysent BE LIABLE FOR ANY
23 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 | */
30 |
31 | import Foundation
32 |
33 | @asmname("yudpsocket_server") func c_yudpsocket_server(host:UnsafePointer,port:Int32) -> Int32
34 | @asmname("yudpsocket_recive") func c_yudpsocket_recive(fd:Int32,buff:UnsafePointer,len:Int32,ip:UnsafePointer,port:UnsafePointer) -> Int32
35 | @asmname("yudpsocket_close") func c_yudpsocket_close(fd:Int32) -> Int32
36 | @asmname("yudpsocket_client") func c_yudpsocket_client() -> Int32
37 | @asmname("yudpsocket_get_server_ip") func c_yudpsocket_get_server_ip(host:UnsafePointer,ip:UnsafePointer) -> Int32
38 | @asmname("yudpsocket_sentto") func c_yudpsocket_sentto(fd:Int32,buff:UnsafePointer,len:Int32,ip:UnsafePointer,port:Int32) -> Int32
39 |
40 | public class UDPClient: YSocket {
41 | public override init(addr a:String,port p:Int){
42 | super.init()
43 | let remoteipbuff:[Int8] = [Int8](count:16,repeatedValue:0x0)
44 | let ret=c_yudpsocket_get_server_ip(a, ip: remoteipbuff)
45 | if ret==0{
46 | if let ip=String(CString: remoteipbuff, encoding: NSUTF8StringEncoding){
47 | self.addr=ip
48 | self.port=p
49 | let fd:Int32=c_yudpsocket_client()
50 | if fd>0{
51 | self.fd=fd
52 | }
53 | }
54 | }
55 | }
56 | /*
57 | * send data
58 | * return success or fail with message
59 | */
60 | public func send(data d:[UInt8])->(Bool,String){
61 | if let fd:Int32=self.fd{
62 | let sendsize:Int32=c_yudpsocket_sentto(fd, buff: d, len: Int32(d.count), ip: self.addr,port: Int32(self.port))
63 | if Int(sendsize)==d.count{
64 | return (true,"send success")
65 | }else{
66 | return (false,"send error")
67 | }
68 | }else{
69 | return (false,"socket not open")
70 | }
71 | }
72 | /*
73 | * send string
74 | * return success or fail with message
75 | */
76 | public func send(str s:String)->(Bool,String){
77 | if let fd:Int32=self.fd{
78 | let sendsize:Int32=c_yudpsocket_sentto(fd, buff: s, len: Int32(strlen(s)), ip: self.addr,port: Int32(self.port))
79 | if sendsize==Int32(strlen(s)){
80 | return (true,"send success")
81 | }else{
82 | return (false,"send error")
83 | }
84 | }else{
85 | return (false,"socket not open")
86 | }
87 | }
88 | /*
89 | *
90 | * send nsdata
91 | */
92 | public func send(data d:NSData)->(Bool,String){
93 | if let fd:Int32=self.fd{
94 | var buff:[UInt8] = [UInt8](count:d.length,repeatedValue:0x0)
95 | d.getBytes(&buff, length: d.length)
96 | let sendsize:Int32=c_yudpsocket_sentto(fd, buff: buff, len: Int32(d.length), ip: self.addr,port: Int32(self.port))
97 | if sendsize==Int32(d.length){
98 | return (true,"send success")
99 | }else{
100 | return (false,"send error")
101 | }
102 | }else{
103 | return (false,"socket not open")
104 | }
105 | }
106 | public func close()->(Bool,String){
107 | if let fd:Int32=self.fd{
108 | c_yudpsocket_close(fd)
109 | self.fd=nil
110 | return (true,"close success")
111 | }else{
112 | return (false,"socket not open")
113 | }
114 | }
115 | //TODO add multycast and boardcast
116 | }
117 |
118 | public class UDPServer:YSocket{
119 | public override init(addr a:String,port p:Int){
120 | super.init(addr: a, port: p)
121 | let fd:Int32 = c_yudpsocket_server(self.addr, port: Int32(self.port))
122 | if fd>0{
123 | self.fd=fd
124 | }
125 | }
126 | //TODO add multycast and boardcast
127 | public func recv(expectlen:Int)->([UInt8]?,String,Int){
128 | if let fd:Int32 = self.fd{
129 | var buff:[UInt8] = [UInt8](count:expectlen,repeatedValue:0x0)
130 | var remoteipbuff:[Int8] = [Int8](count:16,repeatedValue:0x0)
131 | var remoteport:Int32=0
132 | let readLen:Int32=c_yudpsocket_recive(fd, buff: buff, len: Int32(expectlen), ip: &remoteipbuff, port: &remoteport)
133 | let port:Int=Int(remoteport)
134 | var addr:String=""
135 | if let ip=String(CString: remoteipbuff, encoding: NSUTF8StringEncoding){
136 | addr=ip
137 | }
138 | if readLen<=0{
139 | return (nil,addr,port)
140 | }
141 | let rs=buff[0...Int(readLen-1)]
142 | let data:[UInt8] = Array(rs)
143 | return (data,addr,port)
144 | }
145 | return (nil,"no ip",0)
146 | }
147 | public func close()->(Bool,String){
148 | if let fd:Int32=self.fd{
149 | c_yudpsocket_close(fd)
150 | self.fd=nil
151 | return (true,"close success")
152 | }else{
153 | return (false,"socket not open")
154 | }
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/LightSwordX/Socket6/Socket.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Socket.swift
3 | // LightSwordX
4 | //
5 | // Created by Neko on 1/9/16.
6 | // Copyright © 2016 Neko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | class Socket {
12 | var addr: String
13 | var port: Int
14 | var fd: Int32?
15 | internal var _timeout = -1
16 |
17 | init() {
18 | self.addr = ""
19 | self.port = 0
20 | }
21 |
22 | init(addr a: String, port p: Int) {
23 | self.addr = a
24 | self.port = p
25 | }
26 | }
--------------------------------------------------------------------------------
/LightSwordX/Socket6/TCPSocket.c:
--------------------------------------------------------------------------------
1 | //
2 | // TCPSocket.c
3 | // LightSwordX
4 | //
5 | // Created by Neko on 1/9/16.
6 | // Copyright © 2016 Neko. All rights reserved.
7 | //
8 |
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 |
25 | char* get_ip_str(const struct sockaddr *sa, char *s, unsigned int maxlen)
26 | {
27 | switch(sa->sa_family) {
28 | case AF_INET:
29 | inet_ntop(AF_INET, &(((struct sockaddr_in *)sa)->sin_addr), s, maxlen);
30 | break;
31 |
32 | case AF_INET6:
33 | inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)sa)->sin6_addr), s, maxlen);
34 | break;
35 |
36 | default:
37 | strncpy(s, "Unknown AF", maxlen);
38 | return NULL;
39 | }
40 |
41 | return s;
42 | }
43 |
44 | void fill_addrinfo_port(const struct addrinfo* addr, int port) {
45 | if (addr->ai_family == AF_INET) {
46 | struct sockaddr_in* ipv4 = (struct sockaddr_in*)(addr->ai_addr);
47 | ipv4->sin_port = htons(port);
48 | } else if (addr->ai_family == AF_INET6) {
49 | struct sockaddr_in6* ipv6 = (struct sockaddr_in6*)(addr->ai_addr);
50 | ipv6->sin6_port = htons(port);
51 | }
52 | }
53 |
54 | void tcpsocket_set_block(int socket, int on) {
55 | int flags = fcntl(socket, F_GETFL, 0);
56 |
57 | if (on == 0) {
58 | fcntl(socket, F_SETFL, flags | O_NONBLOCK);
59 | } else {
60 | flags &= ~ O_NONBLOCK;
61 | fcntl(socket, F_SETFL, flags);
62 | }
63 | }
64 |
65 | int tcpsocket_connect(const char* host, int port, int timeout) {
66 |
67 | struct addrinfo hints, *addrs, *p;
68 | memset(&hints, 0, sizeof(hints));
69 | hints.ai_family = AF_UNSPEC;
70 | hints.ai_socktype = SOCK_STREAM;
71 |
72 | int s = getaddrinfo(host, NULL, &hints, &addrs);
73 | if (s != 0) {
74 | return -1;
75 | }
76 |
77 | int socketfd = -1;
78 | int error = -1;
79 | int errorlen = sizeof(error);
80 |
81 | for (p = addrs; p != NULL; p = p->ai_next) {
82 |
83 | socketfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
84 | if (socketfd == -1) {
85 | error = socketfd;
86 | continue;
87 | }
88 |
89 | fill_addrinfo_port(p, port);
90 |
91 | tcpsocket_set_block(socketfd, 0); // Set non-block socket
92 | connect(socketfd, p->ai_addr, p->ai_addrlen);
93 |
94 | fd_set fdset;
95 | FD_ZERO(&fdset);
96 | FD_SET(socketfd, &fdset);
97 |
98 | struct timeval tv;
99 | tv.tv_sec = timeout;
100 | tv.tv_usec = 0;
101 |
102 | int retval = select(socketfd + 1, NULL, &fdset, NULL, &tv);
103 | if (retval <= 0) {
104 | close(socketfd); // Error or Timeout
105 | socketfd = -1;
106 | error = retval < 0 ? -2 : -3;
107 | continue;
108 | }
109 |
110 | getsockopt(socketfd, SOL_SOCKET, SO_ERROR, &error, (socklen_t *)&errorlen);
111 | if (error != 0) {
112 | fprintf(stderr, "failed to connect: %s\n", gai_strerror(error));
113 | close(socketfd); // Failed to connect
114 | socketfd = -1;
115 | continue;
116 | }
117 |
118 | tcpsocket_set_block(socketfd, 1);
119 | int set = 1;
120 | setsockopt(socketfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));
121 |
122 | break;
123 | }
124 |
125 | freeaddrinfo(addrs);
126 |
127 | return socketfd > 0 ? socketfd : error;
128 | }
129 |
130 | int tcpsocket_close(int socketfd) {
131 | return close(socketfd);
132 | }
133 |
134 | int tcpsocket_read(int socketfd, char* data, int len) {
135 | return (int)read(socketfd, data, len);
136 | }
137 |
138 | int tcpsocket_send(int socketfd, const char* data, int len) {
139 | int byteswrote = 0;
140 | while (len - byteswrote > 0) {
141 | int wrotelen = (int)write(socketfd, data + byteswrote, len - byteswrote);
142 | if (wrotelen < 0) {
143 | return -1;
144 | }
145 |
146 | byteswrote += wrotelen;
147 | }
148 |
149 | return byteswrote;
150 | }
151 |
152 | int tcpsocket_accept(int socketfd, char* remoteip, int* remoteport) {
153 | char clienthost[NI_MAXHOST];
154 | char clientservice[NI_MAXSERV];
155 |
156 | struct sockaddr_storage clientaddr;
157 | socklen_t addrlen = sizeof(clientaddr);
158 |
159 | int connfd = accept(socketfd, (struct sockaddr *)&clientaddr, &addrlen);
160 | if (getnameinfo((struct sockaddr *)&clientaddr, addrlen, clienthost, NI_MAXHOST, clientservice, NI_MAXSERV, NI_NUMERICHOST)) {
161 | fprintf(stderr, "can not resolve name");
162 | } else {
163 | if (clientaddr.ss_family == AF_INET) {
164 | struct sockaddr_in* ipv4 = (struct sockaddr_in *)&clientaddr;
165 | char* clientip = inet_ntoa(ipv4->sin_addr);
166 | memcpy(remoteip, clientip, strlen(clientip));
167 | *remoteport = ipv4->sin_port;
168 | } else if (clientaddr.ss_family == AF_INET6) {
169 | struct sockaddr_in6* ipv6 = (struct sockaddr_in6 *)&clientaddr;
170 | char clientip[INET6_ADDRSTRLEN];
171 | inet_ntop(AF_INET6, &(ipv6->sin6_addr), clientip, INET6_ADDRSTRLEN);
172 | memcpy(remoteip, clientip, strlen(clientip));
173 | *remoteport = ipv6->sin6_port;
174 | }
175 | }
176 |
177 | return connfd > 0 ? connfd : -1;
178 | }
179 |
180 | int tcpsocket_listen(const char *addr,int port){
181 |
182 | int socketfd=socket(AF_INET, SOCK_STREAM, 0);
183 | int reuseon = 1;
184 |
185 | setsockopt( socketfd, SOL_SOCKET, SO_REUSEADDR, &reuseon, sizeof(reuseon) );
186 |
187 | //bind
188 | struct sockaddr_in serv_addr;
189 | memset( &serv_addr, '\0', sizeof(serv_addr));
190 | serv_addr.sin_family = AF_INET;
191 | serv_addr.sin_addr.s_addr = inet_addr(addr);
192 | serv_addr.sin_port = htons(port);
193 |
194 | int r = bind(socketfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
195 | if(r == 0){
196 | if (listen(socketfd, 128) == 0) {
197 | return socketfd;
198 | }else{
199 | return -2;//listen error
200 | }
201 | }else{
202 | return -1;//bind error
203 | }
204 | }
205 |
206 | int tcpsocket6_listen(const char* addr, int port) {
207 |
208 | int socketfd = socket(AF_INET6, SOCK_STREAM, 0);
209 |
210 | int reuse = 1;
211 | setsockopt(socketfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
212 |
213 | if (socketfd < 0) {
214 | return socketfd;
215 | }
216 |
217 | struct sockaddr_in6 sa;
218 | memset(&sa, 0, sizeof(sa));
219 | sa.sin6_port = htons(port);
220 | sa.sin6_family = AF_INET6;
221 | sa.sin6_len = sizeof(sa);
222 | inet_pton(AF_INET6, addr, &(sa.sin6_addr));
223 |
224 | int b = bind(socketfd, (struct sockaddr *) &sa, sizeof(sa));
225 | if (b != 0) {
226 | fprintf(stderr, "%s\n", gai_strerror(b));
227 | return -1;
228 | }
229 |
230 | int l = listen(socketfd, 128);
231 | if (l !=0 ) {
232 | fprintf(stderr, "%s\n", gai_strerror(b));
233 | return -2;
234 | }
235 |
236 | return socketfd;
237 | }
238 |
239 | void set_socket_timeout(int socketfd, int timeout) {
240 |
241 | if (timeout < 0) return;
242 |
243 | struct timeval tv;
244 |
245 | tv.tv_sec = timeout > 0 ? timeout : 0;
246 | tv.tv_usec = 0;
247 |
248 | setsockopt(socketfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval));
249 | }
--------------------------------------------------------------------------------
/LightSwordX/Socks5/Socks5Constants.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Socks5Constants.swift
3 | // LightSwordX
4 | //
5 | // Created by Neko on 12/17/15.
6 | // Copyright © 2015 Neko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | enum Authentication: UInt8 {
12 | case NOAUTH = 0x00
13 | case GSSAPI = 0x01
14 | case USERPASS = 0x02
15 | case NONE = 0xFF
16 | }
17 |
18 | enum REQUEST_CMD: UInt8 {
19 | case CONNECT = 0x01
20 | case BIND = 0x02
21 | case UDP_ASSOCIATE = 0x03
22 | }
23 |
24 | enum ATYP: UInt8 {
25 | case IPV4 = 0x01
26 | case DN = 0x03
27 | case IPV6 = 0x04
28 | }
29 |
30 | enum REPLY_CODE: UInt8 {
31 | case SUCCESS = 0x00
32 | case SOCKS_SERVER_FAILURE = 0x01
33 | case CONNECTION_NOT_ALLOWED = 0x02
34 | case NETWORK_UNREACHABLE = 0x03
35 | case HOST_UNREACHABLE = 0x04
36 | case CONNECTION_REFUSED = 0x05
37 | case TTL_EXPIRED = 0x06
38 | case CMD_NOT_SUPPORTED = 0x07
39 | case ADDR_TYPE_NOT_SUPPORTED = 0x08
40 | }
41 |
42 | enum SOCKS_VER: UInt8 {
43 | case V5 = 0x05
44 | }
45 |
--------------------------------------------------------------------------------
/LightSwordX/Socks5/Socks5Helper.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Socks5Helper.swift
3 | // LightSwordX
4 | //
5 | // Created by Neko on 12/17/15.
6 | // Copyright © 2015 Neko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import SINQ
11 |
12 | class Socks5Helper {
13 | static func refineDestination(rawData: [UInt8]) -> (cmd: REQUEST_CMD, addr: String, port: Int, headerSize: Int)? {
14 | if rawData.count < 4 {
15 | return nil
16 | }
17 |
18 | if let cmd = REQUEST_CMD(rawValue: rawData[1]) {
19 |
20 | let atyp = rawData[3]
21 | var addr = ""
22 | var dnLength: UInt8 = 0
23 |
24 | switch (atyp) {
25 | case ATYP.DN.rawValue:
26 | dnLength = rawData[4]
27 | let data = sinq(rawData).skip(5).take(Int(dnLength)).toArray()
28 | addr = NSString(bytes: data, length: data.count, encoding: NSUTF8StringEncoding) as! String
29 | break
30 |
31 | case ATYP.IPV4.rawValue:
32 | dnLength = 4
33 | addr = sinq(rawData).skip(4).take(4).aggregate("", combine: { (c: String, n: UInt8) in c.characters.count > 1 ? c + String(format: ".%d", n) : String(format: "%d.%d", c, n)})
34 | break
35 |
36 | case ATYP.IPV6.rawValue:
37 | dnLength = 16
38 | let bytes = sinq(rawData).skip(4).take(16).toArray()
39 | addr = bytes.reduce("", combine: { (s: String, n: UInt8) -> String in
40 | let length = s.length
41 | let lastSemicolon = s.lastIndexOf(":")
42 |
43 | if length == 4 {
44 | return "\(s):\(String(format: "%02x", n))"
45 | }
46 |
47 | return length - lastSemicolon == 5 ? "\(s):\(String(format: "%02x", n))" : "\(s)\(String(format: "%02x", n))"
48 | })
49 | break
50 |
51 | default:
52 | return nil
53 | }
54 |
55 | let headerSize = Int(4 + (atyp == ATYP.DN.rawValue ? 1 : 0) + dnLength + 2)
56 | if rawData.count < headerSize {
57 | return nil
58 | }
59 |
60 | let littleEndian = [rawData[headerSize - 2], rawData[headerSize - 1]]
61 | let port = UnsafePointer(littleEndian).memory.bigEndian
62 | return ( cmd, addr, Int(port), headerSize )
63 | }
64 |
65 | return nil
66 | }
67 | }
--------------------------------------------------------------------------------
/LightSwordX/Socks5/Socks5Server.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Socks5Server.swift
3 | // LightSwordX
4 | //
5 | // Created by Neko on 12/17/15.
6 | // Copyright © 2015 Neko. All rights reserved.
7 | //
8 |
9 | import SINQ
10 | import Foundation
11 | import CryptoSwift
12 |
13 | enum ProxyMode: Int {
14 | case GLOBAL = 0
15 | case BLACK = 1
16 | case WHITE = 2
17 | }
18 |
19 | class Socks5Server {
20 | var serverAddr: String!
21 | var serverPort: Int!
22 | var listenAddr: String!
23 | var listenPort: Int!
24 | var cipherAlgorithm: String!
25 | var password: String!
26 | var timeout: Int!
27 | var bypassLocal: Bool!
28 | var tag: AnyObject?
29 | var blackList: [String]!
30 | var whiteList: [String]!
31 | var proxyMode = ProxyMode.GLOBAL
32 |
33 | private(set) var sentBytes: UInt64 = 0
34 | private(set) var receivedBytes: UInt64 = 0
35 |
36 | private var server: TCPServer6!
37 | private var running = true
38 | private var queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
39 | private let localAreas = ["10.", "192.168.", "localhost", "127.0.0.1", "172.16.", "::1", "169.254.0.0"]
40 | private let localServers = ["127.0.0.1", "localhost", "::1"]
41 | private let bufferSize = 4096
42 |
43 | func startAsync(callback: (success: Bool) -> Void) {
44 | dispatch_async(queue) {
45 | self.startSync(callback)
46 | }
47 | }
48 |
49 | func startSync(callback: (success: Bool) -> Void) {
50 | running = true
51 |
52 | server = TCPServer6(addr: listenAddr, port: listenPort)
53 | let (success, msg) = server.listen()
54 | if !success {
55 | running = false
56 | callback(success: false)
57 | print(msg)
58 | return
59 | }
60 |
61 | callback(success: true)
62 | while running {
63 | if let client = server.accept() {
64 | dispatch_async(queue, { () -> Void in
65 | client.timeout = self.timeout
66 |
67 | let (data: hello, _) = client.read(768)
68 | guard hello != nil else {
69 | client.close()
70 | return
71 | }
72 |
73 | let (success, reply) = self.handleHandshake(hello!)
74 | client.send(data: reply)
75 |
76 | if !success {
77 | client.close()
78 | return
79 | }
80 |
81 | let (data, _) = client.read(self.bufferSize)
82 | guard data != nil else {
83 | client.close()
84 | return
85 | }
86 |
87 | let request: (cmd: REQUEST_CMD, addr: String, port: Int, headerSize: Int)! = Socks5Helper.refineDestination(data!)
88 | if request == nil {
89 | client.close()
90 | return
91 | }
92 |
93 | let connectLocal = sinq(self.localServers).any({ s in self.serverAddr.containsString(s)}) || self.bypassLocal.boolValue && sinq(self.localAreas).any({ s in request.addr.containsString(s)})
94 |
95 | switch(request.cmd) {
96 | case .BIND:
97 | break
98 | case .CONNECT:
99 | if (connectLocal) {
100 | self.connectToTarget(request.addr, destPort: request.port, requestBuf: data!, client: client)
101 | } else {
102 | self.connectToServer(request.addr, destPort: request.port, requestBuf: data!, client: client)
103 | }
104 |
105 | break
106 | case .UDP_ASSOCIATE:
107 | break
108 | }
109 | })
110 | }
111 | }
112 |
113 | }
114 |
115 | func stop() {
116 | running = false
117 |
118 | if server == nil {
119 | return
120 | }
121 |
122 | server.close()
123 | server = nil
124 | }
125 |
126 | private func handleHandshake(data: [UInt8]) -> (success: Bool, reply: [UInt8]) {
127 | if data.count < 2 {
128 | return (success: false, reply: [0x5, Authentication.NONE.rawValue])
129 | }
130 |
131 | let methodCount = data[1]
132 | let code = sinq(data).skip(2).take(Int(methodCount)).contains(Authentication.NOAUTH.rawValue) ? Authentication.NOAUTH : Authentication.NONE
133 |
134 | return (success: true, reply: [0x5, code.rawValue])
135 | }
136 |
137 | private func connectToTarget(destAddr: String, destPort: Int, requestBuf: [UInt8], client: TCPClient6) {
138 | let transitSocket = TCPClient6(addr: destAddr, port: destPort)
139 | let (success, msg) = transitSocket.connect(timeout: timeout)
140 | if !success {
141 | client.close()
142 | print(msg, destAddr)
143 | return
144 | }
145 |
146 | print("connected:", destAddr)
147 |
148 | var reply = requestBuf.map { n in return n }
149 | reply[0] = 0x05
150 | reply[1] = 0x00
151 |
152 | client.send(data: reply)
153 |
154 | dispatch_async(queue, { () -> Void in
155 | self.sentBytes += self.exchangeSocket(client, writeSocket: transitSocket)
156 | })
157 |
158 | dispatch_async(queue, { () -> Void in
159 | self.receivedBytes += self.exchangeSocket(transitSocket, writeSocket: client)
160 | })
161 | }
162 |
163 | private func exchangeSocket(readSocket: TCPClient6, writeSocket: TCPClient6, secret: UInt8? = nil) -> UInt64 {
164 | var bytes: UInt64 = 0
165 | var retry = 0
166 | var readSize = self.bufferSize
167 | var accidentalFailure = 0
168 |
169 | while true {
170 | let (data, errno) = readSocket.read(readSize)
171 |
172 | guard data != nil else {
173 | if errno == 0 {
174 |
175 | if accidentalFailure < 12 {
176 | accidentalFailure++
177 | continue
178 | }
179 |
180 | print("closed successful")
181 | readSocket.close()
182 | writeSocket.close()
183 | break
184 | }
185 |
186 | switch errno {
187 | case -1:
188 | print("closed failure:", accidentalFailure)
189 | readSocket.close()
190 | writeSocket.close()
191 | return bytes
192 |
193 | case EAGAIN:
194 | print("try again")
195 | continue
196 |
197 | case EINVAL:
198 | print("EINVAL")
199 | fallthrough
200 | case EFAULT:
201 | print("EFAULT")
202 | readSize += readSize
203 | break
204 |
205 | case EBADF:
206 | print("EBADF")
207 | break
208 | case EIO:
209 | print("EIO")
210 | break
211 | case EINTR:
212 | print("EINTR")
213 | break
214 | default:
215 | break
216 | }
217 |
218 | print("error:", errno)
219 |
220 | if retry < 7 {
221 | retry++
222 | print("retry", retry)
223 | continue
224 | }
225 |
226 | readSocket.close()
227 | writeSocket.close()
228 | break
229 | }
230 |
231 | if accidentalFailure > 0 {
232 | print("recovered from failure -", accidentalFailure)
233 | accidentalFailure--
234 | }
235 |
236 | writeSocket.send(data: secret != nil ? data!.map{ n in n ^ secret! } : data!)
237 | bytes += UInt64(data!.count)
238 | retry = 0
239 | }
240 |
241 | return bytes
242 | }
243 |
244 | private func connectToServer(destAddr: String, destPort: Int, requestBuf: [UInt8], client: TCPClient6) {
245 | switch proxyMode {
246 | case .BLACK:
247 | if blackList != nil && sinq(blackList).any({ l in destAddr.endsWith(l) }) {
248 | break
249 | }
250 | connectToTarget(destAddr, destPort: destPort, requestBuf: requestBuf, client: client)
251 | return
252 |
253 | case .WHITE:
254 | if whiteList != nil && sinq(whiteList).any({ l in destAddr.endsWith(l) }) {
255 | connectToTarget(destAddr, destPort: destPort, requestBuf: requestBuf, client: client)
256 | return
257 | }
258 | break
259 |
260 | case .GLOBAL:
261 | break
262 | }
263 |
264 | let proxySocket = TCPClient6(addr: serverAddr, port: serverPort)
265 | let (success, msg) = proxySocket.connect(timeout: timeout)
266 | if !success {
267 | client.close()
268 | print(msg)
269 | return
270 | }
271 |
272 | let (cipher, iv) = Crypto.createCipher(cipherAlgorithm, password: password)
273 | let pl = UInt8(arc4random() % 256)
274 | let pa = AES.randomIV(Int(pl))
275 | let et = try! cipher.encrypt(sinq([VPN_TYPE.OSXCL5.rawValue, pl]).concat(pa).concat(requestBuf).toArray(), padding: nil)
276 |
277 | proxySocket.send(data: sinq(iv).concat(et).toArray())
278 |
279 | let (data, _) = proxySocket.read(1024)
280 | if data == nil || data?.count < iv.count {
281 | client.close()
282 | proxySocket.close()
283 | return
284 | }
285 |
286 | let riv = sinq(data!).take(iv.count).toArray()
287 | let (cipher: decipher, _) = Crypto.createCipher(cipherAlgorithm, password: password, iv: riv)
288 | let rlBuf = sinq(data!).skip(iv.count).toArray()
289 | var reBuf = try! decipher.decrypt(rlBuf, padding: nil)
290 | let paddingSize = reBuf[0]
291 |
292 | reBuf = sinq(reBuf).skip(1 + Int(paddingSize)).toArray()
293 | client.send(data: reBuf)
294 |
295 | print("connected:", destAddr)
296 |
297 | dispatch_async(queue, { () -> Void in
298 | self.sentBytes += self.exchangeSocket(client, writeSocket: proxySocket, secret: pl)
299 | })
300 |
301 | dispatch_async(queue, { () -> Void in
302 | self.receivedBytes += self.exchangeSocket(proxySocket, writeSocket: client, secret: paddingSize)
303 | })
304 | }
305 |
306 | }
307 |
308 | extension Socks5Server: Equatable {
309 |
310 | }
311 |
312 | func ==(lhs: Socks5Server, rhs: Socks5Server) -> Bool {
313 | return lhs.serverAddr == rhs.serverAddr && lhs.serverPort == rhs.serverPort && lhs.listenAddr == rhs.listenAddr && lhs.listenPort == rhs.listenPort && lhs.cipherAlgorithm == rhs.cipherAlgorithm && lhs.password == rhs.password
314 | }
--------------------------------------------------------------------------------
/LightSwordX/TCPSocket.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TCPSocket.swift
3 | // LightSwordX
4 | //
5 | // Created by Neko on 1/9/16.
6 | // Copyright © 2016 Neko. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | @asmname("tcpsocket_connect") func c_tcpsocket_connect(host:UnsafePointer, port:Int32, timeout:Int32) -> Int32
12 | @asmname("tcpsocket_close") func c_tcpsocket_close(fd:Int32) -> Int32
13 | @asmname("tcpsocket_send") func c_tcpsocket_send(fd:Int32, buff:UnsafePointer, len:Int32) -> Int32
14 | @asmname("tcpsocket_read") func c_tcpsocket_read(fd:Int32, buff:UnsafePointer, len:Int32) -> Int32
15 | @asmname("tcpsocket_listen") func c_tcpsocket_listen(addr:UnsafePointer, port:Int32) -> Int32
16 | @asmname("tcpsocket_accept") func c_tcpsocket_accept(socketfd:Int32, ip:UnsafePointer, port:UnsafePointer) -> Int32
17 | @asmname("tcpsocket6_listen") func c_tcpsocket6_listen(addr: UnsafePointer, port: Int32) -> Int32
18 | @asmname("set_socket_timeout") func c_set_socket_timeout(socketfd: Int32, timeout: Int) -> Void
19 |
20 | class TCPClient6: Socket {
21 | func connect(timeout t: Int) -> (Bool, String) {
22 | let r = c_tcpsocket_connect(self.addr, port: Int32(self.port), timeout: Int32(t))
23 |
24 | if r > 0 {
25 | self.fd = r
26 | return (true, "connceted")
27 | } else {
28 | switch r {
29 | case -1:
30 | return (false, "failed to query server")
31 | case -2:
32 | return (false,"connection closed")
33 | case -3:
34 | return (false,"connect timeout")
35 | default:
36 | return (false, "unknow err")
37 | }
38 | }
39 | }
40 |
41 | func close() -> (Bool, String) {
42 | guard let fd = self.fd else {
43 | return (false, "socket not open")
44 | }
45 |
46 | c_tcpsocket_close(fd)
47 | self.fd = nil
48 | return (true, "closed")
49 | }
50 |
51 | func send(data d: [UInt8]) -> (Bool, String) {
52 | guard let fd = self.fd else {
53 | return (false, "socket not open")
54 | }
55 |
56 | let sent = c_tcpsocket_send(fd, buff: d, len: Int32(d.count))
57 | if Int(sent) == d.count {
58 | return (true, "succcess")
59 | } else {
60 | return (false, "error")
61 | }
62 | }
63 |
64 | func send(str s: String) -> (Bool, String) {
65 | guard let fd = self.fd else {
66 | return (false, "socket not open")
67 | }
68 |
69 | let sent = c_tcpsocket_send(fd, buff: s, len: Int32(strlen(s)))
70 | if sent == Int32(strlen(s)) {
71 | return (true, "success")
72 | }
73 |
74 | return (false, "error")
75 | }
76 |
77 | func send(data d: NSData) -> (Bool, String) {
78 | guard let fd = self.fd else {
79 | return (false, "socket not open")
80 | }
81 |
82 | var buf = [UInt8](count: d.length, repeatedValue: 0)
83 | d.getBytes(&buf, length: d.length)
84 |
85 | let sent = c_tcpsocket_send(fd, buff: buf, len: Int32(d.length))
86 | if sent == Int32(d.length) {
87 | return (true, "success")
88 | }
89 |
90 | return (false, "error")
91 | }
92 |
93 | func read(exceptLength: Int) -> (data: [UInt8]?, errno: Int32) {
94 | guard let fd = self.fd else {
95 | return (data: nil, errno: -1)
96 | }
97 |
98 | var buf = [UInt8](count: exceptLength, repeatedValue: 0)
99 | let read = c_tcpsocket_read(fd, buff: buf, len: Int32(exceptLength))
100 | if read <= 0 {
101 | return (data: nil, errno: 0)
102 | }
103 |
104 | return (data: Array(buf[0...Int(read - 1)]), errno: read)
105 | }
106 |
107 | var timeout: Int {
108 | get {
109 | return _timeout
110 | }
111 | set {
112 | guard let fd = self.fd else {
113 | return
114 | }
115 |
116 | c_set_socket_timeout(fd, timeout: newValue)
117 | _timeout = newValue
118 | }
119 | }
120 | }
121 |
122 | class TCPServer6: Socket {
123 |
124 | func listen() -> (Bool, String) {
125 |
126 | if self.fd != nil {
127 | return (false, "listening ready")
128 | }
129 |
130 | let fd = c_tcpsocket6_listen(self.addr, port: Int32(self.port))
131 | if fd > 0 {
132 | self.fd = fd;
133 | return (true, "listening")
134 | }
135 |
136 | return (false, "Failed to listen")
137 | }
138 |
139 | func accept() -> TCPClient6? {
140 | guard let fd = self.fd else {
141 | return nil
142 | }
143 |
144 | var buf = [Int8](count: 16, repeatedValue: 0)
145 | var port: Int32 = 0
146 | let clientfd = c_tcpsocket_accept(fd, ip: &buf, port: &port)
147 | if clientfd < 0 {
148 | return nil
149 | }
150 |
151 | let client = TCPClient6()
152 | client.fd = clientfd
153 | client.port = Int(port)
154 | if let addr = String(CString: buf, encoding: NSUTF8StringEncoding) {
155 | client.addr = addr
156 | }
157 |
158 | return client
159 | }
160 |
161 | func close() -> (Bool, String) {
162 |
163 | guard let fd = self.fd else {
164 | return (false, "socket not open")
165 | }
166 |
167 | c_tcpsocket_close(fd)
168 | self.fd = nil
169 | return (true, "closed")
170 | }
171 |
172 | }
--------------------------------------------------------------------------------
/LightSwordX/ViewController.Servers.swift:
--------------------------------------------------------------------------------
1 | //
2 | // UserServersDataSource.swift
3 | // LightSwordX
4 | //
5 | // Created by Neko on 12/23/15.
6 | // Copyright © 2015 Neko. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 | import SINQ
11 |
12 | extension ViewController: NSTableViewDataSource {
13 |
14 | @objc func numberOfRowsInTableView(tableView: NSTableView) -> Int {
15 | return servers.count
16 | }
17 |
18 | @objc func tableView(tableView: NSTableView, objectValueForTableColumn tableColumn: NSTableColumn?, row: Int) -> AnyObject? {
19 | return servers[row].address
20 | }
21 |
22 | @IBAction func addServer(sender: NSButton) {
23 | let server = UserServer()
24 | server.id = servers.count
25 |
26 | if servers.count == 0 {
27 | server.address = "public1.lightsword.org"
28 | server.port = 443
29 | }
30 |
31 | servers.append(server)
32 | serversTableView.reloadData()
33 |
34 | selectedRow = servers.count - 1
35 | let indexSet = NSIndexSet(index: selectedRow)
36 | serversTableView.selectRowIndexes(indexSet, byExtendingSelection: false)
37 |
38 | serverDetailsView.hidden = false
39 | keepConnectionCheckBox.state = server.keepConnection ? NSOnState : NSOffState
40 | serverAddressTextField.stringValue = server.address
41 | serverPortTextField.stringValue = String(server.port)
42 | cipherAlgorithmComboBox.stringValue = server.cipherAlgorithm
43 | proxyModeComboBox.selectItemAtIndex(server.proxyMode.rawValue)
44 | passwordTextField.stringValue = server.password
45 | listenAddressTextField.stringValue = server.listenAddr
46 | listenPortTextField.stringValue = String(server.listenPort)
47 |
48 | saveServers(true)
49 |
50 | if (server.keepConnection) {
51 | startServer(server)
52 | }
53 | }
54 |
55 | @IBAction func removeServer(sender: NSButton) {
56 | let selectedRow = serversTableView.selectedRow
57 | if (selectedRow == -1) {
58 | return
59 | }
60 |
61 | let removed = servers.removeAtIndex(selectedRow)
62 | serversTableView.reloadData()
63 |
64 | if (servers.count == 0) {
65 | serverDetailsView.hidden = true
66 | }
67 |
68 | saveServers(true)
69 | stopServer(removed)
70 | }
71 |
72 | @IBAction func setAsDefaultServer(sender: NSButton) {
73 | let selectedServer = servers[selectedRow]
74 |
75 | selectedServer.keepConnection = !selectedServer.keepConnection
76 | saveServers(true)
77 |
78 | if selectedServer.keepConnection {
79 | startServer(selectedServer)
80 | return
81 | }
82 |
83 | stopServer(selectedServer)
84 | }
85 |
86 | @IBAction func testConnectionSpeed(sender: NSButton) {
87 | let ip = servers[selectedRow].address
88 | let port = servers[selectedRow].port
89 |
90 | sender.enabled = false
91 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
92 | let start = StatisticsHelper.getUptimeInMilliseconds()
93 |
94 | let con = TCPClient(addr: ip, port: port)
95 | let (success, _) = con.connect(timeout: 10)
96 | con.close()
97 |
98 | let message = success ? "\(NSLocalizedString("Elapsed Time", comment: "")): \(StatisticsHelper.getUptimeInMilliseconds() - start)ms\n\(ip) ✓" : NSLocalizedString("Connection Timeout", comment: "")
99 |
100 | let notification = NSUserNotification()
101 | notification.title = NSLocalizedString("Test Connection Speed", comment: "")
102 | notification.informativeText = message
103 |
104 | NSUserNotificationCenter.defaultUserNotificationCenter().deliverNotification(notification)
105 |
106 | dispatch_async(dispatch_get_main_queue()) {
107 | sender.enabled = true
108 | }
109 | }
110 | }
111 | }
112 |
113 | extension ViewController: NSTableViewDelegate {
114 | func tableView(tableView: NSTableView, shouldSelectRow row: Int) -> Bool {
115 |
116 | let info = servers[row]
117 | selectedRow = row
118 |
119 | serverAddressTextField.stringValue = info.address
120 | serverPortTextField.stringValue = String(info.port)
121 | cipherAlgorithmComboBox.stringValue = info.cipherAlgorithm
122 | proxyModeComboBox.selectItemAtIndex(info.proxyMode.rawValue)
123 | passwordTextField.stringValue = info.password
124 | keepConnectionCheckBox.state = info.keepConnection ? NSOnState : NSOffState
125 | listenAddressTextField.stringValue = info.listenAddr
126 | listenPortTextField.stringValue = String(info.listenPort)
127 |
128 | saveServers()
129 | return true
130 | }
131 | }
132 |
133 | extension ViewController: NSComboBoxDelegate {
134 |
135 | override func controlTextDidChange(obj: NSNotification) {
136 | let textField: NSTextField! = obj.object as? NSTextField
137 | if textField == nil {
138 | return
139 | }
140 |
141 | var newValue = textField.stringValue
142 | let selectedServer = servers[selectedRow]
143 |
144 | switch textField.identifier! {
145 |
146 | case "serverAddress":
147 | if (newValue.length == 0) {
148 | newValue = "127.0.0.1"
149 | }
150 |
151 | selectedServer.address = newValue
152 | serversTableView.reloadData()
153 | break
154 |
155 | case "serverPort":
156 | let port = Int(newValue) ?? 8900
157 | selectedServer.port = port
158 | serverPortTextField.stringValue = String(port)
159 | break
160 |
161 | case "password":
162 | if (newValue.length == 0) {
163 | newValue = "lightsword.neko"
164 | }
165 |
166 | selectedServer.password = newValue
167 | break
168 |
169 | case "listenAddr":
170 | if (newValue.length == 0) {
171 | newValue = "127.0.0.1"
172 | } else if (newValue == "localhost") {
173 | newValue = "127.0.0.1"
174 | }
175 |
176 | if ipv4Regex.test(newValue) && !["127.0.0.1", "0.0.0.0"].contains(newValue) {
177 | newValue = "127.0.0.1"
178 | }
179 |
180 | selectedServer.listenAddr = newValue
181 | listenAddressTextField.stringValue = newValue
182 | break
183 |
184 | case "listenPort":
185 | let port = Int(newValue) ?? 1080
186 | selectedServer.listenPort = port
187 | listenPortTextField.stringValue = String(port)
188 | break
189 |
190 | default:
191 | return
192 | }
193 |
194 | isDirty = true
195 | }
196 |
197 | override func controlTextDidEndEditing(obj: NSNotification) {
198 | saveServers()
199 | }
200 |
201 | func comboBoxSelectionDidChange(notification: NSNotification) {
202 | let comboBox = notification.object as! NSComboBox
203 | let handlers = [
204 | "cipherAlgorithm": cipherAlgorithmComboBoxChanged,
205 | "proxyMode": proxyModeComboBoxChanged
206 | ]
207 |
208 | handlers[comboBox.identifier!]?(comboBox)
209 | }
210 |
211 | private func cipherAlgorithmComboBoxChanged(comboBox: NSComboBox) {
212 | let methods = ["aes-256-cfb", "aes-192-cfb", "aes-128-cfb"]
213 | let selectedIndex = comboBox.indexOfSelectedItem
214 | if (servers[selectedRow].cipherAlgorithm == methods[selectedIndex]) {
215 | return
216 | }
217 |
218 | servers[selectedRow].cipherAlgorithm = methods[selectedIndex]
219 | isDirty = true
220 | }
221 |
222 | private func proxyModeComboBoxChanged(comboBox: NSComboBox) {
223 | let modes = [
224 | ProxyMode.GLOBAL.rawValue: ProxyMode.GLOBAL,
225 | ProxyMode.BLACK.rawValue: ProxyMode.BLACK,
226 | ProxyMode.WHITE.rawValue: ProxyMode.WHITE
227 | ]
228 |
229 | let selectedIndex = comboBox.indexOfSelectedItem
230 | if let selectedMode = modes[selectedIndex] {
231 | if (servers[selectedRow].proxyMode == selectedMode) {
232 | return
233 | }
234 |
235 | servers[selectedRow].proxyMode = selectedMode
236 | if let running = sinq(self.runningServers).firstOrNil({ s in s.tag as? Int == self.servers[self.selectedRow].id }) {
237 | running.proxyMode = selectedMode
238 | }
239 | isDirty = true
240 | }
241 | }
242 | }
243 |
--------------------------------------------------------------------------------
/LightSwordX/ViewController.Settings.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.Settings.swift
3 | // LightSwordX
4 | //
5 | // Created by Neko on 12/29/15.
6 | // Copyright © 2015 Neko. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 | import ServiceManagement
11 |
12 | extension ViewController {
13 | @IBAction func toggleLoginItem(sender: NSButton) {
14 | let on = sender.state == NSOnState
15 | let launcherIdentifier = "org.lightsword.LightSwordXHelper"
16 |
17 | SMLoginItemSetEnabled(launcherIdentifier, on)
18 | SettingsHelper.saveValue(on, forKey: AppKeys.LoginItem)
19 | }
20 | }
--------------------------------------------------------------------------------
/LightSwordX/ViewController.Websites.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.Websites.swift
3 | // LightSwordX
4 | //
5 | // Created by Neko on 12/25/15.
6 | // Copyright © 2015 Neko. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 |
11 | extension ViewController: NSTextDelegate {
12 | func textDidChange(notification: NSNotification) {
13 | isWebsitesDirty = true
14 | }
15 | }
--------------------------------------------------------------------------------
/LightSwordX/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // LightSwordX
4 | //
5 | // Created by Neko on 12/17/15.
6 | // Copyright © 2015 Neko. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 | import SINQ
11 |
12 | class ViewController: NSViewController {
13 |
14 | override func viewDidLoad() {
15 | super.viewDidLoad()
16 |
17 | serverDetailsView.hidden = servers.count == 0 ? true : false
18 |
19 | let login = SettingsHelper.loadValue(defaultValue: false, forKey: AppKeys.LoginItem)
20 | loginItemCheckBox.state = login ? NSOnState : NSOffState
21 | }
22 |
23 | override func awakeFromNib() {
24 |
25 | if self.blackList == nil {
26 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {
27 | self.initBlackWhiteList()
28 | }
29 | }
30 |
31 | if (servers != nil && servers.count > 0) {
32 | return
33 | }
34 |
35 | let jsonStr = SettingsHelper.loadValue(defaultValue: "", forKey: AppKeys.Servers)
36 |
37 | if (jsonStr.length == 0) {
38 | self.servers = [UserServer]()
39 | return
40 | }
41 |
42 | let jObjs = JSON(string: jsonStr)
43 | var index = 0
44 | self.servers = jObjs.map{ obj, jObj in
45 | let server = UserServer()
46 |
47 | server.address = jObj["address"].asString!
48 | server.port = jObj["port"].asInt!
49 | server.cipherAlgorithm = jObj["cipherAlgorithm"].asString!
50 | server.password = jObj["password"].asString!
51 | server.keepConnection = jObj["keepConnection"].asBool!
52 | server.listenAddr = jObj["listenAddr"].asString!
53 | server.listenPort = jObj["listenPort"].asInt!
54 | server.proxyMode = ProxyMode(rawValue: jObj["proxyMode"].asInt ?? 0)!
55 | server.id = index++
56 |
57 | return server
58 | }
59 |
60 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
61 | self.servers.filter({ s in return s.keepConnection }).forEach { s in
62 | self.startServer(s)
63 | }
64 | }
65 | }
66 |
67 | func initBlackWhiteList() {
68 | let mainBundle = NSBundle.mainBundle()
69 | let whiteList = SettingsHelper.loadValue(defaultValue: try! NSString(contentsOfFile: mainBundle.pathForResource("white", ofType: "txt")!, encoding: NSUTF8StringEncoding), forKey: AppKeys.WhiteList)
70 | let blackList = SettingsHelper.loadValue(defaultValue: try! NSString(contentsOfFile: mainBundle.pathForResource("black", ofType: "txt")!, encoding: NSUTF8StringEncoding), forKey: AppKeys.BlackList)
71 |
72 | self.whiteList = whiteList.componentsSeparatedByString("\n")
73 | self.blackList = blackList.componentsSeparatedByString("\n")
74 | }
75 |
76 | @IBAction func onCloseClick(sender: NSButton) {
77 | view.window?.close()
78 | saveServers()
79 | saveWebsites()
80 | stopTimer()
81 | }
82 |
83 | var blackList: [String]!
84 | var whiteList: [String]!
85 |
86 | var servers: [UserServer]!
87 | var runningServers = [Socks5Server]()
88 | var selectedRow: Int!
89 | var isDirty = false
90 | var isWebsitesDirty = false
91 | var statisticsTimer: NSTimer!
92 | var totalSentBytes: UInt64 = 0
93 | var totalReceivedBytes: UInt64 = 0
94 |
95 | let ipv4Regex = Regex("^(?:[0-9]{1,3}\\.){3}[0-9]{1,3}$")
96 |
97 | @IBOutlet weak var serversTableView: NSTableView!
98 | @IBOutlet weak var serverDetailsView: NSView!
99 | @IBOutlet weak var serverAddressTextField: NSTextField!
100 | @IBOutlet weak var serverPortTextField: NSTextField!
101 | @IBOutlet weak var listenAddressTextField: NSTextField!
102 | @IBOutlet weak var listenPortTextField: NSTextField!
103 | @IBOutlet weak var cipherAlgorithmComboBox: NSComboBox!
104 | @IBOutlet weak var passwordTextField: NSSecureTextField!
105 | @IBOutlet weak var keepConnectionCheckBox: NSButton!
106 | @IBOutlet weak var proxyModeComboBox: NSComboBox!
107 | @IBOutlet weak var connectionStatus: NSTextField!
108 | var blackListTextView: NSTextView!
109 | var whiteListTextView: NSTextView!
110 | @IBOutlet weak var sentBytesTextField: NSTextField!
111 | @IBOutlet weak var receivedBytesTextField: NSTextField!
112 | @IBOutlet weak var uploadSpeedTextField: NSTextField!
113 | @IBOutlet weak var downloadSpeedTextField: NSTextField!
114 | @IBOutlet weak var loginItemCheckBox: NSButton!
115 |
116 | func startServer(userServer: UserServer) {
117 | let server = Socks5Server()
118 | server.listenAddr = userServer.listenAddr
119 | server.listenPort = userServer.listenPort
120 | server.serverAddr = userServer.address
121 | server.serverPort = userServer.port
122 | server.bypassLocal = true
123 | server.cipherAlgorithm = userServer.cipherAlgorithm
124 | server.password = userServer.password
125 | server.timeout = 30
126 | server.tag = userServer.id
127 | server.proxyMode = userServer.proxyMode
128 | server.blackList = self.blackList
129 | server.whiteList = self.whiteList
130 |
131 | server.startAsync({ s in
132 | if (!s) {
133 | let notification = NSUserNotification()
134 | notification.title = NSLocalizedString("Start Failed", comment: "")
135 | notification.informativeText = NSString(format: NSLocalizedString("Port is used", comment: "Port: %d is used"), server.listenPort) as String
136 |
137 | NSUserNotificationCenter.defaultUserNotificationCenter().deliverNotification(notification)
138 | return
139 | }
140 |
141 | dispatch_async(dispatch_get_main_queue()) {
142 | self.runningServers.append(server)
143 | self.updateStatusText(self.runningServers.count)
144 | }
145 | })
146 | }
147 |
148 | func stopServer(userServer: UserServer) {
149 | if let s = sinq(runningServers).firstOrNil({ s in s.tag as! Int == userServer.id }) {
150 | s.stop()
151 | runningServers.removeAtIndex(runningServers.indexOf({ ss in ss == s })!)
152 | updateStatusText(runningServers.count)
153 | }
154 | }
155 |
156 | func refreshStatistics() {
157 | if self.runningServers.count == 0 {
158 | return
159 | }
160 |
161 | var curSent = self.runningServers.reduce(0, combine: { n, s in n + s.sentBytes })
162 | var curReceived = self.runningServers.reduce(0, combine: { n, s in n + s.receivedBytes })
163 |
164 | if curSent < totalSentBytes {
165 | curSent = totalSentBytes
166 | }
167 |
168 | if curReceived < totalReceivedBytes {
169 | curReceived = totalReceivedBytes
170 | }
171 |
172 | let deltaSent = curSent - totalSentBytes
173 | let deltaReceived = curReceived - totalReceivedBytes
174 |
175 | totalSentBytes = curSent
176 | totalReceivedBytes = curReceived
177 |
178 | let (value: _, formattedValue: sent, unit: sentUnit) = StatisticsHelper.toStatisticsString(curSent)
179 | sentBytesTextField.stringValue = "\(sent) \(sentUnit)"
180 |
181 | let (value: _, formattedValue: received, unit: receivedUnit) = StatisticsHelper.toStatisticsString(curReceived)
182 | receivedBytesTextField.stringValue = "\(received) \(receivedUnit)"
183 |
184 | let (value: _, formattedValue: sentSpeed, unit: sentSpeedUnit) = StatisticsHelper.toStatisticsString(deltaSent)
185 | uploadSpeedTextField.stringValue = "\(sentSpeed) \(sentSpeedUnit)/s ↑"
186 |
187 | let (value: _, formattedValue: receivedSpeed, unit: receivedSpeedUnit) = StatisticsHelper.toStatisticsString(deltaReceived)
188 | downloadSpeedTextField.stringValue = "\(receivedSpeed) \(receivedSpeedUnit)/s ↓"
189 | }
190 |
191 | func saveServers(force: Bool = false) {
192 | if !force && !isDirty {
193 | return
194 | }
195 |
196 | isDirty = false
197 | let list = servers.map{ s in return [
198 | "address": s.address,
199 | "port": s.port,
200 | "cipherAlgorithm": s.cipherAlgorithm,
201 | "password": s.password,
202 | "keepConnection": s.keepConnection,
203 | "listenAddr": s.listenAddr,
204 | "listenPort": s.listenPort,
205 | "proxyMode": s.proxyMode.rawValue
206 | ]}
207 |
208 | SettingsHelper.saveValue(JSON(list).toString(), forKey: AppKeys.Servers)
209 | }
210 |
211 | func saveWebsites() {
212 | if !isWebsitesDirty {
213 | return
214 | }
215 |
216 | SettingsHelper.saveValue(blackListTextView.string!, forKey: AppKeys.BlackList)
217 | SettingsHelper.saveValue(whiteListTextView.string!, forKey: AppKeys.WhiteList)
218 | self.blackList = blackListTextView.string!.componentsSeparatedByString("\n")
219 | self.whiteList = whiteListTextView.string!.componentsSeparatedByString("\n")
220 |
221 | for s in self.runningServers {
222 | s.blackList = self.blackList
223 | s.whiteList = self.whiteList
224 | }
225 |
226 | isWebsitesDirty = false
227 | }
228 |
229 | func updateStatusText(runningCount: Int) {
230 | dispatch_async(dispatch_get_main_queue()) {
231 | let color = runningCount == 0 ? NSColor.grayColor() : NSColor(red: 51.0 / 255, green: 204.0 / 255, blue: 51 / 255, alpha: 1)
232 | let text = runningCount == 0 ? NSLocalizedString("Stopped", comment: "") : "\(NSLocalizedString("Running", comment: "")): \(runningCount)"
233 |
234 | self.connectionStatus.textColor = color
235 | self.connectionStatus.stringValue = "◉ \(text)"
236 | }
237 | }
238 |
239 | func stopTimer() {
240 | if statisticsTimer == nil {
241 | return
242 | }
243 |
244 | statisticsTimer.invalidate()
245 | statisticsTimer = nil
246 | }
247 | }
248 |
249 | extension ViewController: NSTabViewDelegate {
250 | func tabView(tabView: NSTabView, didSelectTabViewItem tabViewItem: NSTabViewItem?) {
251 | let identifier = tabViewItem?.identifier as? String
252 | if identifier == nil {
253 | return
254 | }
255 |
256 | stopTimer()
257 | saveWebsites()
258 |
259 | if identifier! == "Websites" {
260 | if blackListTextView == nil {
261 | blackListTextView = sinq(tabViewItem!.view!.subviews).first{ v in v.identifier == "BlackListScrollView" }.subviews.first!.subviews.first as! NSTextView
262 | whiteListTextView = sinq(tabViewItem!.view!.subviews).first{ v in v.identifier == "WhiteListScrollView" }.subviews.first!.subviews.first as! NSTextView
263 | }
264 |
265 | let blackList = SettingsHelper.loadValue(defaultValue: try! NSString(contentsOfFile: NSBundle.mainBundle().pathForResource("black", ofType: "txt")!, encoding: NSUTF8StringEncoding) as String, forKey: AppKeys.BlackList)
266 | let whiteList = SettingsHelper.loadValue(defaultValue: try! NSString(contentsOfFile: NSBundle.mainBundle().pathForResource("white", ofType: "txt")!, encoding: NSUTF8StringEncoding) as String, forKey: AppKeys.WhiteList)
267 | blackListTextView.string = blackList
268 | whiteListTextView.string = whiteList
269 |
270 | return
271 | }
272 |
273 | if identifier! == "Statistics" {
274 | if self.statisticsTimer == nil {
275 | self.statisticsTimer = NSTimer(timeInterval: 1, target: self, selector: Selector("refreshStatistics"), userInfo: nil, repeats: true)
276 | NSRunLoop.mainRunLoop().addTimer(self.statisticsTimer, forMode: NSRunLoopCommonModes)
277 | refreshStatistics()
278 | }
279 |
280 | return
281 | }
282 |
283 | }
284 | }
285 |
--------------------------------------------------------------------------------
/LightSwordX/zh-Hans.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 | // Connection Test
2 |
3 | "Test Connection Speed" = "测试连接速度";
4 | "Elapsed Time" = "总耗时";
5 | "Connection Timeout" = "连接超时";
6 |
7 | // Menu Bar
8 |
9 | "Preferences" = "偏好设置";
10 | "Quit" = "退出";
11 |
12 | // Status
13 |
14 | "Stopped" = "已停止";
15 | "Running" = "运行中";
16 |
17 | // Local Server
18 |
19 | "Start Failed" = "本地服务器启动失败";
20 | "Port is used" = "端口号: %d 已被使用或拒绝访问,请更换其它端口号";
--------------------------------------------------------------------------------
/LightSwordX/zh-Hans.lproj/Main.strings:
--------------------------------------------------------------------------------
1 |
2 | /* Class = "NSMenuItem"; title = "LightSwordX"; ObjectID = "1Xt-HY-uBw"; */
3 | "1Xt-HY-uBw.title" = "LightSwordX";
4 |
5 | /* Class = "NSTextFieldCell"; placeholderString = "IPv4/Domain"; ObjectID = "1dW-tW-y1K"; */
6 | "1dW-tW-y1K.placeholderString" = "IPv4/Domain";
7 |
8 | /* Class = "NSTextFieldCell"; title = "Cipher Algorithm:"; ObjectID = "2EF-Gk-wm0"; */
9 | "2EF-Gk-wm0.title" = "加密方式 (OS X客户端仅在握手时使用): ";
10 |
11 | /* Class = "NSTextFieldCell"; title = "0 KB"; ObjectID = "40K-aO-fio"; */
12 | "40K-aO-fio.title" = "0 KB";
13 |
14 | /* Class = "NSTextFieldCell"; title = "Blocked Sites List:"; ObjectID = "4ox-Ns-yq2"; */
15 | "4ox-Ns-yq2.title" = "被屏蔽网址:";
16 |
17 | /* Class = "NSMenuItem"; title = "Quit LightSwordX"; ObjectID = "4sb-4s-VLi"; */
18 | "4sb-4s-VLi.title" = "退出 LightSwordX";
19 |
20 | /* Class = "NSTabViewItem"; label = "Statistics"; ObjectID = "50s-kU-6kF"; */
21 | "50s-kU-6kF.label" = "统计";
22 |
23 | /* Class = "NSMenuItem"; title = "Edit"; ObjectID = "5QF-Oa-p0T"; */
24 | "5QF-Oa-p0T.title" = "编辑";
25 |
26 | /* Class = "NSMenuItem"; title = "About LightSwordX"; ObjectID = "5kV-Vb-QxS"; */
27 | "5kV-Vb-QxS.title" = "关于 LightSwordX";
28 |
29 | /* Class = "NSTextFieldCell"; title = "Proxy Mode:"; ObjectID = "8WL-FF-sEa"; */
30 | "8WL-FF-sEa.title" = "代理模式:";
31 |
32 | /* Class = "NSButtonCell"; title = "Start LigthSwordX on system startup"; ObjectID = "8d1-XH-mmP"; */
33 | "8d1-XH-mmP.title" = "开机启动 LightSwordX";
34 |
35 | /* Class = "NSWindow"; title = "LightSwordX"; ObjectID = "8fW-kc-wPs"; */
36 | "8fW-kc-wPs.title" = "LightSwordX";
37 |
38 | /* Class = "NSTextFieldCell"; title = "0 KB/s ↑"; ObjectID = "9mK-b0-W6S"; */
39 | "9mK-b0-W6S.title" = "0 KB/s ↑";
40 |
41 | /* Class = "NSTextFieldCell"; title = "Remote Server:"; ObjectID = "9zW-eR-W7U"; */
42 | "9zW-eR-W7U.title" = "服务器地址:";
43 |
44 | /* Class = "NSTabViewItem"; label = "Servers"; ObjectID = "A5f-Uf-vFi"; */
45 | "A5f-Uf-vFi.label" = "服务器";
46 |
47 | /* Class = "NSMenu"; title = "Main Menu"; ObjectID = "AYu-sK-qS6"; */
48 | "AYu-sK-qS6.title" = "主菜单";
49 |
50 | /* Class = "NSViewController"; title = "LightSwordX"; ObjectID = "B3C-Ed-y2d"; */
51 | "B3C-Ed-y2d.title" = "LightSwordX";
52 |
53 | /* Class = "NSMenuItem"; title = "Preferences…"; ObjectID = "BOF-NM-1cW"; */
54 | "BOF-NM-1cW.title" = "偏好…";
55 |
56 | /* Class = "NSComboBoxCell"; title = "Global"; ObjectID = "C4f-hN-IR5"; */
57 | "C4f-hN-IR5.title" = "全局";
58 |
59 | /* Class = "NSComboBoxCell"; C4f-hN-IR5.ibShadowedObjectValues[0] = "Global"; ObjectID = "C4f-hN-IR5"; */
60 | "C4f-hN-IR5.ibShadowedObjectValues[0]" = "全局代理";
61 |
62 | /* Class = "NSComboBoxCell"; C4f-hN-IR5.ibShadowedObjectValues[1] = "Blacklist only"; ObjectID = "C4f-hN-IR5"; */
63 | "C4f-hN-IR5.ibShadowedObjectValues[1]" = "仅黑名单(仅被封网址)";
64 |
65 | /* Class = "NSComboBoxCell"; C4f-hN-IR5.ibShadowedObjectValues[2] = "Global except whitelist"; ObjectID = "C4f-hN-IR5"; */
66 | "C4f-hN-IR5.ibShadowedObjectValues[2]" = "全局代理(白名单除外)";
67 |
68 | /* Class = "NSTextFieldCell"; placeholderString = "8900"; ObjectID = "DgL-yC-gyI"; */
69 | "DgL-yC-gyI.placeholderString" = "8900";
70 |
71 | /* Class = "NSTextFieldCell"; title = "◉ Stopped"; ObjectID = "Dlh-tC-hWx"; */
72 | "Dlh-tC-hWx.title" = "◉ 未启动";
73 |
74 | /* Class = "NSTabViewItem"; label = "Websites"; ObjectID = "EcX-pW-W6U"; */
75 | "EcX-pW-W6U.label" = "网址列表";
76 |
77 | /* Class = "NSTextFieldCell"; title = ":"; ObjectID = "FLy-ws-6rO"; */
78 | "FLy-ws-6rO.title" = ":";
79 |
80 | /* Class = "NSMenuItem"; title = "View"; ObjectID = "H8h-7b-M4v"; */
81 | "H8h-7b-M4v.title" = "查看";
82 |
83 | /* Class = "NSMenuItem"; title = "Show All"; ObjectID = "Kd2-mp-pUS"; */
84 | "Kd2-mp-pUS.title" = "显示全部";
85 |
86 | /* Class = "NSMenuItem"; title = "Services"; ObjectID = "NMo-om-nkz"; */
87 | "NMo-om-nkz.title" = "服务";
88 |
89 | /* Class = "NSMenuItem"; title = "Hide LightSwordX"; ObjectID = "Olw-nP-bQN"; */
90 | "Olw-nP-bQN.title" = "隐藏 LightSwordX";
91 |
92 | /* Class = "NSTextFieldCell"; title = "Listening:"; ObjectID = "OwG-wI-lyB"; */
93 | "OwG-wI-lyB.title" = "本地监听地址:";
94 |
95 | /* Class = "NSTextFieldCell"; title = ":"; ObjectID = "RLb-g5-Plg"; */
96 | "RLb-g5-Plg.title" = ":";
97 |
98 | /* Class = "NSTableColumn"; headerCell.title = "Address"; ObjectID = "Se1-fH-6G4"; */
99 | "Se1-fH-6G4.headerCell.title" = "地址";
100 |
101 | /* Class = "NSTextFieldCell"; title = "Tips:
102 | 1. Open System Preferences
103 | 2. Select Network
104 | 3. Click Advanced -> Proxies
105 | 4. Select SOCKS Proxy
106 | 5. Fill in Proxy Server Address (eg. 127.0.0.1 1080, NOTE: No Password Required.)
107 |
108 | "; ObjectID = "Te6-Td-saK"; */
109 | "Te6-Td-saK.title" = "提示:
110 | 1. 打开系统偏好
111 | 2. 选择 “网络”
112 | 3. 点击 “高级...” -> “代理”
113 | 4. 勾选 “SOCKS 代理”
114 | 5. 填写代理服务器地址 (例如: 127.0.0.1 1080, 注意: 无需填写密码)
115 |
116 | ";
117 |
118 | /* Class = "NSMenuItem"; title = "Hide Others"; ObjectID = "Vdr-fp-XzO"; */
119 | "Vdr-fp-XzO.title" = "隐藏其它";
120 |
121 | /* Class = "NSComboBoxCell"; placeholderString = "Required"; ObjectID = "YEI-dA-kwa"; */
122 | "YEI-dA-kwa.placeholderString" = "必填";
123 |
124 | /* Class = "NSComboBoxCell"; YEI-dA-kwa.ibShadowedObjectValues[0] = "aes-256-cfb"; ObjectID = "YEI-dA-kwa"; */
125 | "YEI-dA-kwa.ibShadowedObjectValues[0]" = "aes-256-cfb";
126 |
127 | /* Class = "NSComboBoxCell"; YEI-dA-kwa.ibShadowedObjectValues[1] = "aes-192-cfb"; ObjectID = "YEI-dA-kwa"; */
128 | "YEI-dA-kwa.ibShadowedObjectValues[1]" = "aes-192-cfb";
129 |
130 | /* Class = "NSComboBoxCell"; YEI-dA-kwa.ibShadowedObjectValues[2] = "aes-128-cfb"; ObjectID = "YEI-dA-kwa"; */
131 | "YEI-dA-kwa.ibShadowedObjectValues[2]" = "aes-128-cfb";
132 |
133 | /* Class = "NSSecureTextFieldCell"; placeholderString = "Required"; ObjectID = "Z5R-gf-Vfe"; */
134 | "Z5R-gf-Vfe.placeholderString" = "必填";
135 |
136 | /* Class = "NSMenuItem"; title = "Window"; ObjectID = "aUF-d1-5bR"; */
137 | "aUF-d1-5bR.title" = "窗口";
138 |
139 | /* Class = "NSTextFieldCell"; title = "Sent:"; ObjectID = "bYm-WL-eY4"; */
140 | "bYm-WL-eY4.title" = "已发送:";
141 |
142 | /* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "ciz-Oo-91w"; */
143 | "ciz-Oo-91w.title" = "Text Cell";
144 |
145 | /* Class = "NSTextFieldCell"; title = "Received:"; ObjectID = "d6A-Ze-fIH"; */
146 | "d6A-Ze-fIH.title" = "已接收:";
147 |
148 | /* Class = "NSMenuItem"; title = "File"; ObjectID = "dMs-cI-mzQ"; */
149 | "dMs-cI-mzQ.title" = "文件";
150 |
151 | /* Class = "NSButtonCell"; title = "Test Connection Speed"; ObjectID = "fWM-7s-Kmi"; */
152 | "fWM-7s-Kmi.title" = "测试连接速度";
153 |
154 | /* Class = "NSTabViewItem"; label = "Settings"; ObjectID = "gyd-cc-HxZ"; */
155 | "gyd-cc-HxZ.label" = "设置";
156 |
157 | /* Class = "NSTextFieldCell"; title = "White List:"; ObjectID = "h6R-RQ-s0t"; */
158 | "h6R-RQ-s0t.title" = "白名单:";
159 |
160 | /* Class = "NSTextFieldCell"; placeholderString = "1080"; ObjectID = "hpa-EM-orp"; */
161 | "hpa-EM-orp.placeholderString" = "1080";
162 |
163 | /* Class = "NSMenu"; title = "Services"; ObjectID = "hz9-B4-Xy5"; */
164 | "hz9-B4-Xy5.title" = "服务";
165 |
166 | /* Class = "NSMenuItem"; title = "Format"; ObjectID = "jxT-CU-nIS"; */
167 | "jxT-CU-nIS.title" = "格式";
168 |
169 | /* Class = "NSTextFieldCell"; placeholderString = "Listening Address: 0.0.0.0, 127.0.0.1"; ObjectID = "kKq-2t-fwt"; */
170 | "kKq-2t-fwt.placeholderString" = "监听地址: 0.0.0.0, 127.0.0.1";
171 |
172 | /* Class = "NSTextFieldCell"; title = "0 KB/s ↓"; ObjectID = "kcC-Z5-c4O"; */
173 | "kcC-Z5-c4O.title" = "0 KB/s ↓";
174 |
175 | /* Class = "NSTextFieldCell"; title = "0 KB"; ObjectID = "q8v-Xs-Nzp"; */
176 | "q8v-Xs-Nzp.title" = "0 KB";
177 |
178 | /* Class = "NSButtonCell"; title = "Close"; ObjectID = "qah-Sp-kt3"; */
179 | "qah-Sp-kt3.title" = "关闭";
180 |
181 | /* Class = "NSTextFieldCell"; title = "Servers List:"; ObjectID = "rP6-Tk-LZ4"; */
182 | "rP6-Tk-LZ4.title" = "服务器列表:";
183 |
184 | /* Class = "NSButtonCell"; title = "Keep Connection"; ObjectID = "tZb-9v-MfO"; */
185 | "tZb-9v-MfO.title" = "启用服务器";
186 |
187 | /* Class = "NSMenu"; title = "LightSwordX"; ObjectID = "uQy-DD-JDr"; */
188 | "uQy-DD-JDr.title" = "LightSwordX";
189 |
190 | /* Class = "NSMenuItem"; title = "Help"; ObjectID = "wpr-3q-Mcd"; */
191 | "wpr-3q-Mcd.title" = "帮助";
192 |
193 | /* Class = "NSTextFieldCell"; title = "Source Code: https://github.com/SunshinyNeko/LightSwordX"; ObjectID = "xjN-cc-33o"; */
194 | "xjN-cc-33o.title" = "源码地址: https://github.com/SunshinyNeko/LightSwordX";
195 |
196 | /* Class = "NSTextFieldCell"; title = "Password:"; ObjectID = "xmv-oa-oyN"; */
197 | "xmv-oa-oyN.title" = "密码:";
198 |
--------------------------------------------------------------------------------
/LightSwordXHelper/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // LightSwordXHelper
4 | //
5 | // Created by Neko on 12/28/15.
6 | // Copyright © 2015 Neko. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 |
11 | @NSApplicationMain
12 | class AppDelegate: NSObject, NSApplicationDelegate {
13 |
14 | func applicationDidFinishLaunching(aNotification: NSNotification) {
15 | let isRunning = NSWorkspace.sharedWorkspace().runningApplications.filter({ a in a.bundleIdentifier != nil ? a.bundleIdentifier! == "org.lightsword.LightSwordX" : false ?? false }).count > 0
16 |
17 | if isRunning {
18 | NSApp.terminate(nil)
19 | return
20 | }
21 |
22 | let path = NSBundle.mainBundle().bundlePath as NSString
23 | var components = path.pathComponents
24 | components.removeLast()
25 | components.removeLast()
26 | components.removeLast()
27 | components.append("MacOS")
28 | components.append("LightSwordX")
29 |
30 | NSWorkspace.sharedWorkspace().launchApplication(NSString.pathWithComponents(components))
31 | NSApp.terminate(nil)
32 | }
33 |
34 | func applicationWillTerminate(aNotification: NSNotification) {
35 | // Insert code here to tear down your application
36 | }
37 |
38 |
39 | }
40 |
41 |
--------------------------------------------------------------------------------
/LightSwordXHelper/Assets.xcassets/AppIcon.appiconset/1451660318_game-fighting-sword-shooter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UnsignedInt8/LightSwordX/98eea71721ae22a65446b9d56f45aa2a689f5266/LightSwordXHelper/Assets.xcassets/AppIcon.appiconset/1451660318_game-fighting-sword-shooter.png
--------------------------------------------------------------------------------
/LightSwordXHelper/Assets.xcassets/AppIcon.appiconset/1451660323_game-fighting-sword-shooter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UnsignedInt8/LightSwordX/98eea71721ae22a65446b9d56f45aa2a689f5266/LightSwordXHelper/Assets.xcassets/AppIcon.appiconset/1451660323_game-fighting-sword-shooter.png
--------------------------------------------------------------------------------
/LightSwordXHelper/Assets.xcassets/AppIcon.appiconset/1451660327_game-fighting-sword-shooter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UnsignedInt8/LightSwordX/98eea71721ae22a65446b9d56f45aa2a689f5266/LightSwordXHelper/Assets.xcassets/AppIcon.appiconset/1451660327_game-fighting-sword-shooter.png
--------------------------------------------------------------------------------
/LightSwordXHelper/Assets.xcassets/AppIcon.appiconset/1451660336_game-fighting-sword-shooter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UnsignedInt8/LightSwordX/98eea71721ae22a65446b9d56f45aa2a689f5266/LightSwordXHelper/Assets.xcassets/AppIcon.appiconset/1451660336_game-fighting-sword-shooter.png
--------------------------------------------------------------------------------
/LightSwordXHelper/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "16x16",
5 | "idiom" : "mac",
6 | "filename" : "sword_16.png",
7 | "scale" : "1x"
8 | },
9 | {
10 | "size" : "16x16",
11 | "idiom" : "mac",
12 | "filename" : "icon_16x16@2x.png",
13 | "scale" : "2x"
14 | },
15 | {
16 | "size" : "32x32",
17 | "idiom" : "mac",
18 | "filename" : "1451660336_game-fighting-sword-shooter.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "32x32",
23 | "idiom" : "mac",
24 | "filename" : "icon_32x32@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "128x128",
29 | "idiom" : "mac",
30 | "filename" : "1451660318_game-fighting-sword-shooter.png",
31 | "scale" : "1x"
32 | },
33 | {
34 | "size" : "128x128",
35 | "idiom" : "mac",
36 | "filename" : "icon_128x128@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "256x256",
41 | "idiom" : "mac",
42 | "filename" : "1451660323_game-fighting-sword-shooter.png",
43 | "scale" : "1x"
44 | },
45 | {
46 | "size" : "256x256",
47 | "idiom" : "mac",
48 | "filename" : "icon_256x256@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "512x512",
53 | "idiom" : "mac",
54 | "filename" : "1451660327_game-fighting-sword-shooter.png",
55 | "scale" : "1x"
56 | },
57 | {
58 | "size" : "512x512",
59 | "idiom" : "mac",
60 | "filename" : "icon_512x512@2x.png",
61 | "scale" : "2x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
--------------------------------------------------------------------------------
/LightSwordXHelper/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UnsignedInt8/LightSwordX/98eea71721ae22a65446b9d56f45aa2a689f5266/LightSwordXHelper/Assets.xcassets/AppIcon.appiconset/icon_128x128@2x.png
--------------------------------------------------------------------------------
/LightSwordXHelper/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UnsignedInt8/LightSwordX/98eea71721ae22a65446b9d56f45aa2a689f5266/LightSwordXHelper/Assets.xcassets/AppIcon.appiconset/icon_16x16@2x.png
--------------------------------------------------------------------------------
/LightSwordXHelper/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UnsignedInt8/LightSwordX/98eea71721ae22a65446b9d56f45aa2a689f5266/LightSwordXHelper/Assets.xcassets/AppIcon.appiconset/icon_256x256@2x.png
--------------------------------------------------------------------------------
/LightSwordXHelper/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UnsignedInt8/LightSwordX/98eea71721ae22a65446b9d56f45aa2a689f5266/LightSwordXHelper/Assets.xcassets/AppIcon.appiconset/icon_32x32@2x.png
--------------------------------------------------------------------------------
/LightSwordXHelper/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UnsignedInt8/LightSwordX/98eea71721ae22a65446b9d56f45aa2a689f5266/LightSwordXHelper/Assets.xcassets/AppIcon.appiconset/icon_512x512@2x.png
--------------------------------------------------------------------------------
/LightSwordXHelper/Assets.xcassets/AppIcon.appiconset/sword_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UnsignedInt8/LightSwordX/98eea71721ae22a65446b9d56f45aa2a689f5266/LightSwordXHelper/Assets.xcassets/AppIcon.appiconset/sword_16.png
--------------------------------------------------------------------------------
/LightSwordXHelper/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/LightSwordXHelper/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | LSApplicationCategoryType
26 | public.app-category.utilities
27 | LSBackgroundOnly
28 |
29 | LSMinimumSystemVersion
30 | $(MACOSX_DEPLOYMENT_TARGET)
31 | NSHumanReadableCopyright
32 | Copyright © 2015 Neko. All rights reserved.
33 | NSMainStoryboardFile
34 | Main
35 | NSPrincipalClass
36 | NSApplication
37 |
38 |
39 |
--------------------------------------------------------------------------------
/LightSwordXHelper/LightSwordXHelper.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/LightSwordXHelper/zh-Hans.lproj/Main.strings:
--------------------------------------------------------------------------------
1 |
2 | /* Class = "NSMenuItem"; title = "Customize Toolbar…"; ObjectID = "1UK-8n-QPP"; */
3 | "1UK-8n-QPP.title" = "Customize Toolbar…";
4 |
5 | /* Class = "NSMenuItem"; title = "LightSwordXHelper"; ObjectID = "1Xt-HY-uBw"; */
6 | "1Xt-HY-uBw.title" = "LightSwordXHelper";
7 |
8 | /* Class = "NSMenu"; title = "Find"; ObjectID = "1b7-l0-nxx"; */
9 | "1b7-l0-nxx.title" = "Find";
10 |
11 | /* Class = "NSMenuItem"; title = "Lower"; ObjectID = "1tx-W0-xDw"; */
12 | "1tx-W0-xDw.title" = "Lower";
13 |
14 | /* Class = "NSMenuItem"; title = "Raise"; ObjectID = "2h7-ER-AoG"; */
15 | "2h7-ER-AoG.title" = "Raise";
16 |
17 | /* Class = "NSMenuItem"; title = "Transformations"; ObjectID = "2oI-Rn-ZJC"; */
18 | "2oI-Rn-ZJC.title" = "Transformations";
19 |
20 | /* Class = "NSMenu"; title = "Spelling"; ObjectID = "3IN-sU-3Bg"; */
21 | "3IN-sU-3Bg.title" = "Spelling";
22 |
23 | /* Class = "NSMenuItem"; title = "Use Default"; ObjectID = "3Om-Ey-2VK"; */
24 | "3Om-Ey-2VK.title" = "Use Default";
25 |
26 | /* Class = "NSMenu"; title = "Speech"; ObjectID = "3rS-ZA-NoH"; */
27 | "3rS-ZA-NoH.title" = "Speech";
28 |
29 | /* Class = "NSMenuItem"; title = "Tighten"; ObjectID = "46P-cB-AYj"; */
30 | "46P-cB-AYj.title" = "Tighten";
31 |
32 | /* Class = "NSMenuItem"; title = "Find"; ObjectID = "4EN-yA-p0u"; */
33 | "4EN-yA-p0u.title" = "Find";
34 |
35 | /* Class = "NSMenuItem"; title = "Quit LightSwordXHelper"; ObjectID = "4sb-4s-VLi"; */
36 | "4sb-4s-VLi.title" = "Quit LightSwordXHelper";
37 |
38 | /* Class = "NSMenuItem"; title = "Edit"; ObjectID = "5QF-Oa-p0T"; */
39 | "5QF-Oa-p0T.title" = "Edit";
40 |
41 | /* Class = "NSMenuItem"; title = "Copy Style"; ObjectID = "5Vv-lz-BsD"; */
42 | "5Vv-lz-BsD.title" = "Copy Style";
43 |
44 | /* Class = "NSMenuItem"; title = "About LightSwordXHelper"; ObjectID = "5kV-Vb-QxS"; */
45 | "5kV-Vb-QxS.title" = "About LightSwordXHelper";
46 |
47 | /* Class = "NSMenuItem"; title = "Redo"; ObjectID = "6dh-zS-Vam"; */
48 | "6dh-zS-Vam.title" = "Redo";
49 |
50 | /* Class = "NSMenuItem"; title = "Correct Spelling Automatically"; ObjectID = "78Y-hA-62v"; */
51 | "78Y-hA-62v.title" = "Correct Spelling Automatically";
52 |
53 | /* Class = "NSMenu"; title = "Writing Direction"; ObjectID = "8mr-sm-Yjd"; */
54 | "8mr-sm-Yjd.title" = "Writing Direction";
55 |
56 | /* Class = "NSMenuItem"; title = "Substitutions"; ObjectID = "9ic-FL-obx"; */
57 | "9ic-FL-obx.title" = "Substitutions";
58 |
59 | /* Class = "NSMenuItem"; title = "Smart Copy/Paste"; ObjectID = "9yt-4B-nSM"; */
60 | "9yt-4B-nSM.title" = "Smart Copy/Paste";
61 |
62 | /* Class = "NSMenu"; title = "Main Menu"; ObjectID = "AYu-sK-qS6"; */
63 | "AYu-sK-qS6.title" = "Main Menu";
64 |
65 | /* Class = "NSMenuItem"; title = "Preferences…"; ObjectID = "BOF-NM-1cW"; */
66 | "BOF-NM-1cW.title" = "Preferences…";
67 |
68 | /* Class = "NSMenuItem"; title = "\tLeft to Right"; ObjectID = "BgM-ve-c93"; */
69 | "BgM-ve-c93.title" = "\tLeft to Right";
70 |
71 | /* Class = "NSMenuItem"; title = "Save As…"; ObjectID = "Bw7-FT-i3A"; */
72 | "Bw7-FT-i3A.title" = "Save As…";
73 |
74 | /* Class = "NSMenuItem"; title = "Close"; ObjectID = "DVo-aG-piG"; */
75 | "DVo-aG-piG.title" = "Close";
76 |
77 | /* Class = "NSMenuItem"; title = "Spelling and Grammar"; ObjectID = "Dv1-io-Yv7"; */
78 | "Dv1-io-Yv7.title" = "Spelling and Grammar";
79 |
80 | /* Class = "NSMenu"; title = "Help"; ObjectID = "F2S-fz-NVQ"; */
81 | "F2S-fz-NVQ.title" = "Help";
82 |
83 | /* Class = "NSMenuItem"; title = "LightSwordXHelper Help"; ObjectID = "FKE-Sm-Kum"; */
84 | "FKE-Sm-Kum.title" = "LightSwordXHelper Help";
85 |
86 | /* Class = "NSMenuItem"; title = "Text"; ObjectID = "Fal-I4-PZk"; */
87 | "Fal-I4-PZk.title" = "Text";
88 |
89 | /* Class = "NSMenu"; title = "Substitutions"; ObjectID = "FeM-D8-WVr"; */
90 | "FeM-D8-WVr.title" = "Substitutions";
91 |
92 | /* Class = "NSMenuItem"; title = "Bold"; ObjectID = "GB9-OM-e27"; */
93 | "GB9-OM-e27.title" = "Bold";
94 |
95 | /* Class = "NSMenu"; title = "Format"; ObjectID = "GEO-Iw-cKr"; */
96 | "GEO-Iw-cKr.title" = "Format";
97 |
98 | /* Class = "NSMenuItem"; title = "Use Default"; ObjectID = "GUa-eO-cwY"; */
99 | "GUa-eO-cwY.title" = "Use Default";
100 |
101 | /* Class = "NSMenuItem"; title = "Font"; ObjectID = "Gi5-1S-RQB"; */
102 | "Gi5-1S-RQB.title" = "Font";
103 |
104 | /* Class = "NSMenuItem"; title = "Writing Direction"; ObjectID = "H1b-Si-o9J"; */
105 | "H1b-Si-o9J.title" = "Writing Direction";
106 |
107 | /* Class = "NSMenuItem"; title = "View"; ObjectID = "H8h-7b-M4v"; */
108 | "H8h-7b-M4v.title" = "View";
109 |
110 | /* Class = "NSMenuItem"; title = "Text Replacement"; ObjectID = "HFQ-gK-NFA"; */
111 | "HFQ-gK-NFA.title" = "Text Replacement";
112 |
113 | /* Class = "NSMenuItem"; title = "Show Spelling and Grammar"; ObjectID = "HFo-cy-zxI"; */
114 | "HFo-cy-zxI.title" = "Show Spelling and Grammar";
115 |
116 | /* Class = "NSMenu"; title = "View"; ObjectID = "HyV-fh-RgO"; */
117 | "HyV-fh-RgO.title" = "View";
118 |
119 | /* Class = "NSMenuItem"; title = "Subscript"; ObjectID = "I0S-gh-46l"; */
120 | "I0S-gh-46l.title" = "Subscript";
121 |
122 | /* Class = "NSMenuItem"; title = "Open…"; ObjectID = "IAo-SY-fd9"; */
123 | "IAo-SY-fd9.title" = "Open…";
124 |
125 | /* Class = "NSMenuItem"; title = "Justify"; ObjectID = "J5U-5w-g23"; */
126 | "J5U-5w-g23.title" = "Justify";
127 |
128 | /* Class = "NSMenuItem"; title = "Use None"; ObjectID = "J7y-lM-qPV"; */
129 | "J7y-lM-qPV.title" = "Use None";
130 |
131 | /* Class = "NSMenuItem"; title = "Revert to Saved"; ObjectID = "KaW-ft-85H"; */
132 | "KaW-ft-85H.title" = "Revert to Saved";
133 |
134 | /* Class = "NSMenuItem"; title = "Show All"; ObjectID = "Kd2-mp-pUS"; */
135 | "Kd2-mp-pUS.title" = "Show All";
136 |
137 | /* Class = "NSMenuItem"; title = "Bring All to Front"; ObjectID = "LE2-aR-0XJ"; */
138 | "LE2-aR-0XJ.title" = "Bring All to Front";
139 |
140 | /* Class = "NSMenuItem"; title = "Paste Ruler"; ObjectID = "LVM-kO-fVI"; */
141 | "LVM-kO-fVI.title" = "Paste Ruler";
142 |
143 | /* Class = "NSMenuItem"; title = "\tLeft to Right"; ObjectID = "Lbh-J2-qVU"; */
144 | "Lbh-J2-qVU.title" = "\tLeft to Right";
145 |
146 | /* Class = "NSMenuItem"; title = "Copy Ruler"; ObjectID = "MkV-Pr-PK5"; */
147 | "MkV-Pr-PK5.title" = "Copy Ruler";
148 |
149 | /* Class = "NSMenuItem"; title = "Services"; ObjectID = "NMo-om-nkz"; */
150 | "NMo-om-nkz.title" = "Services";
151 |
152 | /* Class = "NSMenuItem"; title = "\tDefault"; ObjectID = "Nop-cj-93Q"; */
153 | "Nop-cj-93Q.title" = "\tDefault";
154 |
155 | /* Class = "NSMenuItem"; title = "Minimize"; ObjectID = "OY7-WF-poV"; */
156 | "OY7-WF-poV.title" = "Minimize";
157 |
158 | /* Class = "NSMenuItem"; title = "Baseline"; ObjectID = "OaQ-X3-Vso"; */
159 | "OaQ-X3-Vso.title" = "Baseline";
160 |
161 | /* Class = "NSMenuItem"; title = "Hide LightSwordXHelper"; ObjectID = "Olw-nP-bQN"; */
162 | "Olw-nP-bQN.title" = "Hide LightSwordXHelper";
163 |
164 | /* Class = "NSMenuItem"; title = "Find Previous"; ObjectID = "OwM-mh-QMV"; */
165 | "OwM-mh-QMV.title" = "Find Previous";
166 |
167 | /* Class = "NSMenuItem"; title = "Stop Speaking"; ObjectID = "Oyz-dy-DGm"; */
168 | "Oyz-dy-DGm.title" = "Stop Speaking";
169 |
170 | /* Class = "NSMenuItem"; title = "Bigger"; ObjectID = "Ptp-SP-VEL"; */
171 | "Ptp-SP-VEL.title" = "Bigger";
172 |
173 | /* Class = "NSMenuItem"; title = "Show Fonts"; ObjectID = "Q5e-8K-NDq"; */
174 | "Q5e-8K-NDq.title" = "Show Fonts";
175 |
176 | /* Class = "NSMenuItem"; title = "Zoom"; ObjectID = "R4o-n2-Eq4"; */
177 | "R4o-n2-Eq4.title" = "Zoom";
178 |
179 | /* Class = "NSMenuItem"; title = "\tRight to Left"; ObjectID = "RB4-Sm-HuC"; */
180 | "RB4-Sm-HuC.title" = "\tRight to Left";
181 |
182 | /* Class = "NSMenuItem"; title = "Superscript"; ObjectID = "Rqc-34-cIF"; */
183 | "Rqc-34-cIF.title" = "Superscript";
184 |
185 | /* Class = "NSMenuItem"; title = "Select All"; ObjectID = "Ruw-6m-B2m"; */
186 | "Ruw-6m-B2m.title" = "Select All";
187 |
188 | /* Class = "NSMenuItem"; title = "Jump to Selection"; ObjectID = "S0p-oC-mLd"; */
189 | "S0p-oC-mLd.title" = "Jump to Selection";
190 |
191 | /* Class = "NSMenu"; title = "Window"; ObjectID = "Td7-aD-5lo"; */
192 | "Td7-aD-5lo.title" = "Window";
193 |
194 | /* Class = "NSMenuItem"; title = "Capitalize"; ObjectID = "UEZ-Bs-lqG"; */
195 | "UEZ-Bs-lqG.title" = "Capitalize";
196 |
197 | /* Class = "NSMenuItem"; title = "Center"; ObjectID = "VIY-Ag-zcb"; */
198 | "VIY-Ag-zcb.title" = "Center";
199 |
200 | /* Class = "NSMenuItem"; title = "Hide Others"; ObjectID = "Vdr-fp-XzO"; */
201 | "Vdr-fp-XzO.title" = "Hide Others";
202 |
203 | /* Class = "NSMenuItem"; title = "Italic"; ObjectID = "Vjx-xi-njq"; */
204 | "Vjx-xi-njq.title" = "Italic";
205 |
206 | /* Class = "NSMenu"; title = "Edit"; ObjectID = "W48-6f-4Dl"; */
207 | "W48-6f-4Dl.title" = "Edit";
208 |
209 | /* Class = "NSMenuItem"; title = "Underline"; ObjectID = "WRG-CD-K1S"; */
210 | "WRG-CD-K1S.title" = "Underline";
211 |
212 | /* Class = "NSMenuItem"; title = "New"; ObjectID = "Was-JA-tGl"; */
213 | "Was-JA-tGl.title" = "New";
214 |
215 | /* Class = "NSMenuItem"; title = "Paste and Match Style"; ObjectID = "WeT-3V-zwk"; */
216 | "WeT-3V-zwk.title" = "Paste and Match Style";
217 |
218 | /* Class = "NSMenuItem"; title = "Find…"; ObjectID = "Xz5-n4-O0W"; */
219 | "Xz5-n4-O0W.title" = "Find…";
220 |
221 | /* Class = "NSMenuItem"; title = "Find and Replace…"; ObjectID = "YEy-JH-Tfz"; */
222 | "YEy-JH-Tfz.title" = "Find and Replace…";
223 |
224 | /* Class = "NSMenuItem"; title = "\tDefault"; ObjectID = "YGs-j5-SAR"; */
225 | "YGs-j5-SAR.title" = "\tDefault";
226 |
227 | /* Class = "NSMenuItem"; title = "Start Speaking"; ObjectID = "Ynk-f8-cLZ"; */
228 | "Ynk-f8-cLZ.title" = "Start Speaking";
229 |
230 | /* Class = "NSMenuItem"; title = "Align Left"; ObjectID = "ZM1-6Q-yy1"; */
231 | "ZM1-6Q-yy1.title" = "Align Left";
232 |
233 | /* Class = "NSMenuItem"; title = "Paragraph"; ObjectID = "ZvO-Gk-QUH"; */
234 | "ZvO-Gk-QUH.title" = "Paragraph";
235 |
236 | /* Class = "NSMenuItem"; title = "Print…"; ObjectID = "aTl-1u-JFS"; */
237 | "aTl-1u-JFS.title" = "Print…";
238 |
239 | /* Class = "NSMenuItem"; title = "Window"; ObjectID = "aUF-d1-5bR"; */
240 | "aUF-d1-5bR.title" = "Window";
241 |
242 | /* Class = "NSMenu"; title = "Font"; ObjectID = "aXa-aM-Jaq"; */
243 | "aXa-aM-Jaq.title" = "Font";
244 |
245 | /* Class = "NSMenuItem"; title = "Use Default"; ObjectID = "agt-UL-0e3"; */
246 | "agt-UL-0e3.title" = "Use Default";
247 |
248 | /* Class = "NSMenuItem"; title = "Show Colors"; ObjectID = "bgn-CT-cEk"; */
249 | "bgn-CT-cEk.title" = "Show Colors";
250 |
251 | /* Class = "NSMenu"; title = "File"; ObjectID = "bib-Uj-vzu"; */
252 | "bib-Uj-vzu.title" = "File";
253 |
254 | /* Class = "NSMenuItem"; title = "Use Selection for Find"; ObjectID = "buJ-ug-pKt"; */
255 | "buJ-ug-pKt.title" = "Use Selection for Find";
256 |
257 | /* Class = "NSMenu"; title = "Transformations"; ObjectID = "c8a-y6-VQd"; */
258 | "c8a-y6-VQd.title" = "Transformations";
259 |
260 | /* Class = "NSMenuItem"; title = "Use None"; ObjectID = "cDB-IK-hbR"; */
261 | "cDB-IK-hbR.title" = "Use None";
262 |
263 | /* Class = "NSMenuItem"; title = "Selection"; ObjectID = "cqv-fj-IhA"; */
264 | "cqv-fj-IhA.title" = "Selection";
265 |
266 | /* Class = "NSMenuItem"; title = "Smart Links"; ObjectID = "cwL-P1-jid"; */
267 | "cwL-P1-jid.title" = "Smart Links";
268 |
269 | /* Class = "NSMenuItem"; title = "Make Lower Case"; ObjectID = "d9M-CD-aMd"; */
270 | "d9M-CD-aMd.title" = "Make Lower Case";
271 |
272 | /* Class = "NSMenu"; title = "Text"; ObjectID = "d9c-me-L2H"; */
273 | "d9c-me-L2H.title" = "Text";
274 |
275 | /* Class = "NSMenuItem"; title = "File"; ObjectID = "dMs-cI-mzQ"; */
276 | "dMs-cI-mzQ.title" = "File";
277 |
278 | /* Class = "NSMenuItem"; title = "Undo"; ObjectID = "dRJ-4n-Yzg"; */
279 | "dRJ-4n-Yzg.title" = "Undo";
280 |
281 | /* Class = "NSMenuItem"; title = "Paste"; ObjectID = "gVA-U4-sdL"; */
282 | "gVA-U4-sdL.title" = "Paste";
283 |
284 | /* Class = "NSMenuItem"; title = "Smart Quotes"; ObjectID = "hQb-2v-fYv"; */
285 | "hQb-2v-fYv.title" = "Smart Quotes";
286 |
287 | /* Class = "NSMenuItem"; title = "Check Document Now"; ObjectID = "hz2-CU-CR7"; */
288 | "hz2-CU-CR7.title" = "Check Document Now";
289 |
290 | /* Class = "NSMenu"; title = "Services"; ObjectID = "hz9-B4-Xy5"; */
291 | "hz9-B4-Xy5.title" = "Services";
292 |
293 | /* Class = "NSMenuItem"; title = "Smaller"; ObjectID = "i1d-Er-qST"; */
294 | "i1d-Er-qST.title" = "Smaller";
295 |
296 | /* Class = "NSMenu"; title = "Baseline"; ObjectID = "ijk-EB-dga"; */
297 | "ijk-EB-dga.title" = "Baseline";
298 |
299 | /* Class = "NSMenuItem"; title = "Kern"; ObjectID = "jBQ-r6-VK2"; */
300 | "jBQ-r6-VK2.title" = "Kern";
301 |
302 | /* Class = "NSMenuItem"; title = "\tRight to Left"; ObjectID = "jFq-tB-4Kx"; */
303 | "jFq-tB-4Kx.title" = "\tRight to Left";
304 |
305 | /* Class = "NSMenuItem"; title = "Format"; ObjectID = "jxT-CU-nIS"; */
306 | "jxT-CU-nIS.title" = "Format";
307 |
308 | /* Class = "NSMenuItem"; title = "Check Grammar With Spelling"; ObjectID = "mK6-2p-4JG"; */
309 | "mK6-2p-4JG.title" = "Check Grammar With Spelling";
310 |
311 | /* Class = "NSMenuItem"; title = "Ligatures"; ObjectID = "o6e-r0-MWq"; */
312 | "o6e-r0-MWq.title" = "Ligatures";
313 |
314 | /* Class = "NSMenu"; title = "Open Recent"; ObjectID = "oas-Oc-fiZ"; */
315 | "oas-Oc-fiZ.title" = "Open Recent";
316 |
317 | /* Class = "NSMenuItem"; title = "Loosen"; ObjectID = "ogc-rX-tC1"; */
318 | "ogc-rX-tC1.title" = "Loosen";
319 |
320 | /* Class = "NSMenuItem"; title = "Delete"; ObjectID = "pa3-QI-u2k"; */
321 | "pa3-QI-u2k.title" = "Delete";
322 |
323 | /* Class = "NSMenuItem"; title = "Save…"; ObjectID = "pxx-59-PXV"; */
324 | "pxx-59-PXV.title" = "Save…";
325 |
326 | /* Class = "NSMenuItem"; title = "Find Next"; ObjectID = "q09-fT-Sye"; */
327 | "q09-fT-Sye.title" = "Find Next";
328 |
329 | /* Class = "NSMenuItem"; title = "Page Setup…"; ObjectID = "qIS-W8-SiK"; */
330 | "qIS-W8-SiK.title" = "Page Setup…";
331 |
332 | /* Class = "NSMenuItem"; title = "Check Spelling While Typing"; ObjectID = "rbD-Rh-wIN"; */
333 | "rbD-Rh-wIN.title" = "Check Spelling While Typing";
334 |
335 | /* Class = "NSMenuItem"; title = "Smart Dashes"; ObjectID = "rgM-f4-ycn"; */
336 | "rgM-f4-ycn.title" = "Smart Dashes";
337 |
338 | /* Class = "NSMenuItem"; title = "Show Toolbar"; ObjectID = "snW-S8-Cw5"; */
339 | "snW-S8-Cw5.title" = "Show Toolbar";
340 |
341 | /* Class = "NSMenuItem"; title = "Data Detectors"; ObjectID = "tRr-pd-1PS"; */
342 | "tRr-pd-1PS.title" = "Data Detectors";
343 |
344 | /* Class = "NSMenuItem"; title = "Open Recent"; ObjectID = "tXI-mr-wws"; */
345 | "tXI-mr-wws.title" = "Open Recent";
346 |
347 | /* Class = "NSMenu"; title = "Kern"; ObjectID = "tlD-Oa-oAM"; */
348 | "tlD-Oa-oAM.title" = "Kern";
349 |
350 | /* Class = "NSMenu"; title = "LightSwordXHelper"; ObjectID = "uQy-DD-JDr"; */
351 | "uQy-DD-JDr.title" = "LightSwordXHelper";
352 |
353 | /* Class = "NSMenuItem"; title = "Cut"; ObjectID = "uRl-iY-unG"; */
354 | "uRl-iY-unG.title" = "Cut";
355 |
356 | /* Class = "NSMenuItem"; title = "Paste Style"; ObjectID = "vKC-jM-MkH"; */
357 | "vKC-jM-MkH.title" = "Paste Style";
358 |
359 | /* Class = "NSMenuItem"; title = "Show Ruler"; ObjectID = "vLm-3I-IUL"; */
360 | "vLm-3I-IUL.title" = "Show Ruler";
361 |
362 | /* Class = "NSMenuItem"; title = "Clear Menu"; ObjectID = "vNY-rz-j42"; */
363 | "vNY-rz-j42.title" = "Clear Menu";
364 |
365 | /* Class = "NSMenuItem"; title = "Make Upper Case"; ObjectID = "vmV-6d-7jI"; */
366 | "vmV-6d-7jI.title" = "Make Upper Case";
367 |
368 | /* Class = "NSMenu"; title = "Ligatures"; ObjectID = "w0m-vy-SC9"; */
369 | "w0m-vy-SC9.title" = "Ligatures";
370 |
371 | /* Class = "NSMenuItem"; title = "Align Right"; ObjectID = "wb2-vD-lq4"; */
372 | "wb2-vD-lq4.title" = "Align Right";
373 |
374 | /* Class = "NSMenuItem"; title = "Help"; ObjectID = "wpr-3q-Mcd"; */
375 | "wpr-3q-Mcd.title" = "Help";
376 |
377 | /* Class = "NSMenuItem"; title = "Copy"; ObjectID = "x3v-GG-iWU"; */
378 | "x3v-GG-iWU.title" = "Copy";
379 |
380 | /* Class = "NSMenuItem"; title = "Use All"; ObjectID = "xQD-1f-W4t"; */
381 | "xQD-1f-W4t.title" = "Use All";
382 |
383 | /* Class = "NSMenuItem"; title = "Speech"; ObjectID = "xrE-MZ-jX0"; */
384 | "xrE-MZ-jX0.title" = "Speech";
385 |
386 | /* Class = "NSMenuItem"; title = "Show Substitutions"; ObjectID = "z6F-FW-3nz"; */
387 | "z6F-FW-3nz.title" = "Show Substitutions";
388 |
--------------------------------------------------------------------------------
/LightSwordXTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/LightSwordXTests/LightSwordXTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LightSwordXTests.swift
3 | // LightSwordXTests
4 | //
5 | // Created by Neko on 12/17/15.
6 | // Copyright © 2015 Neko. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import LightSwordX
11 |
12 | class LightSwordXTests: XCTestCase {
13 |
14 | override func setUp() {
15 | super.setUp()
16 | // Put setup code here. This method is called before the invocation of each test method in the class.
17 | }
18 |
19 | override func tearDown() {
20 | // Put teardown code here. This method is called after the invocation of each test method in the class.
21 | super.tearDown()
22 | }
23 |
24 | func testExample() {
25 | // This is an example of a functional test case.
26 | // Use XCTAssert and related functions to verify your tests produce the correct results.
27 | }
28 |
29 | func testPerformanceExample() {
30 | // This is an example of a performance test case.
31 | self.measureBlock {
32 | // Put the code you want to measure the time of here.
33 | }
34 | }
35 |
36 | func testIpv4() {
37 | let rawData = [0x87, 0x58, 0x24, 0xef];
38 | let addr = rawData.reduce("", combine: { (c: String, n: Int) in c.characters.count > 1 ? c + String(format: ".%d", n) : String(format: "%d.%d", c, n)})
39 |
40 | assert(addr == "135.88.36.239");
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # LightSwordX
2 |
3 | [简体中文](./README_zh.md)
4 |
5 | LightSwordX is a SOCKS5 proxy client for OS X 10.10+.
6 |
7 | It's an open-source project. To get it, you may download the source code and compile it on your Mac, or buy it from Mac App Store.
8 |
9 | LightSwordX has a built-in remote proxy server that is free for everyone. Of course, everyone can set up LightSword Server for self, and enjoy it by using LightSwordX or LightSword Command Line Interface.
10 |
11 | **HOW TO USE**
12 |
13 | 1. Run LightSword from Launchpad
14 |
15 | 2. Open System Preferences - Network - Advanced - Proxies
16 |
17 | 3. Select 'SOCKS Proxy', fill in server address and port number
18 |
19 | 4. Click OK - Apply Settings
20 |
21 | 5. Open Safari or Chrome, surf the Internet!
22 |
23 | You can buy it from Mac App Store:
24 |
25 | [
](https://itunes.apple.com/us/app/lightswordx/id1071607364?ls=1&mt=12)
26 |
27 | Price: $0.99
28 |
29 | **Why it's not Free on Mac App Store?**
30 |
31 | LightSwordX is an open-source software, everyone can download the source code and compile it on Mac without any cost. But you may know **maintenance is the most expensive part** of software. No one can live without money! So, as a developer, I hope people would use and buy it. Thanks.
32 |
33 | Features
34 | ---
35 |
36 | ✓ Enable mutli proxy servers simultaneously
37 |
38 | ✓ IPv6
39 |
40 | ✓ Whitelist & Blacklist
41 |
42 | ✓ Start self on system startup
43 |
44 | ✓ Traffic statistics
45 |
46 | Privacy Policy
47 | ---
48 |
49 | LightSwordX doesn't collect any data about the user.
50 |
51 | License
52 | ---
53 |
54 | GPLv2
--------------------------------------------------------------------------------
/README_zh.md:
--------------------------------------------------------------------------------
1 | # LightSwordX
2 |
3 | [English](./README.md)
4 |
5 | LightSwordX 是一款基于 OS X 10.10+ 的 SOCKS5 代理客户端应用
6 |
7 | LightSwordX 是完全开源的,你可以下载源码并且在 Mac 上编译,或者从 Mac App Store 上购买。
8 |
9 | LightSwordX 内置一台由网友免费提供的公用代理服务器,当然,你也可以搭建自己的服务器,并通过 LightSwordX 或者命令行工具使用代理。
10 |
11 | **如何使用**
12 |
13 | 1. 从 Mac App Store 购买或者下载源码编译并运行,输入服务器IP地址、端口号,密码,勾选“启用该服务器”
14 |
15 | 2. 打开系统偏好 - 网络 - 高级 - 代理
16 |
17 | 3. 勾选 “SOCKS 代理”
18 |
19 | 4. 输入 127.0.0.1 和端口号(默认: 1080),无需密码
20 |
21 | 5. 保存并应用设置
22 |
23 | 6. 使用 Safari 或 Chrome 访问 Internet
24 |
25 | 如果你有多台服务器,LightSwordX 也支持同时启用多服务器。只需要点击 + 按钮,按照上述配置新服务器即可。 在 Chrome 中,安装 SwitchyOmega 插件,新建 Profile,选择 SOCKS5 代理类型,并且填写本地 IP 和端口号,最后再启用 SwitchyOmega 即可。
26 |
27 | 从 Mac App Store 购买:
28 |
29 | [
](https://itunes.apple.com/us/app/lightswordx/id1071607364?ls=1&mt=12)
30 |
31 | 价格: $0.99
32 |
33 | **为什么不是免费的?**
34 |
35 | LightSwordX 是完全开源的软件,每个人都可以下载源码并且编译运行。但是创建和维护任何一个项目都是需要成本与开销的。即便是开源项目,通常来说,也要有资金来源才能更好的发展。虽然不论你是否购买,我都会维护下去,但还是希望有用户能够购买该 App,支持这个该项目发展。
36 |
37 | 特性
38 | ---
39 |
40 | ✓ 同时使用多台服务器
41 |
42 | ✓ IPv6
43 |
44 | ✓ 黑白名单
45 |
46 | ✓ 开机启动
47 |
48 | ✓ 流量统计
49 |
50 | 隐私政策
51 | ---
52 |
53 | LightSwordX 不收集有关用户的任何信息
54 |
55 | License
56 | ---
57 | GPLv2
--------------------------------------------------------------------------------
/SINQ.framework/Headers:
--------------------------------------------------------------------------------
1 | Versions/Current/Headers
--------------------------------------------------------------------------------
/SINQ.framework/Modules:
--------------------------------------------------------------------------------
1 | Versions/Current/Modules
--------------------------------------------------------------------------------
/SINQ.framework/Resources:
--------------------------------------------------------------------------------
1 | Versions/Current/Resources
--------------------------------------------------------------------------------
/SINQ.framework/SINQ:
--------------------------------------------------------------------------------
1 | Versions/Current/SINQ
--------------------------------------------------------------------------------
/SINQ.framework/Versions/A/Headers/SINQ-Swift.h:
--------------------------------------------------------------------------------
1 | // Generated by Apple Swift version 2.1.1 (swiftlang-700.1.101.15 clang-700.1.81)
2 | #pragma clang diagnostic push
3 |
4 | #if defined(__has_include) && __has_include()
5 | # include
6 | #endif
7 |
8 | #pragma clang diagnostic ignored "-Wauto-import"
9 | #include
10 | #include
11 | #include
12 | #include
13 |
14 | #if defined(__has_include) && __has_include()
15 | # include
16 | #elif !defined(__cplusplus) || __cplusplus < 201103L
17 | typedef uint_least16_t char16_t;
18 | typedef uint_least32_t char32_t;
19 | #endif
20 |
21 | typedef struct _NSZone NSZone;
22 |
23 | #if !defined(SWIFT_PASTE)
24 | # define SWIFT_PASTE_HELPER(x, y) x##y
25 | # define SWIFT_PASTE(x, y) SWIFT_PASTE_HELPER(x, y)
26 | #endif
27 | #if !defined(SWIFT_METATYPE)
28 | # define SWIFT_METATYPE(X) Class
29 | #endif
30 |
31 | #if defined(__has_attribute) && __has_attribute(objc_runtime_name)
32 | # define SWIFT_RUNTIME_NAME(X) __attribute__((objc_runtime_name(X)))
33 | #else
34 | # define SWIFT_RUNTIME_NAME(X)
35 | #endif
36 | #if defined(__has_attribute) && __has_attribute(swift_name)
37 | # define SWIFT_COMPILE_NAME(X) __attribute__((swift_name(X)))
38 | #else
39 | # define SWIFT_COMPILE_NAME(X)
40 | #endif
41 | #if !defined(SWIFT_CLASS_EXTRA)
42 | # define SWIFT_CLASS_EXTRA
43 | #endif
44 | #if !defined(SWIFT_PROTOCOL_EXTRA)
45 | # define SWIFT_PROTOCOL_EXTRA
46 | #endif
47 | #if !defined(SWIFT_ENUM_EXTRA)
48 | # define SWIFT_ENUM_EXTRA
49 | #endif
50 | #if !defined(SWIFT_CLASS)
51 | # if defined(__has_attribute) && __has_attribute(objc_subclassing_restricted)
52 | # define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_CLASS_EXTRA
53 | # define SWIFT_CLASS_NAMED(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
54 | # else
55 | # define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
56 | # define SWIFT_CLASS_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
57 | # endif
58 | #endif
59 |
60 | #if !defined(SWIFT_PROTOCOL)
61 | # define SWIFT_PROTOCOL(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA
62 | # define SWIFT_PROTOCOL_NAMED(SWIFT_NAME) SWIFT_COMPILE_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA
63 | #endif
64 |
65 | #if !defined(SWIFT_EXTENSION)
66 | # define SWIFT_EXTENSION(M) SWIFT_PASTE(M##_Swift_, __LINE__)
67 | #endif
68 |
69 | #if !defined(OBJC_DESIGNATED_INITIALIZER)
70 | # if defined(__has_attribute) && __has_attribute(objc_designated_initializer)
71 | # define OBJC_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer))
72 | # else
73 | # define OBJC_DESIGNATED_INITIALIZER
74 | # endif
75 | #endif
76 | #if !defined(SWIFT_ENUM)
77 | # define SWIFT_ENUM(_type, _name) enum _name : _type _name; enum SWIFT_ENUM_EXTRA _name : _type
78 | #endif
79 | typedef float swift_float2 __attribute__((__ext_vector_type__(2)));
80 | typedef float swift_float3 __attribute__((__ext_vector_type__(3)));
81 | typedef float swift_float4 __attribute__((__ext_vector_type__(4)));
82 | typedef double swift_double2 __attribute__((__ext_vector_type__(2)));
83 | typedef double swift_double3 __attribute__((__ext_vector_type__(3)));
84 | typedef double swift_double4 __attribute__((__ext_vector_type__(4)));
85 | typedef int swift_int2 __attribute__((__ext_vector_type__(2)));
86 | typedef int swift_int3 __attribute__((__ext_vector_type__(3)));
87 | typedef int swift_int4 __attribute__((__ext_vector_type__(4)));
88 | #if defined(__has_feature) && __has_feature(modules)
89 | #endif
90 |
91 | #pragma clang diagnostic ignored "-Wproperty-attribute-mismatch"
92 | #pragma clang diagnostic ignored "-Wduplicate-method-arg"
93 | #pragma clang diagnostic pop
94 |
--------------------------------------------------------------------------------
/SINQ.framework/Versions/A/Headers/SINQ.h:
--------------------------------------------------------------------------------
1 | //
2 | // SINQ.h
3 | // SINQ
4 | //
5 | // Created by Leszek Ślażyński on 25/06/14.
6 | // Copyright (c) 2014 Leszek Ślażyński. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | //! Project version number for SINQ.
12 | FOUNDATION_EXPORT double SINQVersionNumber;
13 |
14 | //! Project version string for SINQ.
15 | FOUNDATION_EXPORT const unsigned char SINQVersionString[];
16 |
17 | // In this header, you should import all the public headers of your framework using statements like #import
18 |
19 |
20 |
--------------------------------------------------------------------------------
/SINQ.framework/Versions/A/Modules/SINQ.swiftmodule/x86_64.swiftdoc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UnsignedInt8/LightSwordX/98eea71721ae22a65446b9d56f45aa2a689f5266/SINQ.framework/Versions/A/Modules/SINQ.swiftmodule/x86_64.swiftdoc
--------------------------------------------------------------------------------
/SINQ.framework/Versions/A/Modules/SINQ.swiftmodule/x86_64.swiftmodule:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UnsignedInt8/LightSwordX/98eea71721ae22a65446b9d56f45aa2a689f5266/SINQ.framework/Versions/A/Modules/SINQ.swiftmodule/x86_64.swiftmodule
--------------------------------------------------------------------------------
/SINQ.framework/Versions/A/Modules/module.modulemap:
--------------------------------------------------------------------------------
1 | framework module SINQ {
2 | umbrella header "SINQ.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
8 | module SINQ.Swift {
9 | header "SINQ-Swift.h"
10 | }
11 |
--------------------------------------------------------------------------------
/SINQ.framework/Versions/A/Resources/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | BuildMachineOSBuild
6 | 15D21
7 | CFBundleDevelopmentRegion
8 | en
9 | CFBundleExecutable
10 | SINQ
11 | CFBundleIdentifier
12 | com.utdloc.SINQ
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | SINQ
17 | CFBundlePackageType
18 | FMWK
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleSupportedPlatforms
24 |
25 | MacOSX
26 |
27 | CFBundleVersion
28 | 0.5.0
29 | DTCompiler
30 | com.apple.compilers.llvm.clang.1_0
31 | DTPlatformBuild
32 | 7C1002
33 | DTPlatformVersion
34 | GM
35 | DTSDKBuild
36 | 15C43
37 | DTSDKName
38 | macosx10.11
39 | DTXcode
40 | 0721
41 | DTXcodeBuild
42 | 7C1002
43 | NSHumanReadableCopyright
44 | Copyright © 2014 Leszek Ślażyński. All rights reserved.
45 |
46 |
47 |
--------------------------------------------------------------------------------
/SINQ.framework/Versions/A/SINQ:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UnsignedInt8/LightSwordX/98eea71721ae22a65446b9d56f45aa2a689f5266/SINQ.framework/Versions/A/SINQ
--------------------------------------------------------------------------------
/SINQ.framework/Versions/Current:
--------------------------------------------------------------------------------
1 | A
--------------------------------------------------------------------------------