sse请求 写作思路

This commit is contained in:
pengguangjian 2024-10-21 18:32:40 +08:00
parent 40e1ef1ca5
commit 62a2a61d4d
141 changed files with 10803 additions and 3980 deletions

View File

@ -53,6 +53,8 @@ pod 'UMLink'
pod 'libpag'
pod 'SocketRocket'
post_install do |installer|
installer.generated_projects.each do |project|
project.targets.each do |target|

View File

@ -40,6 +40,7 @@ PODS:
- SDWebImage (5.13.4):
- SDWebImage/Core (= 5.13.4)
- SDWebImage/Core (5.13.4)
- SocketRocket (0.6.0)
- SSZipArchive (2.4.3)
- "UITableView+FDTemplateLayoutCell (1.6)"
- UMAPM (1.9.3)
@ -73,6 +74,7 @@ DEPENDENCIES:
- SDAutoLayout
- SDCycleScrollView
- SDWebImage
- SocketRocket
- SSZipArchive
- "UITableView+FDTemplateLayoutCell"
- UMAPM
@ -105,6 +107,7 @@ SPEC REPOS:
- SDAutoLayout
- SDCycleScrollView
- SDWebImage
- SocketRocket
- SSZipArchive
- "UITableView+FDTemplateLayoutCell"
- UMAPM
@ -137,6 +140,7 @@ SPEC CHECKSUMS:
SDAutoLayout: 8bf6b3bbc8b01f775d4defbb4fda2ace805461be
SDCycleScrollView: a0d74c3384caa72bdfc81470bdbc8c14b3e1fbcf
SDWebImage: e5cc87bf736e60f49592f307bdf9e157189298a3
SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608
SSZipArchive: fe6a26b2a54d5a0890f2567b5cc6de5caa600aef
"UITableView+FDTemplateLayoutCell": 5c949b4a5059c404b442926c0e80f81d10a2d66f
UMAPM: a52ef6d5be72dd11591b917d96df97627970dae6
@ -149,6 +153,6 @@ SPEC CHECKSUMS:
YYText: 5c461d709e24d55a182d1441c41dc639a18a4849
ZXSDK: 414bed508b670437a9bdf7c75d49816b8cb7b2d4
PODFILE CHECKSUM: bef478a5b7edd65f522a744500660b294b7282a8
PODFILE CHECKSUM: 423f6e702dde61dc794a9261b5aa5b8703aa4e68
COCOAPODS: 1.15.2

View File

@ -40,6 +40,7 @@ PODS:
- SDWebImage (5.13.4):
- SDWebImage/Core (= 5.13.4)
- SDWebImage/Core (5.13.4)
- SocketRocket (0.6.0)
- SSZipArchive (2.4.3)
- "UITableView+FDTemplateLayoutCell (1.6)"
- UMAPM (1.9.3)
@ -73,6 +74,7 @@ DEPENDENCIES:
- SDAutoLayout
- SDCycleScrollView
- SDWebImage
- SocketRocket
- SSZipArchive
- "UITableView+FDTemplateLayoutCell"
- UMAPM
@ -105,6 +107,7 @@ SPEC REPOS:
- SDAutoLayout
- SDCycleScrollView
- SDWebImage
- SocketRocket
- SSZipArchive
- "UITableView+FDTemplateLayoutCell"
- UMAPM
@ -137,6 +140,7 @@ SPEC CHECKSUMS:
SDAutoLayout: 8bf6b3bbc8b01f775d4defbb4fda2ace805461be
SDCycleScrollView: a0d74c3384caa72bdfc81470bdbc8c14b3e1fbcf
SDWebImage: e5cc87bf736e60f49592f307bdf9e157189298a3
SocketRocket: fccef3f9c5cedea1353a9ef6ada904fde10d6608
SSZipArchive: fe6a26b2a54d5a0890f2567b5cc6de5caa600aef
"UITableView+FDTemplateLayoutCell": 5c949b4a5059c404b442926c0e80f81d10a2d66f
UMAPM: a52ef6d5be72dd11591b917d96df97627970dae6
@ -149,6 +153,6 @@ SPEC CHECKSUMS:
YYText: 5c461d709e24d55a182d1441c41dc639a18a4849
ZXSDK: 414bed508b670437a9bdf7c75d49816b8cb7b2d4
PODFILE CHECKSUM: bef478a5b7edd65f522a744500660b294b7282a8
PODFILE CHECKSUM: 423f6e702dde61dc794a9261b5aa5b8703aa4e68
COCOAPODS: 1.15.2

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1500"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "1948D0B63D2CF6A48E18B0B292BC6091"
BuildableName = "SocketRocket.framework"
BlueprintName = "SocketRocket"
ReferencedContainer = "container:Pods.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@ -104,6 +104,11 @@
<key>isShown</key>
<false/>
</dict>
<key>SocketRocket.xcscheme</key>
<dict>
<key>isShown</key>
<false/>
</dict>
<key>UITableView+FDTemplateLayoutCell.xcscheme</key>
<dict>
<key>isShown</key>

30
ProductApp/Pods/SocketRocket/LICENSE generated Normal file
View File

@ -0,0 +1,30 @@
BSD License
For SocketRocket software
Copyright (c) 2016-present, Facebook, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name Facebook nor the names of its contributors may be used to
endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,11 @@
Copyright (c) 2016-present, Facebook, Inc. All rights reserved.
The examples provided by Facebook are for non-commercial testing and evaluation
purposes only. Facebook reserves all rights not expressly granted.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

214
ProductApp/Pods/SocketRocket/README.md generated Normal file
View File

@ -0,0 +1,214 @@
# SocketRocket
![Platforms][platforms-svg]
[![License][license-svg]][license-link]
[![Podspec][podspec-svg]][podspec-link]
[![Carthage Compatible][carthage-svg]](carthage-link)
[![Build Status][build-status-svg]][build-status-link]
A conforming WebSocket ([RFC 6455](https://tools.ietf.org/html/rfc6455>)) client library for iOS, macOS and tvOS.
Test results for SocketRocket [here](http://facebook.github.io/SocketRocket/results/).
You can compare to what modern browsers look like [here](http://autobahn.ws/testsuite/reports/clients/index.html).
SocketRocket currently conforms to all core ~300 of [Autobahn](http://autobahn.ws/testsuite/>)'s fuzzing tests
(aside from two UTF-8 ones where it is merely *non-strict* tests 6.4.2 and 6.4.4).
## Features/Design
- TLS (wss) support, including self-signed certificates.
- Seems to perform quite well.
- Supports HTTP Proxies.
- Supports IPv4/IPv6.
- Supports SSL certificate pinning.
- Sends `ping` and can process `pong` events.
- Asynchronous and non-blocking. Most of the work is done on a background thread.
- Supports iOS, macOS, tvOS.
## Installing
There are a few options. Choose one, or just figure it out:
- **[CocoaPods](https://cocoapods.org)**
Add the following line to your Podfile:
```ruby
pod 'SocketRocket'
```
Run `pod install`, and you are all set.
- **[Carthage](https://github.com/carthage/carthage)**
Add the following line to your Cartfile:
```
github "facebook/SocketRocket"
```
Run `carthage update`, and you should now have the latest version of `SocketRocket` in your `Carthage` folder.
- **Using SocketRocket as a sub-project**
You can also include `SocketRocket` as a subproject inside of your application if you'd prefer, although we do not recommend this, as it will increase your indexing time significantly. To do so, just drag and drop the `SocketRocket.xcodeproj` file into your workspace.
## API
### `SRWebSocket`
The Web Socket.
#### Note:
`SRWebSocket` will retain itself between `-(void)open` and when it closes, errors, or fails.
This is similar to how `NSURLConnection` behaves (unlike `NSURLConnection`, `SRWebSocket` won't retain the delegate).
#### Interface
```objective-c
@interface SRWebSocket : NSObject
// Make it with this
- (instancetype)initWithURLRequest:(NSURLRequest *)request;
// Set this before opening
@property (nonatomic, weak) id <SRWebSocketDelegate> delegate;
// Open with this
- (void)open;
// Close it with this
- (void)close;
// Send a Data
- (void)sendData:(nullable NSData *)data error:(NSError **)error;
// Send a UTF8 String
- (void)sendString:(NSString *)string error:(NSError **)error;
@end
```
### `SRWebSocketDelegate`
You implement this
```objective-c
@protocol SRWebSocketDelegate <NSObject>
@optional
- (void)webSocketDidOpen:(SRWebSocket *)webSocket;
- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessageWithString:(NSString *)string;
- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessageWithData:(NSData *)data;
- (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error;
- (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(nullable NSString *)reason wasClean:(BOOL)wasClean;
@end
```
## Testing
Included are setup scripts for the python testing environment.
It comes packaged with vitualenv so all the dependencies are installed in userland.
To run the short test from the command line, run:
```bash
make test
```
To run all the tests, run:
```bash
make test_all
```
The short tests don't include the performance tests
(the test harness is actually the bottleneck, not SocketRocket).
The first time this is run, it may take a while to install the dependencies. It will be smooth sailing after that.
You can also run tests inside Xcode, which runs the same thing, but makes it easier to debug.
- Choose the `SocketRocketTests` target
- Make sure your running destination is either your Mac or any Simulator
- Run the test action (`⌘+U`)
### TestChat Demo Application
SocketRocket includes a demo app, TestChat.
It will "chat" with a listening websocket on port 9900.
#### TestChat Server
The sever takes a message and broadcasts it to all other connected clients.
It requires some dependencies though to run.
We also want to reuse the virtualenv we made when we ran the tests.
If you haven't run the tests yet, go into the SocketRocket root directory and type:
```bash
make test
```
This will set up your [virtualenv](https://pypi.python.org/pypi/virtualenv).
Now, in your terminal:
```bash
source .env/bin/activate
pip install git+https://github.com/tornadoweb/tornado.git
```
In the same terminal session, start the chatroom server:
```bash
python TestChatServer/py/chatroom.py
```
There's also a Go implementation (with the latest weekly) where you can:
```bash
cd TestChatServer/go
go run chatroom.go
```
#### Chatting
Now, start TestChat.app (just run the target in the Xcode project).
If you had it started already you can hit the refresh button to reconnect.
It should say "Connected!" on top.
To talk with the app, open up your browser to [http://localhost:9000](http://localhost:9000) and start chatting.
## WebSocket Server Implementation Recommendations
SocketRocket has been used with the following libraries:
- [Tornado](https://github.com/tornadoweb/tornado)
- Go's [WebSocket package](https://godoc.org/golang.org/x/net/websocket) or Gorilla's [version](http://www.gorillatoolkit.org/pkg/websocket).
- [Autobahn](http://autobahn.ws/testsuite/) (using its fuzzing client).
The Tornado one is dirt simple and works like a charm.
([IPython notebook](http://ipython.org/ipython-doc/dev/interactive/htmlnotebook.html) uses it too).
It's much easier to configure handlers and routes than in Autobahn/twisted.
## Contributing
Were glad youre interested in SocketRocket, and wed love to see where you take it.
Please read our [contributing guidelines](https://github.com/facebook/SocketRocket/blob/master/CONTRIBUTING.md) prior to submitting a Pull Request.
[build-status-svg]: https://img.shields.io/travis/facebook/SocketRocket/master.svg
[build-status-link]: https://travis-ci.org/facebook/SocketRocket/branches
[license-svg]: https://img.shields.io/badge/license-BSD-lightgrey.svg
[license-link]: https://github.com/facebook/SocketRocket/blob/master/LICENSE
[podspec-svg]: https://img.shields.io/cocoapods/v/SocketRocket.svg
[podspec-link]: https://cocoapods.org/pods/SocketRocket
[carthage-svg]: https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat
[carthage-link]: https://github.com/carthage/carthage
[platforms-svg]: http://img.shields.io/cocoapods/p/SocketRocket.svg?style=flat

View File

@ -0,0 +1,67 @@
//
// Copyright (c) 2016-present, Facebook, Inc.
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import <Foundation/Foundation.h>
#import <SocketRocket/SRWebSocket.h>
NS_ASSUME_NONNULL_BEGIN
#if OBJC_BOOL_IS_BOOL
struct SRDelegateAvailableMethods {
BOOL didReceiveMessage : 1;
BOOL didReceiveMessageWithString : 1;
BOOL didReceiveMessageWithData : 1;
BOOL didOpen : 1;
BOOL didFailWithError : 1;
BOOL didCloseWithCode : 1;
BOOL didReceivePing : 1;
BOOL didReceivePong : 1;
BOOL shouldConvertTextFrameToString : 1;
};
#else
struct SRDelegateAvailableMethods {
BOOL didReceiveMessage;
BOOL didReceiveMessageWithString;
BOOL didReceiveMessageWithData;
BOOL didOpen;
BOOL didFailWithError;
BOOL didCloseWithCode;
BOOL didReceivePing;
BOOL didReceivePong;
BOOL shouldConvertTextFrameToString;
};
#endif
typedef struct SRDelegateAvailableMethods SRDelegateAvailableMethods;
typedef void(^SRDelegateBlock)(id<SRWebSocketDelegate> _Nullable delegate, SRDelegateAvailableMethods availableMethods);
@interface SRDelegateController : NSObject
@property (nonatomic, weak) id<SRWebSocketDelegate> delegate;
@property (atomic, readonly) SRDelegateAvailableMethods availableDelegateMethods;
@property (nullable, nonatomic, strong) dispatch_queue_t dispatchQueue;
@property (nullable, nonatomic, strong) NSOperationQueue *operationQueue;
///--------------------------------------
#pragma mark - Perform
///--------------------------------------
- (void)performDelegateBlock:(SRDelegateBlock)block;
- (void)performDelegateQueueBlock:(dispatch_block_t)block;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,138 @@
//
// Copyright (c) 2016-present, Facebook, Inc.
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import "SRDelegateController.h"
NS_ASSUME_NONNULL_BEGIN
@interface SRDelegateController ()
@property (nonatomic, strong, readonly) dispatch_queue_t accessQueue;
@property (atomic, assign, readwrite) SRDelegateAvailableMethods availableDelegateMethods;
@end
@implementation SRDelegateController
@synthesize delegate = _delegate;
@synthesize dispatchQueue = _dispatchQueue;
@synthesize operationQueue = _operationQueue;
///--------------------------------------
#pragma mark - Init
///--------------------------------------
- (instancetype)init
{
self = [super init];
if (!self) return self;
_accessQueue = dispatch_queue_create("com.facebook.socketrocket.delegate.access", DISPATCH_QUEUE_CONCURRENT);
_dispatchQueue = dispatch_get_main_queue();
return self;
}
///--------------------------------------
#pragma mark - Accessors
///--------------------------------------
- (void)setDelegate:(id<SRWebSocketDelegate> _Nullable)delegate
{
dispatch_barrier_async(self.accessQueue, ^{
self->_delegate = delegate;
self.availableDelegateMethods = (SRDelegateAvailableMethods){
.didReceiveMessage = [delegate respondsToSelector:@selector(webSocket:didReceiveMessage:)],
.didReceiveMessageWithString = [delegate respondsToSelector:@selector(webSocket:didReceiveMessageWithString:)],
.didReceiveMessageWithData = [delegate respondsToSelector:@selector(webSocket:didReceiveMessageWithData:)],
.didOpen = [delegate respondsToSelector:@selector(webSocketDidOpen:)],
.didFailWithError = [delegate respondsToSelector:@selector(webSocket:didFailWithError:)],
.didCloseWithCode = [delegate respondsToSelector:@selector(webSocket:didCloseWithCode:reason:wasClean:)],
.didReceivePing = [delegate respondsToSelector:@selector(webSocket:didReceivePingWithData:)],
.didReceivePong = [delegate respondsToSelector:@selector(webSocket:didReceivePong:)],
.shouldConvertTextFrameToString = [delegate respondsToSelector:@selector(webSocketShouldConvertTextFrameToString:)]
};
});
}
- (id<SRWebSocketDelegate> _Nullable)delegate
{
__block id<SRWebSocketDelegate> delegate = nil;
dispatch_sync(self.accessQueue, ^{
delegate = self->_delegate;
});
return delegate;
}
- (void)setDispatchQueue:(dispatch_queue_t _Nullable)queue
{
dispatch_barrier_async(self.accessQueue, ^{
self->_dispatchQueue = queue ?: dispatch_get_main_queue();
self->_operationQueue = nil;
});
}
- (dispatch_queue_t _Nullable)dispatchQueue
{
__block dispatch_queue_t queue = nil;
dispatch_sync(self.accessQueue, ^{
queue = self->_dispatchQueue;
});
return queue;
}
- (void)setOperationQueue:(NSOperationQueue *_Nullable)queue
{
dispatch_barrier_async(self.accessQueue, ^{
self->_dispatchQueue = queue ? nil : dispatch_get_main_queue();
self->_operationQueue = queue;
});
}
- (NSOperationQueue *_Nullable)operationQueue
{
__block NSOperationQueue *queue = nil;
dispatch_sync(self.accessQueue, ^{
queue = self->_operationQueue;
});
return queue;
}
///--------------------------------------
#pragma mark - Perform
///--------------------------------------
- (void)performDelegateBlock:(SRDelegateBlock)block
{
__block __strong id<SRWebSocketDelegate> delegate = nil;
__block SRDelegateAvailableMethods availableMethods = {};
dispatch_sync(self.accessQueue, ^{
delegate = self->_delegate; // Not `OK` to go through `self`, since queue sync.
availableMethods = self.availableDelegateMethods; // `OK` to call through `self`, since no queue sync.
});
[self performDelegateQueueBlock:^{
block(delegate, availableMethods);
}];
}
- (void)performDelegateQueueBlock:(dispatch_block_t)block
{
dispatch_queue_t dispatchQueue = self.dispatchQueue;
if (dispatchQueue) {
dispatch_async(dispatchQueue, block);
} else {
[self.operationQueue addOperationWithBlock:block];
}
}
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,40 @@
//
// Copyright 2012 Square Inc.
// Portions Copyright (c) 2016-present, Facebook, Inc.
//
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import <Foundation/Foundation.h>
@class SRWebSocket; // TODO: (nlutsenko) Remove dependency on SRWebSocket here.
// Returns number of bytes consumed. Returning 0 means you didn't match.
// Sends bytes to callback handler;
typedef size_t (^stream_scanner)(NSData *collected_data);
typedef void (^data_callback)(SRWebSocket *webSocket, NSData *data);
@interface SRIOConsumer : NSObject {
stream_scanner _scanner;
data_callback _handler;
size_t _bytesNeeded;
BOOL _readToCurrentFrame;
BOOL _unmaskBytes;
}
@property (nonatomic, copy, readonly) stream_scanner consumer;
@property (nonatomic, copy, readonly) data_callback handler;
@property (nonatomic, assign) size_t bytesNeeded;
@property (nonatomic, assign, readonly) BOOL readToCurrentFrame;
@property (nonatomic, assign, readonly) BOOL unmaskBytes;
- (void)resetWithScanner:(stream_scanner)scanner
handler:(data_callback)handler
bytesNeeded:(size_t)bytesNeeded
readToCurrentFrame:(BOOL)readToCurrentFrame
unmaskBytes:(BOOL)unmaskBytes;
@end

View File

@ -0,0 +1,36 @@
//
// Copyright 2012 Square Inc.
// Portions Copyright (c) 2016-present, Facebook, Inc.
//
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import "SRIOConsumer.h"
@implementation SRIOConsumer
@synthesize bytesNeeded = _bytesNeeded;
@synthesize consumer = _scanner;
@synthesize handler = _handler;
@synthesize readToCurrentFrame = _readToCurrentFrame;
@synthesize unmaskBytes = _unmaskBytes;
- (void)resetWithScanner:(stream_scanner)scanner
handler:(data_callback)handler
bytesNeeded:(size_t)bytesNeeded
readToCurrentFrame:(BOOL)readToCurrentFrame
unmaskBytes:(BOOL)unmaskBytes
{
_scanner = [scanner copy];
_handler = [handler copy];
_bytesNeeded = bytesNeeded;
_readToCurrentFrame = readToCurrentFrame;
_unmaskBytes = unmaskBytes;
assert(_scanner || _bytesNeeded);
}
@end

View File

@ -0,0 +1,28 @@
//
// Copyright 2012 Square Inc.
// Portions Copyright (c) 2016-present, Facebook, Inc.
//
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import <Foundation/Foundation.h>
#import "SRIOConsumer.h" // TODO: (nlutsenko) Convert to @class and constants file for block types
// This class is not thread-safe, and is expected to always be run on the same queue.
@interface SRIOConsumerPool : NSObject
- (instancetype)initWithBufferCapacity:(NSUInteger)poolSize;
- (SRIOConsumer *)consumerWithScanner:(stream_scanner)scanner
handler:(data_callback)handler
bytesNeeded:(size_t)bytesNeeded
readToCurrentFrame:(BOOL)readToCurrentFrame
unmaskBytes:(BOOL)unmaskBytes;
- (void)returnConsumer:(SRIOConsumer *)consumer;
@end

View File

@ -0,0 +1,64 @@
//
// Copyright 2012 Square Inc.
// Portions Copyright (c) 2016-present, Facebook, Inc.
//
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import "SRIOConsumerPool.h"
@implementation SRIOConsumerPool {
NSUInteger _poolSize;
NSMutableArray<SRIOConsumer *> *_bufferedConsumers;
}
- (instancetype)initWithBufferCapacity:(NSUInteger)poolSize;
{
self = [super init];
if (self) {
_poolSize = poolSize;
_bufferedConsumers = [NSMutableArray arrayWithCapacity:poolSize];
}
return self;
}
- (instancetype)init
{
return [self initWithBufferCapacity:8];
}
- (SRIOConsumer *)consumerWithScanner:(stream_scanner)scanner
handler:(data_callback)handler
bytesNeeded:(size_t)bytesNeeded
readToCurrentFrame:(BOOL)readToCurrentFrame
unmaskBytes:(BOOL)unmaskBytes
{
SRIOConsumer *consumer = nil;
if (_bufferedConsumers.count) {
consumer = [_bufferedConsumers lastObject];
[_bufferedConsumers removeLastObject];
} else {
consumer = [[SRIOConsumer alloc] init];
}
[consumer resetWithScanner:scanner
handler:handler
bytesNeeded:bytesNeeded
readToCurrentFrame:readToCurrentFrame
unmaskBytes:unmaskBytes];
return consumer;
}
- (void)returnConsumer:(SRIOConsumer *)consumer;
{
if (_bufferedConsumers.count < _poolSize) {
[_bufferedConsumers addObject:consumer];
}
}
@end

View File

@ -0,0 +1,13 @@
//
// Copyright (c) 2016-present, Facebook, Inc.
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import <SocketRocket/NSRunLoop+SRWebSocket.h>
// Empty function that force links the object file for the category.
extern void import_NSRunLoop_SRWebSocket(void);

View File

@ -0,0 +1,13 @@
//
// Copyright (c) 2016-present, Facebook, Inc.
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import <SocketRocket/NSURLRequest+SRWebSocket.h>
// Empty function that force links the object file for the category.
extern void import_NSURLRequest_SRWebSocket(void);

View File

@ -0,0 +1,26 @@
//
// Copyright (c) 2016-present, Facebook, Inc.
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
typedef void(^SRProxyConnectCompletion)(NSError *_Nullable error,
NSInputStream *_Nullable readStream,
NSOutputStream *_Nullable writeStream);
@interface SRProxyConnect : NSObject
- (instancetype)initWithURL:(NSURL *)url;
- (void)openNetworkStreamWithCompletion:(SRProxyConnectCompletion)completion;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,481 @@
//
// Copyright (c) 2016-present, Facebook, Inc.
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import "SRProxyConnect.h"
#import "NSRunLoop+SRWebSocket.h"
#import "SRConstants.h"
#import "SRError.h"
#import "SRLog.h"
#import "SRURLUtilities.h"
@interface SRProxyConnect() <NSStreamDelegate>
@property (nonatomic, strong) NSURL *url;
@property (nonatomic, strong) NSInputStream *inputStream;
@property (nonatomic, strong) NSOutputStream *outputStream;
@end
@implementation SRProxyConnect
{
SRProxyConnectCompletion _completion;
NSString *_httpProxyHost;
uint32_t _httpProxyPort;
CFHTTPMessageRef _receivedHTTPHeaders;
NSString *_socksProxyHost;
uint32_t _socksProxyPort;
NSString *_socksProxyUsername;
NSString *_socksProxyPassword;
BOOL _connectionRequiresSSL;
NSMutableArray<NSData *> *_inputQueue;
dispatch_queue_t _writeQueue;
}
///--------------------------------------
#pragma mark - Init
///--------------------------------------
-(instancetype)initWithURL:(NSURL *)url
{
self = [super init];
if (!self) return self;
_url = url;
_connectionRequiresSSL = SRURLRequiresSSL(url);
_writeQueue = dispatch_queue_create("com.facebook.socketrocket.proxyconnect.write", DISPATCH_QUEUE_SERIAL);
_inputQueue = [NSMutableArray arrayWithCapacity:2];
return self;
}
- (void)dealloc
{
// If we get deallocated before the socket open finishes - we need to cleanup everything.
[self.inputStream removeFromRunLoop:[NSRunLoop SR_networkRunLoop] forMode:NSDefaultRunLoopMode];
self.inputStream.delegate = nil;
[self.inputStream close];
self.inputStream = nil;
self.outputStream.delegate = nil;
[self.outputStream close];
self.outputStream = nil;
}
///--------------------------------------
#pragma mark - Open
///--------------------------------------
- (void)openNetworkStreamWithCompletion:(SRProxyConnectCompletion)completion
{
_completion = completion;
[self _configureProxy];
}
///--------------------------------------
#pragma mark - Flow
///--------------------------------------
- (void)_didConnect
{
SRDebugLog(@"_didConnect, return streams");
if (_connectionRequiresSSL) {
if (_httpProxyHost) {
// Must set the real peer name before turning on SSL
SRDebugLog(@"proxy set peer name to real host %@", self.url.host);
[self.outputStream setProperty:self.url.host forKey:@"_kCFStreamPropertySocketPeerName"];
}
}
if (_receivedHTTPHeaders) {
CFRelease(_receivedHTTPHeaders);
_receivedHTTPHeaders = NULL;
}
NSInputStream *inputStream = self.inputStream;
NSOutputStream *outputStream = self.outputStream;
self.inputStream = nil;
self.outputStream = nil;
[inputStream removeFromRunLoop:[NSRunLoop SR_networkRunLoop] forMode:NSDefaultRunLoopMode];
inputStream.delegate = nil;
outputStream.delegate = nil;
_completion(nil, inputStream, outputStream);
}
- (void)_failWithError:(NSError *)error
{
SRDebugLog(@"_failWithError, return error");
if (!error) {
error = SRHTTPErrorWithCodeDescription(500, 2132,@"Proxy Error");
}
if (_receivedHTTPHeaders) {
CFRelease(_receivedHTTPHeaders);
_receivedHTTPHeaders = NULL;
}
self.inputStream.delegate = nil;
self.outputStream.delegate = nil;
[self.inputStream removeFromRunLoop:[NSRunLoop SR_networkRunLoop]
forMode:NSDefaultRunLoopMode];
[self.inputStream close];
[self.outputStream close];
self.inputStream = nil;
self.outputStream = nil;
_completion(error, nil, nil);
}
// get proxy setting from device setting
- (void)_configureProxy
{
SRDebugLog(@"configureProxy");
NSDictionary *proxySettings = CFBridgingRelease(CFNetworkCopySystemProxySettings());
// CFNetworkCopyProxiesForURL doesn't understand ws:// or wss://
NSURL *httpURL;
if (_connectionRequiresSSL) {
httpURL = [NSURL URLWithString:[NSString stringWithFormat:@"https://%@", _url.host]];
} else {
httpURL = [NSURL URLWithString:[NSString stringWithFormat:@"http://%@", _url.host]];
}
NSArray *proxies = CFBridgingRelease(CFNetworkCopyProxiesForURL((__bridge CFURLRef)httpURL, (__bridge CFDictionaryRef)proxySettings));
if (proxies.count == 0) {
SRDebugLog(@"configureProxy no proxies");
[self _openConnection];
return; // no proxy
}
NSDictionary *settings = [proxies objectAtIndex:0];
NSString *proxyType = settings[(NSString *)kCFProxyTypeKey];
if ([proxyType isEqualToString:(NSString *)kCFProxyTypeAutoConfigurationURL]) {
NSURL *pacURL = settings[(NSString *)kCFProxyAutoConfigurationURLKey];
if (pacURL) {
[self _fetchPAC:pacURL withProxySettings:proxySettings];
return;
}
}
if ([proxyType isEqualToString:(__bridge NSString *)kCFProxyTypeAutoConfigurationJavaScript]) {
NSString *script = settings[(__bridge NSString *)kCFProxyAutoConfigurationJavaScriptKey];
if (script) {
[self _runPACScript:script withProxySettings:proxySettings];
return;
}
}
[self _readProxySettingWithType:proxyType settings:settings];
[self _openConnection];
}
- (void)_readProxySettingWithType:(NSString *)proxyType settings:(NSDictionary *)settings
{
if ([proxyType isEqualToString:(NSString *)kCFProxyTypeHTTP] ||
[proxyType isEqualToString:(NSString *)kCFProxyTypeHTTPS]) {
_httpProxyHost = settings[(NSString *)kCFProxyHostNameKey];
NSNumber *portValue = settings[(NSString *)kCFProxyPortNumberKey];
if (portValue) {
_httpProxyPort = [portValue intValue];
}
}
if ([proxyType isEqualToString:(NSString *)kCFProxyTypeSOCKS]) {
_socksProxyHost = settings[(NSString *)kCFProxyHostNameKey];
NSNumber *portValue = settings[(NSString *)kCFProxyPortNumberKey];
if (portValue)
_socksProxyPort = [portValue intValue];
_socksProxyUsername = settings[(NSString *)kCFProxyUsernameKey];
_socksProxyPassword = settings[(NSString *)kCFProxyPasswordKey];
}
if (_httpProxyHost) {
SRDebugLog(@"Using http proxy %@:%u", _httpProxyHost, _httpProxyPort);
} else if (_socksProxyHost) {
SRDebugLog(@"Using socks proxy %@:%u", _socksProxyHost, _socksProxyPort);
} else {
SRDebugLog(@"configureProxy no proxies");
}
}
- (void)_fetchPAC:(NSURL *)PACurl withProxySettings:(NSDictionary *)proxySettings
{
SRDebugLog(@"SRWebSocket fetchPAC:%@", PACurl);
if ([PACurl isFileURL]) {
NSError *error = nil;
NSString *script = [NSString stringWithContentsOfURL:PACurl
usedEncoding:NULL
error:&error];
if (error) {
[self _openConnection];
} else {
[self _runPACScript:script withProxySettings:proxySettings];
}
return;
}
NSString *scheme = [PACurl.scheme lowercaseString];
if (![scheme isEqualToString:@"http"] && ![scheme isEqualToString:@"https"]) {
// Don't know how to read data from this URL, we'll have to give up
// We'll simply assume no proxies, and start the request as normal
[self _openConnection];
return;
}
__weak typeof(self) wself = self;
NSURLRequest *request = [NSURLRequest requestWithURL:PACurl];
NSURLSession *session = [NSURLSession sharedSession];
[[session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
__strong typeof(wself) sself = wself;
if (!error) {
NSString *script = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
[sself _runPACScript:script withProxySettings:proxySettings];
} else {
[sself _openConnection];
}
}] resume];
}
- (void)_runPACScript:(NSString *)script withProxySettings:(NSDictionary *)proxySettings
{
if (!script) {
[self _openConnection];
return;
}
SRDebugLog(@"runPACScript");
// From: http://developer.apple.com/samplecode/CFProxySupportTool/listing1.html
// Work around <rdar://problem/5530166>. This dummy call to
// CFNetworkCopyProxiesForURL initialise some state within CFNetwork
// that is required by CFNetworkCopyProxiesForAutoConfigurationScript.
CFBridgingRelease(CFNetworkCopyProxiesForURL((__bridge CFURLRef)_url, (__bridge CFDictionaryRef)proxySettings));
// Obtain the list of proxies by running the autoconfiguration script
CFErrorRef err = NULL;
// CFNetworkCopyProxiesForAutoConfigurationScript doesn't understand ws:// or wss://
NSURL *httpURL;
if (_connectionRequiresSSL)
httpURL = [NSURL URLWithString:[NSString stringWithFormat:@"https://%@", _url.host]];
else
httpURL = [NSURL URLWithString:[NSString stringWithFormat:@"http://%@", _url.host]];
NSArray *proxies = CFBridgingRelease(CFNetworkCopyProxiesForAutoConfigurationScript((__bridge CFStringRef)script,(__bridge CFURLRef)httpURL, &err));
if (!err && [proxies count] > 0) {
NSDictionary *settings = [proxies objectAtIndex:0];
NSString *proxyType = settings[(NSString *)kCFProxyTypeKey];
[self _readProxySettingWithType:proxyType settings:settings];
}
[self _openConnection];
}
- (void)_openConnection
{
[self _initializeStreams];
[self.inputStream scheduleInRunLoop:[NSRunLoop SR_networkRunLoop]
forMode:NSDefaultRunLoopMode];
//[self.outputStream scheduleInRunLoop:[NSRunLoop SR_networkRunLoop]
// forMode:NSDefaultRunLoopMode];
[self.outputStream open];
[self.inputStream open];
}
- (void)_initializeStreams
{
assert(_url.port.unsignedIntValue <= UINT32_MAX);
uint32_t port = _url.port.unsignedIntValue;
if (port == 0) {
port = (_connectionRequiresSSL ? 443 : 80);
}
NSString *host = _url.host;
if (_httpProxyHost) {
host = _httpProxyHost;
port = (_httpProxyPort ?: 80);
}
CFReadStreamRef readStream = NULL;
CFWriteStreamRef writeStream = NULL;
SRDebugLog(@"ProxyConnect connect stream to %@:%u", host, port);
CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)host, port, &readStream, &writeStream);
self.outputStream = CFBridgingRelease(writeStream);
self.inputStream = CFBridgingRelease(readStream);
if (_socksProxyHost) {
SRDebugLog(@"ProxyConnect set sock property stream to %@:%u user %@ password %@", _socksProxyHost, _socksProxyPort, _socksProxyUsername, _socksProxyPassword);
NSMutableDictionary *settings = [NSMutableDictionary dictionaryWithCapacity:4];
settings[NSStreamSOCKSProxyHostKey] = _socksProxyHost;
if (_socksProxyPort) {
settings[NSStreamSOCKSProxyPortKey] = @(_socksProxyPort);
}
if (_socksProxyUsername) {
settings[NSStreamSOCKSProxyUserKey] = _socksProxyUsername;
}
if (_socksProxyPassword) {
settings[NSStreamSOCKSProxyPasswordKey] = _socksProxyPassword;
}
[self.inputStream setProperty:settings forKey:NSStreamSOCKSProxyConfigurationKey];
[self.outputStream setProperty:settings forKey:NSStreamSOCKSProxyConfigurationKey];
}
self.inputStream.delegate = self;
self.outputStream.delegate = self;
}
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode;
{
SRDebugLog(@"stream handleEvent %u", eventCode);
switch (eventCode) {
case NSStreamEventOpenCompleted: {
if (aStream == self.inputStream) {
if (_httpProxyHost) {
[self _proxyDidConnect];
} else {
[self _didConnect];
}
}
} break;
case NSStreamEventErrorOccurred: {
[self _failWithError:aStream.streamError];
} break;
case NSStreamEventEndEncountered: {
[self _failWithError:aStream.streamError];
} break;
case NSStreamEventHasBytesAvailable: {
if (aStream == _inputStream) {
[self _processInputStream];
}
} break;
case NSStreamEventHasSpaceAvailable:
case NSStreamEventNone:
SRDebugLog(@"(default) %@", aStream);
break;
}
}
- (void)_proxyDidConnect
{
SRDebugLog(@"Proxy Connected");
uint32_t port = _url.port.unsignedIntValue;
if (port == 0) {
port = (_connectionRequiresSSL ? 443 : 80);
}
// Send HTTP CONNECT Request
NSString *connectRequestStr = [NSString stringWithFormat:@"CONNECT %@:%u HTTP/1.1\r\nHost: %@\r\nConnection: keep-alive\r\nProxy-Connection: keep-alive\r\n\r\n", _url.host, port, _url.host];
NSData *message = [connectRequestStr dataUsingEncoding:NSUTF8StringEncoding];
SRDebugLog(@"Proxy sending %@", connectRequestStr);
[self _writeData:message];
}
///handles the incoming bytes and sending them to the proper processing method
- (void)_processInputStream
{
NSMutableData *buf = [NSMutableData dataWithCapacity:SRDefaultBufferSize()];
uint8_t *buffer = buf.mutableBytes;
NSInteger length = [_inputStream read:buffer maxLength:SRDefaultBufferSize()];
if (length <= 0) {
return;
}
BOOL process = (_inputQueue.count == 0);
[_inputQueue addObject:[NSData dataWithBytes:buffer length:length]];
if (process) {
[self _dequeueInput];
}
}
// dequeue the incoming input so it is processed in order
- (void)_dequeueInput
{
while (_inputQueue.count > 0) {
NSData *data = _inputQueue.firstObject;
[_inputQueue removeObjectAtIndex:0];
// No need to process any data further, we got the full header data.
if ([self _proxyProcessHTTPResponseWithData:data]) {
break;
}
}
}
//handle checking the proxy connection status
- (BOOL)_proxyProcessHTTPResponseWithData:(NSData *)data
{
if (_receivedHTTPHeaders == NULL) {
_receivedHTTPHeaders = CFHTTPMessageCreateEmpty(NULL, NO);
}
CFHTTPMessageAppendBytes(_receivedHTTPHeaders, (const UInt8 *)data.bytes, data.length);
if (CFHTTPMessageIsHeaderComplete(_receivedHTTPHeaders)) {
SRDebugLog(@"Finished reading headers %@", CFBridgingRelease(CFHTTPMessageCopyAllHeaderFields(_receivedHTTPHeaders)));
[self _proxyHTTPHeadersDidFinish];
return YES;
}
return NO;
}
- (void)_proxyHTTPHeadersDidFinish
{
NSInteger responseCode = CFHTTPMessageGetResponseStatusCode(_receivedHTTPHeaders);
if (responseCode >= 299) {
SRDebugLog(@"Connect to Proxy Request failed with response code %d", responseCode);
NSError *error = SRHTTPErrorWithCodeDescription(responseCode, 2132,
[NSString stringWithFormat:@"Received bad response code from proxy server: %d.",
(int)responseCode]);
[self _failWithError:error];
return;
}
SRDebugLog(@"proxy connect return %d, call socket connect", responseCode);
[self _didConnect];
}
static NSTimeInterval const SRProxyConnectWriteTimeout = 5.0;
- (void)_writeData:(NSData *)data
{
const uint8_t * bytes = data.bytes;
__block NSInteger timeout = (NSInteger)(SRProxyConnectWriteTimeout * 1000000); // wait timeout before giving up
__weak typeof(self) wself = self;
dispatch_async(_writeQueue, ^{
__strong typeof(wself) sself = self;
if (!sself) {
return;
}
NSOutputStream *outStream = sself.outputStream;
if (!outStream) {
return;
}
while (![outStream hasSpaceAvailable]) {
usleep(100); //wait until the socket is ready
timeout -= 100;
if (timeout < 0) {
NSError *error = SRHTTPErrorWithCodeDescription(408, 2132, @"Proxy timeout");
[sself _failWithError:error];
} else if (outStream.streamError != nil) {
[sself _failWithError:outStream.streamError];
}
}
[outStream write:bytes maxLength:data.length];
});
}
@end

View File

@ -0,0 +1,24 @@
//
// Copyright 2012 Square Inc.
// Portions Copyright (c) 2016-present, Facebook, Inc.
//
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface SRRunLoopThread : NSThread
@property (nonatomic, strong, readonly) NSRunLoop *runLoop;
+ (instancetype)sharedThread;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,83 @@
//
// Copyright 2012 Square Inc.
// Portions Copyright (c) 2016-present, Facebook, Inc.
//
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import "SRRunLoopThread.h"
@interface SRRunLoopThread ()
{
dispatch_group_t _waitGroup;
}
@property (nonatomic, strong, readwrite) NSRunLoop *runLoop;
@end
@implementation SRRunLoopThread
+ (instancetype)sharedThread
{
static SRRunLoopThread *thread;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
thread = [[SRRunLoopThread alloc] init];
thread.name = @"com.facebook.SocketRocket.NetworkThread";
[thread start];
});
return thread;
}
- (instancetype)init
{
self = [super init];
if (self) {
_waitGroup = dispatch_group_create();
dispatch_group_enter(_waitGroup);
}
return self;
}
- (void)main
{
@autoreleasepool {
_runLoop = [NSRunLoop currentRunLoop];
dispatch_group_leave(_waitGroup);
// Add an empty run loop source to prevent runloop from spinning.
CFRunLoopSourceContext sourceCtx = {
.version = 0,
.info = NULL,
.retain = NULL,
.release = NULL,
.copyDescription = NULL,
.equal = NULL,
.hash = NULL,
.schedule = NULL,
.cancel = NULL,
.perform = NULL
};
CFRunLoopSourceRef source = CFRunLoopSourceCreate(NULL, 0, &sourceCtx);
CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopDefaultMode);
CFRelease(source);
while ([_runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]) {
}
assert(NO);
}
}
- (NSRunLoop *)runLoop;
{
dispatch_group_wait(_waitGroup, DISPATCH_TIME_FOREVER);
return _runLoop;
}
@end

View File

@ -0,0 +1,26 @@
//
// Copyright (c) 2016-present, Facebook, Inc.
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import <Foundation/Foundation.h>
typedef NS_ENUM(uint8_t, SROpCode)
{
SROpCodeTextFrame = 0x1,
SROpCodeBinaryFrame = 0x2,
// 3-7 reserved.
SROpCodeConnectionClose = 0x8,
SROpCodePing = 0x9,
SROpCodePong = 0xA,
// B-F reserved.
};
/**
Default buffer size that is used for reading/writing to streams.
*/
extern size_t SRDefaultBufferSize(void);

View File

@ -0,0 +1,19 @@
//
// Copyright (c) 2016-present, Facebook, Inc.
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import "SRConstants.h"
size_t SRDefaultBufferSize(void) {
static size_t size;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
size = getpagesize();
});
return size;
}

View File

@ -0,0 +1,27 @@
//
// Copyright (c) 2016-present, Facebook, Inc.
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import <Foundation/Foundation.h>
#import <SocketRocket/SRSecurityPolicy.h>
NS_ASSUME_NONNULL_BEGIN
/**
* NOTE: While publicly, SocketRocket does not support configuring the security policy with pinned certificates,
* it is still possible to manually construct a security policy of this class. If you do this, note that you may
* be open to MitM attacks, and we will not support any issues you may have. Dive at your own risk.
*/
@interface SRPinningSecurityPolicy : SRSecurityPolicy
- (instancetype)initWithCertificates:(NSArray *)pinnedCertificates;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,73 @@
//
// Copyright (c) 2016-present, Facebook, Inc.
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import "SRPinningSecurityPolicy.h"
#import <Foundation/Foundation.h>
#import "SRLog.h"
NS_ASSUME_NONNULL_BEGIN
@interface SRPinningSecurityPolicy ()
@property (nonatomic, copy, readonly) NSArray *pinnedCertificates;
@end
@implementation SRPinningSecurityPolicy
- (instancetype)initWithCertificates:(NSArray *)pinnedCertificates
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated"
// Do not validate certificate chain since we're pinning to specific certificates.
self = [super initWithCertificateChainValidationEnabled:NO];
#pragma clang diagnostic pop
if (!self) { return self; }
if (pinnedCertificates.count == 0) {
@throw [NSException exceptionWithName:@"Creating security policy failed."
reason:@"Must specify at least one certificate when creating a pinning policy."
userInfo:nil];
}
_pinnedCertificates = [pinnedCertificates copy];
return self;
}
- (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust forDomain:(NSString *)domain
{
SRDebugLog(@"Pinned cert count: %d", self.pinnedCertificates.count);
NSUInteger requiredCertCount = self.pinnedCertificates.count;
NSUInteger validatedCertCount = 0;
CFIndex serverCertCount = SecTrustGetCertificateCount(serverTrust);
for (CFIndex i = 0; i < serverCertCount; i++) {
SecCertificateRef cert = SecTrustGetCertificateAtIndex(serverTrust, i);
NSData *data = CFBridgingRelease(SecCertificateCopyData(cert));
for (id ref in self.pinnedCertificates) {
SecCertificateRef trustedCert = (__bridge SecCertificateRef)ref;
// TODO: (nlutsenko) Add caching, so we don't copy the data for every pinned cert all the time.
NSData *trustedCertData = CFBridgingRelease(SecCertificateCopyData(trustedCert));
if ([trustedCertData isEqualToData:data]) {
validatedCertCount++;
break;
}
}
}
return (requiredCertCount == validatedCertCount);
}
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,20 @@
//
// Copyright (c) 2016-present, Facebook, Inc.
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
extern NSError *SRErrorWithDomainCodeDescription(NSString *domain, NSInteger code, NSString *description);
extern NSError *SRErrorWithCodeDescription(NSInteger code, NSString *description);
extern NSError *SRErrorWithCodeDescriptionUnderlyingError(NSInteger code, NSString *description, NSError *underlyingError);
extern NSError *SRHTTPErrorWithCodeDescription(NSInteger httpCode, NSInteger errorCode, NSString *description);
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,42 @@
//
// Copyright (c) 2016-present, Facebook, Inc.
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import "SRError.h"
#import "SRWebSocket.h"
NS_ASSUME_NONNULL_BEGIN
NSError *SRErrorWithDomainCodeDescription(NSString *domain, NSInteger code, NSString *description)
{
return [NSError errorWithDomain:domain code:code userInfo:@{ NSLocalizedDescriptionKey: description }];
}
NSError *SRErrorWithCodeDescription(NSInteger code, NSString *description)
{
return SRErrorWithDomainCodeDescription(SRWebSocketErrorDomain, code, description);
}
NSError *SRErrorWithCodeDescriptionUnderlyingError(NSInteger code, NSString *description, NSError *underlyingError)
{
return [NSError errorWithDomain:SRWebSocketErrorDomain
code:code
userInfo:@{ NSLocalizedDescriptionKey: description,
NSUnderlyingErrorKey: underlyingError }];
}
NSError *SRHTTPErrorWithCodeDescription(NSInteger httpCode, NSInteger errorCode, NSString *description)
{
return [NSError errorWithDomain:SRWebSocketErrorDomain
code:errorCode
userInfo:@{ NSLocalizedDescriptionKey: description,
SRHTTPResponseErrorKey: @(httpCode) }];
}
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,20 @@
//
// Copyright (c) 2016-present, Facebook, Inc.
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
extern CFHTTPMessageRef SRHTTPConnectMessageCreate(NSURLRequest *request,
NSString *securityKey,
uint8_t webSocketProtocolVersion,
NSArray<NSHTTPCookie *> *_Nullable cookies,
NSArray<NSString *> *_Nullable requestedProtocols);
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,79 @@
//
// Copyright (c) 2016-present, Facebook, Inc.
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import "SRHTTPConnectMessage.h"
#import "SRURLUtilities.h"
NS_ASSUME_NONNULL_BEGIN
static NSString *_SRHTTPConnectMessageHost(NSURL *url)
{
NSString *host = url.host;
if (url.port) {
host = [host stringByAppendingFormat:@":%@", url.port];
}
return host;
}
CFHTTPMessageRef SRHTTPConnectMessageCreate(NSURLRequest *request,
NSString *securityKey,
uint8_t webSocketProtocolVersion,
NSArray<NSHTTPCookie *> *_Nullable cookies,
NSArray<NSString *> *_Nullable requestedProtocols)
{
NSURL *url = request.URL;
CFHTTPMessageRef message = CFHTTPMessageCreateRequest(NULL, CFSTR("GET"), (__bridge CFURLRef)url, kCFHTTPVersion1_1);
// Set host first so it defaults
CFHTTPMessageSetHeaderFieldValue(message, CFSTR("Host"), (__bridge CFStringRef)_SRHTTPConnectMessageHost(url));
NSMutableData *keyBytes = [[NSMutableData alloc] initWithLength:16];
int result = SecRandomCopyBytes(kSecRandomDefault, keyBytes.length, keyBytes.mutableBytes);
if (result != 0) {
//TODO: (nlutsenko) Check if there was an error.
}
// Apply cookies if any have been provided
if (cookies) {
NSDictionary<NSString *, NSString *> *messageCookies = [NSHTTPCookie requestHeaderFieldsWithCookies:cookies];
[messageCookies enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull obj, BOOL * _Nonnull stop) {
if (key.length && obj.length) {
CFHTTPMessageSetHeaderFieldValue(message, (__bridge CFStringRef)key, (__bridge CFStringRef)obj);
}
}];
}
// set header for http basic auth
NSString *basicAuthorizationString = SRBasicAuthorizationHeaderFromURL(url);
if (basicAuthorizationString) {
CFHTTPMessageSetHeaderFieldValue(message, CFSTR("Authorization"), (__bridge CFStringRef)basicAuthorizationString);
}
CFHTTPMessageSetHeaderFieldValue(message, CFSTR("Upgrade"), CFSTR("websocket"));
CFHTTPMessageSetHeaderFieldValue(message, CFSTR("Connection"), CFSTR("Upgrade"));
CFHTTPMessageSetHeaderFieldValue(message, CFSTR("Sec-WebSocket-Key"), (__bridge CFStringRef)securityKey);
CFHTTPMessageSetHeaderFieldValue(message, CFSTR("Sec-WebSocket-Version"), (__bridge CFStringRef)@(webSocketProtocolVersion).stringValue);
CFHTTPMessageSetHeaderFieldValue(message, CFSTR("Origin"), (__bridge CFStringRef)SRURLOrigin(url));
if (requestedProtocols.count) {
CFHTTPMessageSetHeaderFieldValue(message, CFSTR("Sec-WebSocket-Protocol"),
(__bridge CFStringRef)[requestedProtocols componentsJoinedByString:@", "]);
}
[request.allHTTPHeaderFields enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
CFHTTPMessageSetHeaderFieldValue(message, (__bridge CFStringRef)key, (__bridge CFStringRef)obj);
}];
return message;
}
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,19 @@
//
// Copyright (c) 2016-present, Facebook, Inc.
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
extern NSData *SRSHA1HashFromString(NSString *string);
extern NSData *SRSHA1HashFromBytes(const char *bytes, size_t length);
extern NSString *SRBase64EncodedStringFromData(NSData *data);
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,43 @@
//
// Copyright (c) 2016-present, Facebook, Inc.
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import "SRHash.h"
#import <CommonCrypto/CommonDigest.h>
NS_ASSUME_NONNULL_BEGIN
NSData *SRSHA1HashFromString(NSString *string)
{
size_t length = [string lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
return SRSHA1HashFromBytes(string.UTF8String, length);
}
NSData *SRSHA1HashFromBytes(const char *bytes, size_t length)
{
uint8_t outputLength = CC_SHA1_DIGEST_LENGTH;
unsigned char output[outputLength];
CC_SHA1(bytes, (CC_LONG)length, output);
return [NSData dataWithBytes:output length:outputLength];
}
NSString *SRBase64EncodedStringFromData(NSData *data)
{
if ([data respondsToSelector:@selector(base64EncodedStringWithOptions:)]) {
return [data base64EncodedStringWithOptions:0];
}
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
return [data base64Encoding];
#pragma clang diagnostic pop
}
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,20 @@
//
// Copyright (c) 2016-present, Facebook, Inc.
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
// Uncomment this line to enable debug logging
//#define SR_DEBUG_LOG_ENABLED
extern void SRErrorLog(NSString *format, ...);
extern void SRDebugLog(NSString *format, ...);
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,33 @@
//
// Copyright (c) 2016-present, Facebook, Inc.
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import "SRLog.h"
NS_ASSUME_NONNULL_BEGIN
extern void SRErrorLog(NSString *format, ...)
{
__block va_list arg_list;
va_start (arg_list, format);
NSString *formattedString = [[NSString alloc] initWithFormat:format arguments:arg_list];
va_end(arg_list);
NSLog(@"[SocketRocket] %@", formattedString);
}
extern void SRDebugLog(NSString *format, ...)
{
#ifdef SR_DEBUG_LOG_ENABLED
SRErrorLog(tag, format);
#endif
}
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,22 @@
//
// Copyright (c) 2016-present, Facebook, Inc.
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
typedef __attribute__((capability("mutex"))) pthread_mutex_t *SRMutex;
extern SRMutex SRMutexInitRecursive(void);
extern void SRMutexDestroy(SRMutex mutex);
extern void SRMutexLock(SRMutex mutex) __attribute__((acquire_capability(mutex)));
extern void SRMutexUnlock(SRMutex mutex) __attribute__((release_capability(mutex)));
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,47 @@
//
// Copyright (c) 2016-present, Facebook, Inc.
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import "SRMutex.h"
#import <pthread/pthread.h>
NS_ASSUME_NONNULL_BEGIN
SRMutex SRMutexInitRecursive(void)
{
pthread_mutex_t *mutex = malloc(sizeof(pthread_mutex_t));
pthread_mutexattr_t attributes;
pthread_mutexattr_init(&attributes);
pthread_mutexattr_settype(&attributes, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(mutex, &attributes);
pthread_mutexattr_destroy(&attributes);
return mutex;
}
void SRMutexDestroy(SRMutex mutex)
{
pthread_mutex_destroy(mutex);
free(mutex);
}
__attribute__((no_thread_safety_analysis))
void SRMutexLock(SRMutex mutex)
{
pthread_mutex_lock(mutex);
}
__attribute__((no_thread_safety_analysis))
void SRMutexUnlock(SRMutex mutex)
{
pthread_mutex_unlock(mutex);
}
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,16 @@
//
// Copyright (c) 2016-present, Facebook, Inc.
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
extern NSData *SRRandomData(NSUInteger length);
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,26 @@
//
// Copyright (c) 2016-present, Facebook, Inc.
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import "SRRandom.h"
#import <Security/SecRandom.h>
NS_ASSUME_NONNULL_BEGIN
NSData *SRRandomData(NSUInteger length)
{
NSMutableData *data = [NSMutableData dataWithLength:length];
int result = SecRandomCopyBytes(kSecRandomDefault, data.length, data.mutableBytes);
if (result != 0) {
[NSException raise:NSInternalInconsistencyException format:@"Failed to generate random bytes with OSStatus: %d", result];
}
return data;
}
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,19 @@
//
// Copyright (c) 2016-present, Facebook, Inc.
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import <Foundation/Foundation.h>
/**
Unmask bytes using XOR via SIMD.
@param bytes The bytes to unmask.
@param length The number of bytes to unmask.
@param maskKey The mask to XOR with MUST be of length sizeof(uint32_t).
*/
void SRMaskBytesSIMD(uint8_t *bytes, size_t length, uint8_t *maskKey);

View File

@ -0,0 +1,73 @@
//
// Copyright (c) 2016-present, Facebook, Inc.
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import "SRSIMDHelpers.h"
typedef uint8_t uint8x32_t __attribute__((vector_size(32)));
static void SRMaskBytesManual(uint8_t *bytes, size_t length, uint8_t *maskKey) {
for (size_t i = 0; i < length; i++) {
bytes[i] = bytes[i] ^ maskKey[i % sizeof(uint32_t)];
}
}
/**
Right-shift the elements of a vector, circularly.
@param vector The vector to circular shift.
@param by The number of elements to shift by.
@return A shifted vector.
*/
static uint8x32_t SRShiftVector(uint8x32_t vector, size_t by) {
uint8x32_t vectorCopy = vector;
by = by % _Alignof(uint8x32_t);
uint8_t *vectorPointer = (uint8_t *)&vector;
uint8_t *vectorCopyPointer = (uint8_t *)&vectorCopy;
memmove(vectorPointer + by, vectorPointer, sizeof(vector) - by);
memcpy(vectorPointer, vectorCopyPointer + (sizeof(vector) - by), by);
return vector;
}
void SRMaskBytesSIMD(uint8_t *bytes, size_t length, uint8_t *maskKey) {
size_t alignmentBytes = _Alignof(uint8x32_t) - ((uintptr_t)bytes % _Alignof(uint8x32_t));
if (alignmentBytes == _Alignof(uint8x32_t)) {
alignmentBytes = 0;
}
// If the number of bytes that can be processed after aligning is
// less than the number of bytes we can put into a vector,
// then there's no work to do with SIMD, just call the manual version.
if (alignmentBytes > length || (length - alignmentBytes) < sizeof(uint8x32_t)) {
SRMaskBytesManual(bytes, length, maskKey);
return;
}
size_t vectorLength = (length - alignmentBytes) / sizeof(uint8x32_t);
size_t manualStartOffset = alignmentBytes + (vectorLength * sizeof(uint8x32_t));
size_t manualLength = length - manualStartOffset;
uint8x32_t *vector = (uint8x32_t *)(bytes + alignmentBytes);
uint8x32_t maskVector = { };
memset_pattern4(&maskVector, maskKey, sizeof(uint8x32_t));
maskVector = SRShiftVector(maskVector, alignmentBytes);
SRMaskBytesManual(bytes, alignmentBytes, maskKey);
for (size_t vectorIndex = 0; vectorIndex < vectorLength; vectorIndex++) {
vector[vectorIndex] = vector[vectorIndex] ^ maskVector;
}
// Use the shifted mask for the final manual part.
SRMaskBytesManual(bytes + manualStartOffset, manualLength, (uint8_t *) &maskVector);
}

View File

@ -0,0 +1,26 @@
//
// Copyright (c) 2016-present, Facebook, Inc.
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
// The origin isn't really applicable for a native application.
// So instead, just map ws -> http and wss -> https.
extern NSString *SRURLOrigin(NSURL *url);
extern BOOL SRURLRequiresSSL(NSURL *url);
// Extracts `user` and `password` from url (if available) into `Basic base64(user:password)`.
extern NSString *_Nullable SRBasicAuthorizationHeaderFromURL(NSURL *url);
// Returns a valid value for `NSStreamNetworkServiceType` or `nil`.
extern NSString *_Nullable SRStreamNetworkServiceTypeFromURLRequest(NSURLRequest *request);
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,80 @@
//
// Copyright (c) 2016-present, Facebook, Inc.
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import "SRURLUtilities.h"
#import "SRHash.h"
NS_ASSUME_NONNULL_BEGIN
NSString *SRURLOrigin(NSURL *url)
{
NSMutableString *origin = [NSMutableString string];
NSString *scheme = url.scheme.lowercaseString;
if ([scheme isEqualToString:@"wss"]) {
scheme = @"https";
} else if ([scheme isEqualToString:@"ws"]) {
scheme = @"http";
}
[origin appendFormat:@"%@://%@", scheme, url.host];
NSNumber *port = url.port;
BOOL portIsDefault = (!port ||
([scheme isEqualToString:@"http"] && port.integerValue == 80) ||
([scheme isEqualToString:@"https"] && port.integerValue == 443));
if (!portIsDefault) {
[origin appendFormat:@":%@", port.stringValue];
}
return origin;
}
extern BOOL SRURLRequiresSSL(NSURL *url)
{
NSString *scheme = url.scheme.lowercaseString;
return ([scheme isEqualToString:@"wss"] || [scheme isEqualToString:@"https"]);
}
extern NSString *_Nullable SRBasicAuthorizationHeaderFromURL(NSURL *url)
{
NSData *data = [[NSString stringWithFormat:@"%@:%@", url.user, url.password] dataUsingEncoding:NSUTF8StringEncoding];
return [NSString stringWithFormat:@"Basic %@", SRBase64EncodedStringFromData(data)];
}
extern NSString *_Nullable SRStreamNetworkServiceTypeFromURLRequest(NSURLRequest *request)
{
NSString *networkServiceType = nil;
switch (request.networkServiceType) {
case NSURLNetworkServiceTypeDefault:
case NSURLNetworkServiceTypeResponsiveData:
case NSURLNetworkServiceTypeAVStreaming:
case NSURLNetworkServiceTypeResponsiveAV:
break;
case NSURLNetworkServiceTypeVoIP:
networkServiceType = NSStreamNetworkServiceTypeVoIP;
break;
case NSURLNetworkServiceTypeVideo:
networkServiceType = NSStreamNetworkServiceTypeVideo;
break;
case NSURLNetworkServiceTypeBackground:
networkServiceType = NSStreamNetworkServiceTypeBackground;
break;
case NSURLNetworkServiceTypeVoice:
networkServiceType = NSStreamNetworkServiceTypeVoice;
break;
case NSURLNetworkServiceTypeCallSignaling: {
if (@available(iOS 10.0, tvOS 10.0, macOS 10.12, *)) {
networkServiceType = NSStreamNetworkServiceTypeCallSignaling;
}
} break;
}
return networkServiceType;
}
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,27 @@
//
// Copyright 2012 Square Inc.
// Portions Copyright (c) 2016-present, Facebook, Inc.
//
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSRunLoop (SRWebSocket)
/**
Default run loop that will be used to schedule all instances of `SRWebSocket`.
@return An instance of `NSRunLoop`.
*/
+ (NSRunLoop *)SR_networkRunLoop;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,27 @@
//
// Copyright 2012 Square Inc.
// Portions Copyright (c) 2016-present, Facebook, Inc.
//
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import "NSRunLoop+SRWebSocket.h"
#import "NSRunLoop+SRWebSocketPrivate.h"
#import "SRRunLoopThread.h"
// Required for object file to always be linked.
void import_NSRunLoop_SRWebSocket() { }
@implementation NSRunLoop (SRWebSocket)
+ (NSRunLoop *)SR_networkRunLoop
{
return [SRRunLoopThread sharedThread].runLoop;
}
@end

View File

@ -0,0 +1,38 @@
//
// Copyright 2012 Square Inc.
// Portions Copyright (c) 2016-present, Facebook, Inc.
//
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSURLRequest (SRWebSocket)
/**
An array of pinned `SecCertificateRef` SSL certificates that `SRWebSocket` will use for validation.
*/
@property (nullable, nonatomic, copy, readonly) NSArray *SR_SSLPinnedCertificates
DEPRECATED_MSG_ATTRIBUTE("Using pinned certificates is neither secure nor supported in SocketRocket, "
"and leads to security issues. Please use a proper, trust chain validated certificate.");
@end
@interface NSMutableURLRequest (SRWebSocket)
/**
An array of pinned `SecCertificateRef` SSL certificates that `SRWebSocket` will use for validation.
*/
@property (nullable, nonatomic, copy) NSArray *SR_SSLPinnedCertificates
DEPRECATED_MSG_ATTRIBUTE("Using pinned certificates is neither secure nor supported in SocketRocket, "
"and leads to security issues. Please use a proper, trust chain validated certificate.");
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,42 @@
//
// Copyright 2012 Square Inc.
// Portions Copyright (c) 2016-present, Facebook, Inc.
//
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import "NSURLRequest+SRWebSocket.h"
#import "NSURLRequest+SRWebSocketPrivate.h"
// Required for object file to always be linked.
void import_NSURLRequest_SRWebSocket() { }
NS_ASSUME_NONNULL_BEGIN
static NSString *const SRSSLPinnnedCertificatesKey = @"SocketRocket_SSLPinnedCertificates";
@implementation NSURLRequest (SRWebSocket)
- (nullable NSArray *)SR_SSLPinnedCertificates
{
return nil;
}
@end
@implementation NSMutableURLRequest (SRWebSocket)
- (void)setSR_SSLPinnedCertificates:(nullable NSArray *)SR_SSLPinnedCertificates
{
[NSException raise:NSInvalidArgumentException
format:@"Using pinned certificates is neither secure nor supported in SocketRocket, "
"and leads to security issues. Please use a proper, trust chain validated certificate."];
}
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,72 @@
//
// Copyright (c) 2016-present, Facebook, Inc.
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import <Foundation/Foundation.h>
#import <Security/Security.h>
NS_ASSUME_NONNULL_BEGIN
@interface SRSecurityPolicy : NSObject
/**
A default `SRSecurityPolicy` implementation specifies socket security and
validates the certificate chain.
Use a subclass of `SRSecurityPolicy` for more fine grained customization.
*/
+ (instancetype)defaultPolicy;
/**
Specifies socket security and provider certificate pinning, disregarding certificate
chain validation.
@param pinnedCertificates Array of `SecCertificateRef` SSL certificates to use for validation.
*/
+ (instancetype)pinnningPolicyWithCertificates:(NSArray *)pinnedCertificates
DEPRECATED_MSG_ATTRIBUTE("Using pinned certificates is neither secure nor supported in SocketRocket, "
"and leads to security issues. Please use a proper, trust chain validated certificate.");
/**
Specifies socket security and optional certificate chain validation.
@param enabled Whether or not to validate the SSL certificate chain. If you
are considering using this method because your certificate was not issued by a
recognized certificate authority, consider using `pinningPolicyWithCertificates` instead.
*/
- (instancetype)initWithCertificateChainValidationEnabled:(BOOL)enabled
DEPRECATED_MSG_ATTRIBUTE("Disabling certificate chain validation is unsafe. "
"Please use a proper Certificate Authority to issue your TLS certificates.")
NS_DESIGNATED_INITIALIZER;
/**
Updates all the security options for input and output streams, for example you
can set your socket security level here.
@param stream Stream to update the options in.
*/
- (void)updateSecurityOptionsInStream:(NSStream *)stream;
/**
Whether or not the specified server trust should be accepted, based on the security policy.
This method should be used when responding to an authentication challenge from
a server. In the default implemenation, no further validation is done here, but
you're free to override it in a subclass. See `SRPinningSecurityPolicy.h` for
an example.
@param serverTrust The X.509 certificate trust of the server.
@param domain The domain of serverTrust.
@return Whether or not to trust the server.
*/
- (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust forDomain:(NSString *)domain;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,75 @@
//
// Copyright (c) 2016-present, Facebook, Inc.
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import "SRSecurityPolicy.h"
#import "SRPinningSecurityPolicy.h"
NS_ASSUME_NONNULL_BEGIN
@interface SRSecurityPolicy ()
@property (nonatomic, assign, readonly) BOOL certificateChainValidationEnabled;
@end
@implementation SRSecurityPolicy
+ (instancetype)defaultPolicy
{
return [self new];
}
+ (instancetype)pinnningPolicyWithCertificates:(NSArray *)pinnedCertificates
{
[NSException raise:NSInvalidArgumentException
format:@"Using pinned certificates is neither secure nor supported in SocketRocket, "
"and leads to security issues. Please use a proper, trust chain validated certificate."];
return nil;
}
- (instancetype)initWithCertificateChainValidationEnabled:(BOOL)enabled
{
self = [super init];
if (!self) { return self; }
_certificateChainValidationEnabled = enabled;
return self;
}
- (instancetype)init
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated"
return [self initWithCertificateChainValidationEnabled:YES];
#pragma clang diagnostic pop
}
- (void)updateSecurityOptionsInStream:(NSStream *)stream
{
// Enforce TLS 1.2
[stream setProperty:(__bridge id)CFSTR("kCFStreamSocketSecurityLevelTLSv1_2") forKey:(__bridge id)kCFStreamPropertySocketSecurityLevel];
// Validate certificate chain for this stream if enabled.
NSDictionary<NSString *, id> *sslOptions = @{ (__bridge NSString *)kCFStreamSSLValidatesCertificateChain : @(self.certificateChainValidationEnabled) };
[stream setProperty:sslOptions forKey:(__bridge NSString *)kCFStreamPropertySSLSettings];
}
- (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust forDomain:(NSString *)domain
{
// No further evaluation happens in the default policy.
return YES;
}
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,417 @@
//
// Copyright 2012 Square Inc.
// Portions Copyright (c) 2016-present, Facebook, Inc.
//
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSInteger, SRReadyState) {
SR_CONNECTING = 0,
SR_OPEN = 1,
SR_CLOSING = 2,
SR_CLOSED = 3,
};
typedef NS_ENUM(NSInteger, SRStatusCode) {
// 0-999: Reserved and not used.
SRStatusCodeNormal = 1000,
SRStatusCodeGoingAway = 1001,
SRStatusCodeProtocolError = 1002,
SRStatusCodeUnhandledType = 1003,
// 1004 reserved.
SRStatusNoStatusReceived = 1005,
SRStatusCodeAbnormal = 1006,
SRStatusCodeInvalidUTF8 = 1007,
SRStatusCodePolicyViolated = 1008,
SRStatusCodeMessageTooBig = 1009,
SRStatusCodeMissingExtension = 1010,
SRStatusCodeInternalError = 1011,
SRStatusCodeServiceRestart = 1012,
SRStatusCodeTryAgainLater = 1013,
// 1014: Reserved for future use by the WebSocket standard.
SRStatusCodeTLSHandshake = 1015,
// 1016-1999: Reserved for future use by the WebSocket standard.
// 2000-2999: Reserved for use by WebSocket extensions.
// 3000-3999: Available for use by libraries and frameworks. May not be used by applications. Available for registration at the IANA via first-come, first-serve.
// 4000-4999: Available for use by applications.
};
@class SRWebSocket;
@class SRSecurityPolicy;
/**
Error domain used for errors reported by SRWebSocket.
*/
extern NSString *const SRWebSocketErrorDomain;
/**
Key used for HTTP status code if bad response was received from the server.
*/
extern NSString *const SRHTTPResponseErrorKey;
@protocol SRWebSocketDelegate;
///--------------------------------------
#pragma mark - SRWebSocket
///--------------------------------------
/**
A `SRWebSocket` object lets you connect, send and receive data to a remote Web Socket.
*/
@interface SRWebSocket : NSObject <NSStreamDelegate>
/**
The delegate of the web socket.
The web socket delegate is notified on all state changes that happen to the web socket.
*/
@property (nonatomic, weak) id <SRWebSocketDelegate> delegate;
/**
A dispatch queue for scheduling the delegate calls. The queue doesn't need be a serial queue.
If `nil` and `delegateOperationQueue` is `nil`, the socket uses main queue for performing all delegate method calls.
*/
@property (nullable, nonatomic, strong) dispatch_queue_t delegateDispatchQueue;
/**
An operation queue for scheduling the delegate calls.
If `nil` and `delegateOperationQueue` is `nil`, the socket uses main queue for performing all delegate method calls.
*/
@property (nullable, nonatomic, strong) NSOperationQueue *delegateOperationQueue;
/**
Current ready state of the socket. Default: `SR_CONNECTING`.
This property is Key-Value Observable and fully thread-safe.
*/
@property (atomic, assign, readonly) SRReadyState readyState;
/**
An instance of `NSURL` that this socket connects to.
*/
@property (nullable, nonatomic, strong, readonly) NSURL *url;
/**
All HTTP headers that were received by socket or `nil` if none were received so far.
*/
@property (nullable, nonatomic, assign, readonly) CFHTTPMessageRef receivedHTTPHeaders;
/**
Array of `NSHTTPCookie` cookies to apply to the connection.
*/
@property (nullable, nonatomic, copy) NSArray<NSHTTPCookie *> *requestCookies;
/**
The negotiated web socket protocol or `nil` if handshake did not yet complete.
*/
@property (nullable, nonatomic, copy, readonly) NSString *protocol;
/**
A boolean value indicating whether this socket will allow connection without SSL trust chain evaluation.
For DEBUG builds this flag is ignored, and SSL connections are allowed regardless of the certificate trust configuration
*/
@property (nonatomic, assign, readonly) BOOL allowsUntrustedSSLCertificates;
///--------------------------------------
#pragma mark - Constructors
///--------------------------------------
/**
Initializes a web socket with a given `NSURLRequest`.
@param request Request to initialize with.
*/
- (instancetype)initWithURLRequest:(NSURLRequest *)request;
/**
Initializes a web socket with a given `NSURLRequest`, specifying a transport security policy (e.g. SSL configuration).
@param request Request to initialize with.
@param securityPolicy Policy object describing transport security behavior.
*/
- (instancetype)initWithURLRequest:(NSURLRequest *)request securityPolicy:(SRSecurityPolicy *)securityPolicy;
/**
Initializes a web socket with a given `NSURLRequest` and list of sub-protocols.
@param request Request to initialize with.
@param protocols An array of strings that turn into `Sec-WebSocket-Protocol`. Default: `nil`.
*/
- (instancetype)initWithURLRequest:(NSURLRequest *)request protocols:(nullable NSArray<NSString *> *)protocols;
/**
Initializes a web socket with a given `NSURLRequest`, list of sub-protocols and whether untrusted SSL certificates are allowed.
@param request Request to initialize with.
@param protocols An array of strings that turn into `Sec-WebSocket-Protocol`. Default: `nil`.
@param allowsUntrustedSSLCertificates Boolean value indicating whether untrusted SSL certificates are allowed. Default: `false`.
*/
- (instancetype)initWithURLRequest:(NSURLRequest *)request protocols:(nullable NSArray<NSString *> *)protocols allowsUntrustedSSLCertificates:(BOOL)allowsUntrustedSSLCertificates
DEPRECATED_MSG_ATTRIBUTE("Disabling certificate chain validation is unsafe. "
"Please use a proper Certificate Authority to issue your TLS certificates.");
/**
Initializes a web socket with a given `NSURLRequest`, list of sub-protocols and whether untrusted SSL certificates are allowed.
@param request Request to initialize with.
@param protocols An array of strings that turn into `Sec-WebSocket-Protocol`. Default: `nil`.
@param securityPolicy Policy object describing transport security behavior.
*/
- (instancetype)initWithURLRequest:(NSURLRequest *)request protocols:(nullable NSArray<NSString *> *)protocols securityPolicy:(SRSecurityPolicy *)securityPolicy NS_DESIGNATED_INITIALIZER;
/**
Initializes a web socket with a given `NSURL`.
@param url URL to initialize with.
*/
- (instancetype)initWithURL:(NSURL *)url;
/**
Initializes a web socket with a given `NSURL` and list of sub-protocols.
@param url URL to initialize with.
@param protocols An array of strings that turn into `Sec-WebSocket-Protocol`. Default: `nil`.
*/
- (instancetype)initWithURL:(NSURL *)url protocols:(nullable NSArray<NSString *> *)protocols;
/**
Initializes a web socket with a given `NSURL`, specifying a transport security policy (e.g. SSL configuration).
@param url URL to initialize with.
@param securityPolicy Policy object describing transport security behavior.
*/
- (instancetype)initWithURL:(NSURL *)url securityPolicy:(SRSecurityPolicy *)securityPolicy;
/**
Initializes a web socket with a given `NSURL`, list of sub-protocols and whether untrusted SSL certificates are allowed.
@param url URL to initialize with.
@param protocols An array of strings that turn into `Sec-WebSocket-Protocol`. Default: `nil`.
@param allowsUntrustedSSLCertificates Boolean value indicating whether untrusted SSL certificates are allowed. Default: `false`.
*/
- (instancetype)initWithURL:(NSURL *)url protocols:(nullable NSArray<NSString *> *)protocols allowsUntrustedSSLCertificates:(BOOL)allowsUntrustedSSLCertificates
DEPRECATED_MSG_ATTRIBUTE("Disabling certificate chain validation is unsafe. "
"Please use a proper Certificate Authority to issue your TLS certificates.");
/**
Unavailable initializer. Please use any other initializer.
*/
- (instancetype)init NS_UNAVAILABLE;
/**
Unavailable constructor. Please use any other initializer.
*/
+ (instancetype)new NS_UNAVAILABLE;
///--------------------------------------
#pragma mark - Schedule
///--------------------------------------
/**
Schedules a received on a given run loop in a given mode.
By default, a web socket will schedule itself on `+[NSRunLoop SR_networkRunLoop]` using `NSDefaultRunLoopMode`.
@param runLoop The run loop on which to schedule the receiver.
@param mode The mode for the run loop.
*/
- (void)scheduleInRunLoop:(NSRunLoop *)runLoop forMode:(NSString *)mode NS_SWIFT_NAME(schedule(in:forMode:));
/**
Removes the receiver from a given run loop running in a given mode.
@param runLoop The run loop on which the receiver was scheduled.
@param mode The mode for the run loop.
*/
- (void)unscheduleFromRunLoop:(NSRunLoop *)runLoop forMode:(NSString *)mode NS_SWIFT_NAME(unschedule(from:forMode:));
///--------------------------------------
#pragma mark - Open / Close
///--------------------------------------
/**
Opens web socket, which will trigger connection, authentication and start receiving/sending events.
An instance of `SRWebSocket` is intended for one-time-use only. This method should be called once and only once.
*/
- (void)open;
/**
Closes a web socket using `SRStatusCodeNormal` code and no reason.
*/
- (void)close;
/**
Closes a web socket using a given code and reason.
@param code Code to close the socket with.
@param reason Reason to send to the server or `nil`.
*/
- (void)closeWithCode:(NSInteger)code reason:(nullable NSString *)reason;
///--------------------------------------
#pragma mark Send
///--------------------------------------
/**
Send a UTF-8 string or binary data to the server.
@param message UTF-8 String or Data to send.
@deprecated Please use `sendString:` or `sendData` instead.
*/
- (void)send:(nullable id)message __attribute__((deprecated("Please use `sendString:error:` or `sendData:error:` instead.")));
/**
Send a UTF-8 String to the server.
@param string String to send.
@param error On input, a pointer to variable for an `NSError` object.
If an error occurs, this pointer is set to an `NSError` object containing information about the error.
You may specify `nil` to ignore the error information.
@return `YES` if the string was scheduled to send, otherwise - `NO`.
*/
- (BOOL)sendString:(NSString *)string error:(NSError **)error NS_SWIFT_NAME(send(string:));
/**
Send binary data to the server.
@param data Data to send.
@param error On input, a pointer to variable for an `NSError` object.
If an error occurs, this pointer is set to an `NSError` object containing information about the error.
You may specify `nil` to ignore the error information.
@return `YES` if the string was scheduled to send, otherwise - `NO`.
*/
- (BOOL)sendData:(nullable NSData *)data error:(NSError **)error NS_SWIFT_NAME(send(data:));
/**
Send binary data to the server, without making a defensive copy of it first.
@param data Data to send.
@param error On input, a pointer to variable for an `NSError` object.
If an error occurs, this pointer is set to an `NSError` object containing information about the error.
You may specify `nil` to ignore the error information.
@return `YES` if the string was scheduled to send, otherwise - `NO`.
*/
- (BOOL)sendDataNoCopy:(nullable NSData *)data error:(NSError **)error NS_SWIFT_NAME(send(dataNoCopy:));
/**
Send Ping message to the server with optional data.
@param data Instance of `NSData` or `nil`.
@param error On input, a pointer to variable for an `NSError` object.
If an error occurs, this pointer is set to an `NSError` object containing information about the error.
You may specify `nil` to ignore the error information.
@return `YES` if the string was scheduled to send, otherwise - `NO`.
*/
- (BOOL)sendPing:(nullable NSData *)data error:(NSError **)error NS_SWIFT_NAME(sendPing(_:));
@end
///--------------------------------------
#pragma mark - SRWebSocketDelegate
///--------------------------------------
/**
The `SRWebSocketDelegate` protocol describes the methods that `SRWebSocket` objects
call on their delegates to handle status and messsage events.
*/
@protocol SRWebSocketDelegate <NSObject>
@optional
#pragma mark Receive Messages
/**
Called when any message was received from a web socket.
This method is suboptimal and might be deprecated in a future release.
@param webSocket An instance of `SRWebSocket` that received a message.
@param message Received message. Either a `String` or `NSData`.
*/
- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message;
/**
Called when a frame was received from a web socket.
@param webSocket An instance of `SRWebSocket` that received a message.
@param string Received text in a form of UTF-8 `String`.
*/
- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessageWithString:(NSString *)string;
/**
Called when a frame was received from a web socket.
@param webSocket An instance of `SRWebSocket` that received a message.
@param data Received data in a form of `NSData`.
*/
- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessageWithData:(NSData *)data;
#pragma mark Status & Connection
/**
Called when a given web socket was open and authenticated.
@param webSocket An instance of `SRWebSocket` that was open.
*/
- (void)webSocketDidOpen:(SRWebSocket *)webSocket;
/**
Called when a given web socket encountered an error.
@param webSocket An instance of `SRWebSocket` that failed with an error.
@param error An instance of `NSError`.
*/
- (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error;
/**
Called when a given web socket was closed.
@param webSocket An instance of `SRWebSocket` that was closed.
@param code Code reported by the server.
@param reason Reason in a form of a String that was reported by the server or `nil`.
@param wasClean Boolean value indicating whether a socket was closed in a clean state.
*/
- (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(nullable NSString *)reason wasClean:(BOOL)wasClean;
/**
Called on receive of a ping message from the server.
@param webSocket An instance of `SRWebSocket` that received a ping frame.
@param data Payload that was received or `nil` if there was no payload.
*/
- (void)webSocket:(SRWebSocket *)webSocket didReceivePingWithData:(nullable NSData *)data;
/**
Called when a pong data was received in response to ping.
@param webSocket An instance of `SRWebSocket` that received a pong frame.
@param pongData Payload that was received or `nil` if there was no payload.
*/
- (void)webSocket:(SRWebSocket *)webSocket didReceivePong:(nullable NSData *)pongData;
/**
Sent before reporting a text frame to be able to configure if it shuold be convert to a UTF-8 String or passed as `NSData`.
If the method is not implemented - it will always convert text frames to String.
@param webSocket An instance of `SRWebSocket` that received a text frame.
@return `YES` if text frame should be converted to UTF-8 String, otherwise - `NO`. Default: `YES`.
*/
- (BOOL)webSocketShouldConvertTextFrameToString:(SRWebSocket *)webSocket NS_SWIFT_NAME(webSocketShouldConvertTextFrameToString(_:));
@end
NS_ASSUME_NONNULL_END

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,15 @@
//
// Copyright 2012 Square Inc.
// Portions Copyright (c) 2016-present, Facebook, Inc.
//
// All rights reserved.
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.
//
#import <SocketRocket/NSRunLoop+SRWebSocket.h>
#import <SocketRocket/NSURLRequest+SRWebSocket.h>
#import <SocketRocket/SRSecurityPolicy.h>
#import <SocketRocket/SRWebSocket.h>

View File

@ -761,6 +761,39 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
## SocketRocket
BSD License
For SocketRocket software
Copyright (c) 2016-present, Facebook, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name Facebook nor the names of its contributors may be used to
endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
## UITableView+FDTemplateLayoutCell
The MIT License (MIT)

View File

@ -886,6 +886,45 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>BSD License
For SocketRocket software
Copyright (c) 2016-present, Facebook, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name Facebook nor the names of its contributors may be used to
endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</string>
<key>License</key>
<string>BSD</string>
<key>Title</key>
<string>SocketRocket</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>The MIT License (MIT)

View File

@ -14,6 +14,7 @@ ${BUILT_PRODUCTS_DIR}/SDAutoLayout/SDAutoLayout.framework
${BUILT_PRODUCTS_DIR}/SDCycleScrollView/SDCycleScrollView.framework
${BUILT_PRODUCTS_DIR}/SDWebImage/SDWebImage.framework
${BUILT_PRODUCTS_DIR}/SSZipArchive/SSZipArchive.framework
${BUILT_PRODUCTS_DIR}/SocketRocket/SocketRocket.framework
${BUILT_PRODUCTS_DIR}/UITableView+FDTemplateLayoutCell/UITableView_FDTemplateLayoutCell.framework
${BUILT_PRODUCTS_DIR}/YYModel/YYModel.framework
${BUILT_PRODUCTS_DIR}/YYText/YYText.framework

View File

@ -13,6 +13,7 @@ ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDAutoLayout.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDCycleScrollView.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImage.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SSZipArchive.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SocketRocket.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/UITableView_FDTemplateLayoutCell.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YYModel.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YYText.framework

View File

@ -14,6 +14,7 @@ ${BUILT_PRODUCTS_DIR}/SDAutoLayout/SDAutoLayout.framework
${BUILT_PRODUCTS_DIR}/SDCycleScrollView/SDCycleScrollView.framework
${BUILT_PRODUCTS_DIR}/SDWebImage/SDWebImage.framework
${BUILT_PRODUCTS_DIR}/SSZipArchive/SSZipArchive.framework
${BUILT_PRODUCTS_DIR}/SocketRocket/SocketRocket.framework
${BUILT_PRODUCTS_DIR}/UITableView+FDTemplateLayoutCell/UITableView_FDTemplateLayoutCell.framework
${BUILT_PRODUCTS_DIR}/YYModel/YYModel.framework
${BUILT_PRODUCTS_DIR}/YYText/YYText.framework

View File

@ -13,6 +13,7 @@ ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDAutoLayout.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDCycleScrollView.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImage.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SSZipArchive.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SocketRocket.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/UITableView_FDTemplateLayoutCell.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YYModel.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YYText.framework

View File

@ -191,6 +191,7 @@ if [[ "$CONFIGURATION" == "Debug" ]]; then
install_framework "${BUILT_PRODUCTS_DIR}/SDCycleScrollView/SDCycleScrollView.framework"
install_framework "${BUILT_PRODUCTS_DIR}/SDWebImage/SDWebImage.framework"
install_framework "${BUILT_PRODUCTS_DIR}/SSZipArchive/SSZipArchive.framework"
install_framework "${BUILT_PRODUCTS_DIR}/SocketRocket/SocketRocket.framework"
install_framework "${BUILT_PRODUCTS_DIR}/UITableView+FDTemplateLayoutCell/UITableView_FDTemplateLayoutCell.framework"
install_framework "${BUILT_PRODUCTS_DIR}/YYModel/YYModel.framework"
install_framework "${BUILT_PRODUCTS_DIR}/YYText/YYText.framework"
@ -212,6 +213,7 @@ if [[ "$CONFIGURATION" == "Release" ]]; then
install_framework "${BUILT_PRODUCTS_DIR}/SDCycleScrollView/SDCycleScrollView.framework"
install_framework "${BUILT_PRODUCTS_DIR}/SDWebImage/SDWebImage.framework"
install_framework "${BUILT_PRODUCTS_DIR}/SSZipArchive/SSZipArchive.framework"
install_framework "${BUILT_PRODUCTS_DIR}/SocketRocket/SocketRocket.framework"
install_framework "${BUILT_PRODUCTS_DIR}/UITableView+FDTemplateLayoutCell/UITableView_FDTemplateLayoutCell.framework"
install_framework "${BUILT_PRODUCTS_DIR}/YYModel/YYModel.framework"
install_framework "${BUILT_PRODUCTS_DIR}/YYText/YYText.framework"

View File

@ -1,12 +1,12 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES
EXCLUDED_ARCHS[sdk=iphonesimulator*] = arm64
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet" "${PODS_CONFIGURATION_BUILD_DIR}/HXPhotoPicker" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardManager" "${PODS_CONFIGURATION_BUILD_DIR}/LSTTimer" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/MOFSPickerManager" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/PopupKit" "${PODS_CONFIGURATION_BUILD_DIR}/Reachability" "${PODS_CONFIGURATION_BUILD_DIR}/SDAutoLayout" "${PODS_CONFIGURATION_BUILD_DIR}/SDCycleScrollView" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage" "${PODS_CONFIGURATION_BUILD_DIR}/SSZipArchive" "${PODS_CONFIGURATION_BUILD_DIR}/UITableView+FDTemplateLayoutCell" "${PODS_CONFIGURATION_BUILD_DIR}/YYModel" "${PODS_CONFIGURATION_BUILD_DIR}/YYText" "${PODS_ROOT}/GTCommonSDK" "${PODS_ROOT}/GTExtensionSDK" "${PODS_ROOT}/GTSDK" "${PODS_ROOT}/GYSDK" "${PODS_ROOT}/UMAPM/UMAPM_1.9.3" "${PODS_ROOT}/UMCCommonLog/UMCommonLog" "${PODS_ROOT}/UMCommon/UMCommon_7.4.7" "${PODS_ROOT}/UMDevice/UMDevice_3.4.0" "${PODS_ROOT}/UMLink" "${PODS_ROOT}/ZXSDK" "${PODS_ROOT}/libpag/framework" "${PODS_XCFRAMEWORKS_BUILD_DIR}/GTCommonSDK" "${PODS_XCFRAMEWORKS_BUILD_DIR}/GTExtensionSDK" "${PODS_XCFRAMEWORKS_BUILD_DIR}/GTSDK" "${PODS_XCFRAMEWORKS_BUILD_DIR}/UMAPM" "${PODS_XCFRAMEWORKS_BUILD_DIR}/UMCommon" "${PODS_XCFRAMEWORKS_BUILD_DIR}/UMDevice" "${PODS_XCFRAMEWORKS_BUILD_DIR}/libpag"
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet" "${PODS_CONFIGURATION_BUILD_DIR}/HXPhotoPicker" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardManager" "${PODS_CONFIGURATION_BUILD_DIR}/LSTTimer" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/MOFSPickerManager" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/PopupKit" "${PODS_CONFIGURATION_BUILD_DIR}/Reachability" "${PODS_CONFIGURATION_BUILD_DIR}/SDAutoLayout" "${PODS_CONFIGURATION_BUILD_DIR}/SDCycleScrollView" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage" "${PODS_CONFIGURATION_BUILD_DIR}/SSZipArchive" "${PODS_CONFIGURATION_BUILD_DIR}/SocketRocket" "${PODS_CONFIGURATION_BUILD_DIR}/UITableView+FDTemplateLayoutCell" "${PODS_CONFIGURATION_BUILD_DIR}/YYModel" "${PODS_CONFIGURATION_BUILD_DIR}/YYText" "${PODS_ROOT}/GTCommonSDK" "${PODS_ROOT}/GTExtensionSDK" "${PODS_ROOT}/GTSDK" "${PODS_ROOT}/GYSDK" "${PODS_ROOT}/UMAPM/UMAPM_1.9.3" "${PODS_ROOT}/UMCCommonLog/UMCommonLog" "${PODS_ROOT}/UMCommon/UMCommon_7.4.7" "${PODS_ROOT}/UMDevice/UMDevice_3.4.0" "${PODS_ROOT}/UMLink" "${PODS_ROOT}/ZXSDK" "${PODS_ROOT}/libpag/framework" "${PODS_XCFRAMEWORKS_BUILD_DIR}/GTCommonSDK" "${PODS_XCFRAMEWORKS_BUILD_DIR}/GTExtensionSDK" "${PODS_XCFRAMEWORKS_BUILD_DIR}/GTSDK" "${PODS_XCFRAMEWORKS_BUILD_DIR}/UMAPM" "${PODS_XCFRAMEWORKS_BUILD_DIR}/UMCommon" "${PODS_XCFRAMEWORKS_BUILD_DIR}/UMDevice" "${PODS_XCFRAMEWORKS_BUILD_DIR}/libpag"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking/AFNetworking.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet/DZNEmptyDataSet.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/HXPhotoPicker/HXPhotoPicker.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardManager/IQKeyboardManager.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/LSTTimer/LSTTimer.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD/MBProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MOFSPickerManager/MOFSPickerManager.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/PopupKit/PopupKit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Reachability/Reachability.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SDAutoLayout/SDAutoLayout.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SDCycleScrollView/SDCycleScrollView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage/SDWebImage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SSZipArchive/SSZipArchive.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/UITableView+FDTemplateLayoutCell/UITableView_FDTemplateLayoutCell.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YYModel/YYModel.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YYText/YYText.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/WechatOpenSDK"
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking/AFNetworking.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet/DZNEmptyDataSet.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/HXPhotoPicker/HXPhotoPicker.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardManager/IQKeyboardManager.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/LSTTimer/LSTTimer.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD/MBProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MOFSPickerManager/MOFSPickerManager.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/PopupKit/PopupKit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Reachability/Reachability.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SDAutoLayout/SDAutoLayout.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SDCycleScrollView/SDCycleScrollView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage/SDWebImage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SSZipArchive/SSZipArchive.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SocketRocket/SocketRocket.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/UITableView+FDTemplateLayoutCell/UITableView_FDTemplateLayoutCell.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YYModel/YYModel.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YYText/YYText.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/WechatOpenSDK"
LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks'
LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/WechatOpenSDK/OpenSDK2.0.4" "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift
OTHER_LDFLAGS = $(inherited) -ObjC -l"WechatOpenSDK" -l"c++" -l"iconv" -l"resolv" -l"sqlite3" -l"sqlite3.0" -l"z" -framework "AFNetworking" -framework "AVFoundation" -framework "Accelerate" -framework "AdSupport" -framework "CFNetwork" -framework "CoreFoundation" -framework "CoreGraphics" -framework "CoreLocation" -framework "CoreMedia" -framework "CoreTelephony" -framework "CoreText" -framework "DZNEmptyDataSet" -framework "Foundation" -framework "GTCommonSDK" -framework "GTExtensionSDK" -framework "GTSDK" -framework "GeYanSdk" -framework "HXPhotoPicker" -framework "IQKeyboardManager" -framework "ImageIO" -framework "LSTTimer" -framework "MBProgressHUD" -framework "MJRefresh" -framework "MOFSPickerManager" -framework "Masonry" -framework "MobileCoreServices" -framework "Photos" -framework "PhotosUI" -framework "PopupKit" -framework "QuartzCore" -framework "Reachability" -framework "SDAutoLayout" -framework "SDCycleScrollView" -framework "SDWebImage" -framework "SSZipArchive" -framework "Security" -framework "SystemConfiguration" -framework "UIKit" -framework "UITableView_FDTemplateLayoutCell" -framework "UMAPM" -framework "UMCommon" -framework "UMCommonLog" -framework "UMDevice" -framework "UMLink" -framework "VideoToolbox" -framework "WebKit" -framework "YYModel" -framework "YYText" -framework "ZXSDK" -framework "libpag" -weak_framework "AppTrackingTransparency" -weak_framework "Network" -weak_framework "UserNotifications"
OTHER_LDFLAGS = $(inherited) -ObjC -l"WechatOpenSDK" -l"c++" -l"iconv" -l"icucore" -l"resolv" -l"sqlite3" -l"sqlite3.0" -l"z" -framework "AFNetworking" -framework "AVFoundation" -framework "Accelerate" -framework "AdSupport" -framework "CFNetwork" -framework "CoreFoundation" -framework "CoreGraphics" -framework "CoreLocation" -framework "CoreMedia" -framework "CoreTelephony" -framework "CoreText" -framework "DZNEmptyDataSet" -framework "Foundation" -framework "GTCommonSDK" -framework "GTExtensionSDK" -framework "GTSDK" -framework "GeYanSdk" -framework "HXPhotoPicker" -framework "IQKeyboardManager" -framework "ImageIO" -framework "LSTTimer" -framework "MBProgressHUD" -framework "MJRefresh" -framework "MOFSPickerManager" -framework "Masonry" -framework "MobileCoreServices" -framework "Photos" -framework "PhotosUI" -framework "PopupKit" -framework "QuartzCore" -framework "Reachability" -framework "SDAutoLayout" -framework "SDCycleScrollView" -framework "SDWebImage" -framework "SSZipArchive" -framework "Security" -framework "SocketRocket" -framework "SystemConfiguration" -framework "UIKit" -framework "UITableView_FDTemplateLayoutCell" -framework "UMAPM" -framework "UMCommon" -framework "UMCommonLog" -framework "UMDevice" -framework "UMLink" -framework "VideoToolbox" -framework "WebKit" -framework "YYModel" -framework "YYText" -framework "ZXSDK" -framework "libpag" -weak_framework "AppTrackingTransparency" -weak_framework "Network" -weak_framework "UserNotifications"
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)

View File

@ -1,12 +1,12 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES
EXCLUDED_ARCHS[sdk=iphonesimulator*] = arm64
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet" "${PODS_CONFIGURATION_BUILD_DIR}/HXPhotoPicker" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardManager" "${PODS_CONFIGURATION_BUILD_DIR}/LSTTimer" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/MOFSPickerManager" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/PopupKit" "${PODS_CONFIGURATION_BUILD_DIR}/Reachability" "${PODS_CONFIGURATION_BUILD_DIR}/SDAutoLayout" "${PODS_CONFIGURATION_BUILD_DIR}/SDCycleScrollView" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage" "${PODS_CONFIGURATION_BUILD_DIR}/SSZipArchive" "${PODS_CONFIGURATION_BUILD_DIR}/UITableView+FDTemplateLayoutCell" "${PODS_CONFIGURATION_BUILD_DIR}/YYModel" "${PODS_CONFIGURATION_BUILD_DIR}/YYText" "${PODS_ROOT}/GTCommonSDK" "${PODS_ROOT}/GTExtensionSDK" "${PODS_ROOT}/GTSDK" "${PODS_ROOT}/GYSDK" "${PODS_ROOT}/UMAPM/UMAPM_1.9.3" "${PODS_ROOT}/UMCCommonLog/UMCommonLog" "${PODS_ROOT}/UMCommon/UMCommon_7.4.7" "${PODS_ROOT}/UMDevice/UMDevice_3.4.0" "${PODS_ROOT}/UMLink" "${PODS_ROOT}/ZXSDK" "${PODS_ROOT}/libpag/framework" "${PODS_XCFRAMEWORKS_BUILD_DIR}/GTCommonSDK" "${PODS_XCFRAMEWORKS_BUILD_DIR}/GTExtensionSDK" "${PODS_XCFRAMEWORKS_BUILD_DIR}/GTSDK" "${PODS_XCFRAMEWORKS_BUILD_DIR}/UMAPM" "${PODS_XCFRAMEWORKS_BUILD_DIR}/UMCommon" "${PODS_XCFRAMEWORKS_BUILD_DIR}/UMDevice" "${PODS_XCFRAMEWORKS_BUILD_DIR}/libpag"
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet" "${PODS_CONFIGURATION_BUILD_DIR}/HXPhotoPicker" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardManager" "${PODS_CONFIGURATION_BUILD_DIR}/LSTTimer" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/MOFSPickerManager" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/PopupKit" "${PODS_CONFIGURATION_BUILD_DIR}/Reachability" "${PODS_CONFIGURATION_BUILD_DIR}/SDAutoLayout" "${PODS_CONFIGURATION_BUILD_DIR}/SDCycleScrollView" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage" "${PODS_CONFIGURATION_BUILD_DIR}/SSZipArchive" "${PODS_CONFIGURATION_BUILD_DIR}/SocketRocket" "${PODS_CONFIGURATION_BUILD_DIR}/UITableView+FDTemplateLayoutCell" "${PODS_CONFIGURATION_BUILD_DIR}/YYModel" "${PODS_CONFIGURATION_BUILD_DIR}/YYText" "${PODS_ROOT}/GTCommonSDK" "${PODS_ROOT}/GTExtensionSDK" "${PODS_ROOT}/GTSDK" "${PODS_ROOT}/GYSDK" "${PODS_ROOT}/UMAPM/UMAPM_1.9.3" "${PODS_ROOT}/UMCCommonLog/UMCommonLog" "${PODS_ROOT}/UMCommon/UMCommon_7.4.7" "${PODS_ROOT}/UMDevice/UMDevice_3.4.0" "${PODS_ROOT}/UMLink" "${PODS_ROOT}/ZXSDK" "${PODS_ROOT}/libpag/framework" "${PODS_XCFRAMEWORKS_BUILD_DIR}/GTCommonSDK" "${PODS_XCFRAMEWORKS_BUILD_DIR}/GTExtensionSDK" "${PODS_XCFRAMEWORKS_BUILD_DIR}/GTSDK" "${PODS_XCFRAMEWORKS_BUILD_DIR}/UMAPM" "${PODS_XCFRAMEWORKS_BUILD_DIR}/UMCommon" "${PODS_XCFRAMEWORKS_BUILD_DIR}/UMDevice" "${PODS_XCFRAMEWORKS_BUILD_DIR}/libpag"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking/AFNetworking.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet/DZNEmptyDataSet.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/HXPhotoPicker/HXPhotoPicker.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardManager/IQKeyboardManager.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/LSTTimer/LSTTimer.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD/MBProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MOFSPickerManager/MOFSPickerManager.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/PopupKit/PopupKit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Reachability/Reachability.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SDAutoLayout/SDAutoLayout.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SDCycleScrollView/SDCycleScrollView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage/SDWebImage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SSZipArchive/SSZipArchive.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/UITableView+FDTemplateLayoutCell/UITableView_FDTemplateLayoutCell.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YYModel/YYModel.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YYText/YYText.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/WechatOpenSDK"
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking/AFNetworking.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DZNEmptyDataSet/DZNEmptyDataSet.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/HXPhotoPicker/HXPhotoPicker.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/IQKeyboardManager/IQKeyboardManager.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/LSTTimer/LSTTimer.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MBProgressHUD/MBProgressHUD.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MOFSPickerManager/MOFSPickerManager.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/PopupKit/PopupKit.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Reachability/Reachability.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SDAutoLayout/SDAutoLayout.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SDCycleScrollView/SDCycleScrollView.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage/SDWebImage.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SSZipArchive/SSZipArchive.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SocketRocket/SocketRocket.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/UITableView+FDTemplateLayoutCell/UITableView_FDTemplateLayoutCell.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YYModel/YYModel.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YYText/YYText.framework/Headers" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/WechatOpenSDK"
LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks'
LIBRARY_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/WechatOpenSDK/OpenSDK2.0.4" "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift
OTHER_LDFLAGS = $(inherited) -ObjC -l"WechatOpenSDK" -l"c++" -l"iconv" -l"resolv" -l"sqlite3" -l"sqlite3.0" -l"z" -framework "AFNetworking" -framework "AVFoundation" -framework "Accelerate" -framework "AdSupport" -framework "CFNetwork" -framework "CoreFoundation" -framework "CoreGraphics" -framework "CoreLocation" -framework "CoreMedia" -framework "CoreTelephony" -framework "CoreText" -framework "DZNEmptyDataSet" -framework "Foundation" -framework "GTCommonSDK" -framework "GTExtensionSDK" -framework "GTSDK" -framework "GeYanSdk" -framework "HXPhotoPicker" -framework "IQKeyboardManager" -framework "ImageIO" -framework "LSTTimer" -framework "MBProgressHUD" -framework "MJRefresh" -framework "MOFSPickerManager" -framework "Masonry" -framework "MobileCoreServices" -framework "Photos" -framework "PhotosUI" -framework "PopupKit" -framework "QuartzCore" -framework "Reachability" -framework "SDAutoLayout" -framework "SDCycleScrollView" -framework "SDWebImage" -framework "SSZipArchive" -framework "Security" -framework "SystemConfiguration" -framework "UIKit" -framework "UITableView_FDTemplateLayoutCell" -framework "UMAPM" -framework "UMCommon" -framework "UMCommonLog" -framework "UMDevice" -framework "UMLink" -framework "VideoToolbox" -framework "WebKit" -framework "YYModel" -framework "YYText" -framework "ZXSDK" -framework "libpag" -weak_framework "AppTrackingTransparency" -weak_framework "Network" -weak_framework "UserNotifications"
OTHER_LDFLAGS = $(inherited) -ObjC -l"WechatOpenSDK" -l"c++" -l"iconv" -l"icucore" -l"resolv" -l"sqlite3" -l"sqlite3.0" -l"z" -framework "AFNetworking" -framework "AVFoundation" -framework "Accelerate" -framework "AdSupport" -framework "CFNetwork" -framework "CoreFoundation" -framework "CoreGraphics" -framework "CoreLocation" -framework "CoreMedia" -framework "CoreTelephony" -framework "CoreText" -framework "DZNEmptyDataSet" -framework "Foundation" -framework "GTCommonSDK" -framework "GTExtensionSDK" -framework "GTSDK" -framework "GeYanSdk" -framework "HXPhotoPicker" -framework "IQKeyboardManager" -framework "ImageIO" -framework "LSTTimer" -framework "MBProgressHUD" -framework "MJRefresh" -framework "MOFSPickerManager" -framework "Masonry" -framework "MobileCoreServices" -framework "Photos" -framework "PhotosUI" -framework "PopupKit" -framework "QuartzCore" -framework "Reachability" -framework "SDAutoLayout" -framework "SDCycleScrollView" -framework "SDWebImage" -framework "SSZipArchive" -framework "Security" -framework "SocketRocket" -framework "SystemConfiguration" -framework "UIKit" -framework "UITableView_FDTemplateLayoutCell" -framework "UMAPM" -framework "UMCommon" -framework "UMCommonLog" -framework "UMDevice" -framework "UMLink" -framework "VideoToolbox" -framework "WebKit" -framework "YYModel" -framework "YYText" -framework "ZXSDK" -framework "libpag" -weak_framework "AppTrackingTransparency" -weak_framework "Network" -weak_framework "UserNotifications"
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>${PODS_DEVELOPMENT_LANGUAGE}</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>0.6.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${CURRENT_PROJECT_VERSION}</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>

View File

@ -0,0 +1,5 @@
#import <Foundation/Foundation.h>
@interface PodsDummy_SocketRocket : NSObject
@end
@implementation PodsDummy_SocketRocket
@end

View File

@ -0,0 +1,12 @@
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#else
#ifndef FOUNDATION_EXPORT
#if defined(__cplusplus)
#define FOUNDATION_EXPORT extern "C"
#else
#define FOUNDATION_EXPORT extern
#endif
#endif
#endif

View File

@ -0,0 +1,21 @@
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#else
#ifndef FOUNDATION_EXPORT
#if defined(__cplusplus)
#define FOUNDATION_EXPORT extern "C"
#else
#define FOUNDATION_EXPORT extern
#endif
#endif
#endif
#import "NSRunLoop+SRWebSocket.h"
#import "NSURLRequest+SRWebSocket.h"
#import "SocketRocket.h"
#import "SRSecurityPolicy.h"
#import "SRWebSocket.h"
FOUNDATION_EXPORT double SocketRocketVersionNumber;
FOUNDATION_EXPORT const unsigned char SocketRocketVersionString[];

View File

@ -0,0 +1,13 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SocketRocket
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
OTHER_LDFLAGS = $(inherited) -l"icucore" -framework "CFNetwork" -framework "Security"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE}
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/SocketRocket
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View File

@ -0,0 +1,6 @@
framework module SocketRocket {
umbrella header "SocketRocket-umbrella.h"
export *
module * { export * }
}

View File

@ -0,0 +1,13 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SocketRocket
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
OTHER_LDFLAGS = $(inherited) -l"icucore" -framework "CFNetwork" -framework "Security"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE}
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/SocketRocket
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

View File

@ -8,6 +8,12 @@
/* Begin PBXBuildFile section */
664551746CA42328436EB43A /* Pods_ProductApp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7E9D1598912BF8D031CA536 /* Pods_ProductApp.framework */; };
CA07CD142CC5E5C500AF41ED /* XieYiAlterView.m in Sources */ = {isa = PBXBuildFile; fileRef = CA07CD132CC5E5C500AF41ED /* XieYiAlterView.m */; };
CA07CD172CC5F25B00AF41ED /* TextbookDetailModel.m in Sources */ = {isa = PBXBuildFile; fileRef = CA07CD162CC5F25B00AF41ED /* TextbookDetailModel.m */; };
CA07CD1A2CC6335400AF41ED /* ExampleCorrectList.m in Sources */ = {isa = PBXBuildFile; fileRef = CA07CD192CC6335400AF41ED /* ExampleCorrectList.m */; };
CA07CD1D2CC646AA00AF41ED /* ExampleWriteList.m in Sources */ = {isa = PBXBuildFile; fileRef = CA07CD1C2CC646AA00AF41ED /* ExampleWriteList.m */; };
CA07CD202CC6572E00AF41ED /* WebSocketManager.m in Sources */ = {isa = PBXBuildFile; fileRef = CA07CD1F2CC6572E00AF41ED /* WebSocketManager.m */; };
CA07CD232CC6601500AF41ED /* SSENetWorkManager.m in Sources */ = {isa = PBXBuildFile; fileRef = CA07CD222CC6601500AF41ED /* SSENetWorkManager.m */; };
CA0C3A832CB4C27E00E01A72 /* HuanGeSiLuViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CA0C3A822CB4C27E00E01A72 /* HuanGeSiLuViewController.m */; };
CA0C3A872CB4C34800E01A72 /* HuanGeSiLuView.m in Sources */ = {isa = PBXBuildFile; fileRef = CA0C3A862CB4C34800E01A72 /* HuanGeSiLuView.m */; };
CA0C3A8B2CB4C80300E01A72 /* HuanGeSiLuCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = CA0C3A8A2CB4C80300E01A72 /* HuanGeSiLuCollectionViewCell.m */; };
@ -482,6 +488,18 @@
/* Begin PBXFileReference section */
87167CC240BDAA55C86F80DE /* Pods-ProductApp.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ProductApp.debug.xcconfig"; path = "Target Support Files/Pods-ProductApp/Pods-ProductApp.debug.xcconfig"; sourceTree = "<group>"; };
B3DBEC0C6ED0E182F65EDBEA /* Pods-ProductApp.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ProductApp.release.xcconfig"; path = "Target Support Files/Pods-ProductApp/Pods-ProductApp.release.xcconfig"; sourceTree = "<group>"; };
CA07CD122CC5E5C500AF41ED /* XieYiAlterView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XieYiAlterView.h; sourceTree = "<group>"; };
CA07CD132CC5E5C500AF41ED /* XieYiAlterView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XieYiAlterView.m; sourceTree = "<group>"; };
CA07CD152CC5F25B00AF41ED /* TextbookDetailModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TextbookDetailModel.h; sourceTree = "<group>"; };
CA07CD162CC5F25B00AF41ED /* TextbookDetailModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TextbookDetailModel.m; sourceTree = "<group>"; };
CA07CD182CC6335400AF41ED /* ExampleCorrectList.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ExampleCorrectList.h; sourceTree = "<group>"; };
CA07CD192CC6335400AF41ED /* ExampleCorrectList.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ExampleCorrectList.m; sourceTree = "<group>"; };
CA07CD1B2CC646AA00AF41ED /* ExampleWriteList.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ExampleWriteList.h; sourceTree = "<group>"; };
CA07CD1C2CC646AA00AF41ED /* ExampleWriteList.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ExampleWriteList.m; sourceTree = "<group>"; };
CA07CD1E2CC6572E00AF41ED /* WebSocketManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebSocketManager.h; sourceTree = "<group>"; };
CA07CD1F2CC6572E00AF41ED /* WebSocketManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebSocketManager.m; sourceTree = "<group>"; };
CA07CD212CC6601500AF41ED /* SSENetWorkManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SSENetWorkManager.h; sourceTree = "<group>"; };
CA07CD222CC6601500AF41ED /* SSENetWorkManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SSENetWorkManager.m; sourceTree = "<group>"; };
CA0C3A812CB4C27E00E01A72 /* HuanGeSiLuViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HuanGeSiLuViewController.h; sourceTree = "<group>"; };
CA0C3A822CB4C27E00E01A72 /* HuanGeSiLuViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HuanGeSiLuViewController.m; sourceTree = "<group>"; };
CA0C3A852CB4C34800E01A72 /* HuanGeSiLuView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HuanGeSiLuView.h; sourceTree = "<group>"; };
@ -1828,6 +1846,8 @@
CA5D036E2CC0DFCD007B3BA5 /* GuiZheAlterView.m */,
CA3868672CC211FE009C98B0 /* LoadAlterView.h */,
CA3868682CC211FE009C98B0 /* LoadAlterView.m */,
CA07CD122CC5E5C500AF41ED /* XieYiAlterView.h */,
CA07CD132CC5E5C500AF41ED /* XieYiAlterView.m */,
);
path = alter;
sourceTree = "<group>";
@ -2856,6 +2876,10 @@
CABA148C2C9D4312002CB3B1 /* PublicNetWorkManager.m */,
CABA14BA2C9D4330002CB3B1 /* PublicUploadImageManager.h */,
CABA14B92C9D4330002CB3B1 /* PublicUploadImageManager.m */,
CA07CD1E2CC6572E00AF41ED /* WebSocketManager.h */,
CA07CD1F2CC6572E00AF41ED /* WebSocketManager.m */,
CA07CD212CC6601500AF41ED /* SSENetWorkManager.h */,
CA07CD222CC6601500AF41ED /* SSENetWorkManager.m */,
);
path = NetWorkManager;
sourceTree = "<group>";
@ -2957,6 +2981,12 @@
CAF76E6B2CBE0BAA00825E5E /* ToolsListModel.m */,
CABD8C962CBF9D26009A5E5E /* LanguageKeyModel.h */,
CABD8C972CBF9D26009A5E5E /* LanguageKeyModel.m */,
CA07CD152CC5F25B00AF41ED /* TextbookDetailModel.h */,
CA07CD162CC5F25B00AF41ED /* TextbookDetailModel.m */,
CA07CD182CC6335400AF41ED /* ExampleCorrectList.h */,
CA07CD192CC6335400AF41ED /* ExampleCorrectList.m */,
CA07CD1B2CC646AA00AF41ED /* ExampleWriteList.h */,
CA07CD1C2CC646AA00AF41ED /* ExampleWriteList.m */,
);
path = models;
sourceTree = "<group>";
@ -4352,6 +4382,7 @@
CB489FCB2744A0BD00DA044A /* HXHud.m in Sources */,
CA0C3A9E2CB4DADA00E01A72 /* DuanLuoXieZuoViewController.m in Sources */,
CAC806562CA1382500C21AA7 /* StartZNXZView.m in Sources */,
CA07CD1D2CC646AA00AF41ED /* ExampleWriteList.m in Sources */,
CA4257BD2CA2C65600A36A10 /* StartPayTQViewCell.m in Sources */,
CABD8CA72CBFA7A3009A5E5E /* GongJuImageToTextView.m in Sources */,
CA5D03272CC0DDF0007B3BA5 /* PayPublicView.m in Sources */,
@ -4384,6 +4415,7 @@
CABA14BB2C9D4330002CB3B1 /* PublicUploadImageManager.m in Sources */,
CA6B97292CBD04FA000213F3 /* AIChatModel.m in Sources */,
CA0D08412CA52F800086855E /* ShouYeShenFenViewController.m in Sources */,
CA07CD202CC6572E00AF41ED /* WebSocketManager.m in Sources */,
CA5D035E2CC0DE8D007B3BA5 /* YaoQingAlterView.m in Sources */,
CA4257AA2CA2A30C00A36A10 /* StartZNPPTYuLanViewController.m in Sources */,
CB489F9D2744A0BD00DA044A /* AssistiveView.m in Sources */,
@ -4400,6 +4432,7 @@
CA81818B2C9E598300EE7E6E /* StartKTXZWenZhangView.m in Sources */,
CB489FA72744A0BD00DA044A /* ZJScrollPageView.m in Sources */,
CA5D03292CC0DDF0007B3BA5 /* PayPublicYouHuiLogVuew.m in Sources */,
CA07CD142CC5E5C500AF41ED /* XieYiAlterView.m in Sources */,
CA5D02ED2CC0DD6B007B3BA5 /* PayOrderModel.m in Sources */,
CA3868582CC1F66E009C98B0 /* LoginTelView.m in Sources */,
CA5D03632CC0DE8D007B3BA5 /* YaoQingView.m in Sources */,
@ -4498,6 +4531,7 @@
CAC8064E2CA119F800C21AA7 /* StartZWPIDetailView.m in Sources */,
CA5D02E32CC0DD6B007B3BA5 /* UserModel.m in Sources */,
CB489F6C2744A0BD00DA044A /* RadianDisView.m in Sources */,
CA07CD1A2CC6335400AF41ED /* ExampleCorrectList.m in Sources */,
CA487D8A2CA3AB6B00AE773B /* UITableView+MoveCell.m in Sources */,
CA0D08782CA557700086855E /* ShouYeLiShiJiLuPGCollectionViewCell.m in Sources */,
CAB0F3512CAA7321003B0C39 /* ZhiShuAlterView.m in Sources */,
@ -4666,7 +4700,9 @@
CAA600D12CA9565500026CF4 /* KeTangXieZuoViewController.m in Sources */,
CB489FA12744A0BD00DA044A /* ZJTitleView.m in Sources */,
CA0D082D2CA4F8930086855E /* ShouYeZNXZTableViewCell.m in Sources */,
CA07CD232CC6601500AF41ED /* SSENetWorkManager.m in Sources */,
CAF76E872CBE5F8B00825E5E /* GongJuCreateView.m in Sources */,
CA07CD172CC5F25B00AF41ED /* TextbookDetailModel.m in Sources */,
CAB0D3792CAA488C009BF67D /* ZhiNengXieZuoView.m in Sources */,
CABD8C852CBF72A7009A5E5E /* GongJuTextView.m in Sources */,
CABD8C812CBF6FFB009A5E5E /* GongJuTextViewController.m in Sources */,

View File

@ -78,11 +78,105 @@
filePath = "ProductApp/ProductMain/NetWorkManager/NetWorkManager.m"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "162"
endingLineNumber = "162"
startingLineNumber = "269"
endingLineNumber = "269"
landmarkName = "+requestToolsListData:page:type_id:tool_name:is_recommend:Callback:"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "144E884F-35FD-43B2-858C-7EFD5F276307"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "ProductApp/ProductMain/NetWorkManager/WebSocketManager.m"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "336"
endingLineNumber = "336"
landmarkName = "-webSocket:didReceiveMessage:"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "51A20835-14FF-4F2C-9252-8798E7712AF7"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "ProductApp/ProductMain/NetWorkManager/WebSocketManager.m"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "124"
endingLineNumber = "124"
landmarkName = "-connect"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "6246BC94-D07E-4E5C-88FC-6280FB9F6DAD"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "ProductApp/ProductMain/NetWorkManager/WebSocketManager.m"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "356"
endingLineNumber = "356"
landmarkName = "-webSocket:didFailWithError:"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "D4B77918-AD0D-4325-923A-A6D2D5DBFE85"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "ProductApp/ProductMain/NetWorkManager/SSENetWorkManager.m"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "26"
endingLineNumber = "26"
landmarkName = "-requestTo:stage:title:require:title_id:"
landmarkType = "7">
<Locations>
<Location
uuid = "D4B77918-AD0D-4325-923A-A6D2D5DBFE85 - 5a44dda45c228076"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "+[SSENetWorkManager requestTo:stage:title:require:title_id:]"
moduleName = "ProductApp"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/gongzuo/Desktop/%E5%85%AC%E5%8F%B8GIT/%E6%9E%81%E5%85%89%E5%86%99%E4%BD%9C/ProductApp/ProductApp/ProductMain/NetWorkManager/SSENetWorkManager.m"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "26"
endingLineNumber = "26">
</Location>
<Location
uuid = "D4B77918-AD0D-4325-923A-A6D2D5DBFE85 - dca731babbc01e48"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "-[SSENetWorkManager requestTo:stage:title:require:title_id:]"
moduleName = "ProductApp"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/gongzuo/Desktop/%E5%85%AC%E5%8F%B8GIT/%E6%9E%81%E5%85%89%E5%86%99%E4%BD%9C/ProductApp/ProductApp/ProductMain/NetWorkManager/SSENetWorkManager.m"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "26"
endingLineNumber = "26">
</Location>
</Locations>
</BreakpointContent>
</BreakpointProxy>
</Breakpoints>
</Bucket>

View File

@ -258,7 +258,7 @@ static NSTimeInterval af_timeout = 30.0f;
{
[dicheadertemp setDictionary:Headers];
}
[dicheadertemp setObject:@"com.devcon.bid" forKey:@"x-package"];
[dicheadertemp setObject:@"com.batiao.aiwrite" forKey:@"x-package"];
NSArray *arrkeys = [dicheadertemp allKeys];
for(NSString *key in arrkeys)

View File

@ -36,6 +36,9 @@ NS_ASSUME_NONNULL_BEGIN
///讯飞appid
#define XunFeiAppId @"a26724a7"
///友盟
#define YouMengAppKey @""
//网络请求数据回调block
#define SAFE_BLOCK_CALL_NO_P(b) (b == nil ?: b())
#define SAFE_BLOCK_CALL(b, p) (b == nil ? : b(p) )
@ -119,6 +122,13 @@ alpha:alphaValue]
///微信登录通知
#define WeiXinDengLuSQ @"WeiXinDengLuSQ"
///协议弹窗
#define UserXieYiOk @"UserXieYiOk"
///引导页
#define YingDaoYe @"YingDaoYe"
@end
NS_ASSUME_NONNULL_END

View File

@ -354,6 +354,8 @@ NS_ASSUME_NONNULL_BEGIN
+(NSMutableAttributedString *)applyCSS:(NSString *)text;
///创建二维码
+(UIImage *)CreateStrcode:(NSString *)strcode size:(CGFloat)f_width;
///将小写数字转换为大写
+ (NSString *)convertNumberToUppercase:(NSInteger)number ;
@end
NS_ASSUME_NONNULL_END

View File

@ -2120,5 +2120,20 @@ static dispatch_source_t _timer;
return [UIImage imageWithCGImage:scaledImage];
}
+(NSString *)convertNumberToUppercase:(NSInteger)number {
NSArray *digitCharacters = @[@"零", @"一", @"二", @"三", @"四", @"五", @"六", @"七", @"八", @"九"];
NSMutableString *uppercaseString = [[NSMutableString alloc] init];
if (number == 0) {
return digitCharacters[0];
}
NSInteger tempNumber = 0;
while (tempNumber < [NSString stringWithFormat:@"%ld",number].length) {
[uppercaseString insertString:digitCharacters[tempNumber] atIndex:0];
tempNumber++;
}
return uppercaseString;
}
@end

View File

@ -153,7 +153,7 @@
}
NSLog(@"%@",NSStringFromCGPoint(point));
// NSLog(@"%@",NSStringFromCGPoint(point));
}
- (CGPoint)boundingRectForLastCharacterInLabel:(UILabel *)label {

View File

@ -8,10 +8,12 @@
#import <Foundation/Foundation.h>
#import "RoleTreeModel.h"
#import "TextbookInfoModel.h"
#import "ToolsTypeModel.h"
#import "ToolsListModel.h"
#import "LanguageKeyModel.h"
#import "TextbookDetailModel.h"
#import "ExampleCorrectList.h"
#import "ExampleWriteList.h"
NS_ASSUME_NONNULL_BEGIN
@ -37,13 +39,33 @@ NS_ASSUME_NONNULL_BEGIN
pid:(NSString *)pid
Callback:(completeModeBlock)callback;
/*
/api/textbook/detail
id
*/
+ (void)requestTextbookDetailData:(UIView *)view
ID:(NSString *)ID
Callback:(completeModeBlock)callback;
/*
/api/example/correct/list
role_id
*/
+ (void)requestExampleCorrectListData:(UIView *)view
role_id:(NSString *)role_id
Callback:(completeModeBlock)callback;
/*
/api/example/write/list
role_id
*/
+ (void)requestExampleWriteListData:(UIView *)view
role_id:(NSString *)role_id
Callback:(completeModeBlock)callback;
/*

View File

@ -56,8 +56,14 @@
Callback:(completeModeBlock)callback
{
NSMutableDictionary *dicQuery = [NSMutableDictionary new];
[dicQuery setObject:[Tools isStringnil:role_id] forKey:@"role_id"];
[dicQuery setObject:[Tools isStringnil:pid] forKey:@"pid"];
if([Tools isStringnil:role_id].length>0)
{
[dicQuery setObject:[Tools isStringnil:role_id] forKey:@"role_id"];
}
if([Tools isStringnil:pid].length>0)
{
[dicQuery setObject:[Tools isStringnil:pid] forKey:@"pid"];
}
NSMutableDictionary *dicHeader = [NSMutableDictionary new];
@ -82,9 +88,110 @@
}];
}
/*
/api/textbook/detail
id
*/
+ (void)requestTextbookDetailData:(UIView *)view
ID:(NSString *)ID
Callback:(completeModeBlock)callback
{
NSMutableDictionary *dicQuery = [NSMutableDictionary new];
[dicQuery setObject:[Tools isStringnil:ID] forKey:@"id"];
NSMutableDictionary *dicHeader = [NSMutableDictionary new];
NSMutableDictionary *dicpush = [NSMutableDictionary new];
[YSAPIClient requestWithRequestBaseUrl:BaseUrl Type:1 url:@"api/textbook/detail" paraments:dicpush Headers:dicHeader Query:dicQuery completeBlock:^(id _Nullable responseObject, NSError * _Nullable error) {
BOOL state = NO;
NSString *describle = @"";
if (responseObject==nil) {
describle = @"网络错误";
BaseModel *model = [BaseModel new];
model.message =describle;
callback(state,model,describle);
}else{
NSDictionary *dicAll=responseObject;
describle = dicAll[@"message"];
if ([[NSString stringWithFormat:@"%@",dicAll[@"code"]] intValue] == 0) {
state = YES;
}
callback(state,[TextbookDetailModel yy_modelWithJSON:dicAll],describle);
}
}];
}
/*
/api/example/correct/list
role_id
*/
+ (void)requestExampleCorrectListData:(UIView *)view
role_id:(NSString *)role_id
Callback:(completeModeBlock)callback
{
NSMutableDictionary *dicQuery = [NSMutableDictionary new];
[dicQuery setObject:[Tools isStringnil:role_id] forKey:@"role_id"];
NSMutableDictionary *dicHeader = [NSMutableDictionary new];
NSMutableDictionary *dicpush = [NSMutableDictionary new];
[YSAPIClient requestWithRequestBaseUrl:BaseUrl Type:1 url:@"api/example/correct/list" paraments:dicpush Headers:dicHeader Query:dicQuery completeBlock:^(id _Nullable responseObject, NSError * _Nullable error) {
BOOL state = NO;
NSString *describle = @"";
if (responseObject==nil) {
describle = @"网络错误";
BaseModel *model = [BaseModel new];
model.message =describle;
callback(state,model,describle);
}else{
NSDictionary *dicAll=responseObject;
describle = dicAll[@"message"];
if ([[NSString stringWithFormat:@"%@",dicAll[@"code"]] intValue] == 0) {
state = YES;
}
callback(state,[ExampleCorrectList yy_modelWithJSON:dicAll],describle);
}
}];
}
/*
/api/example/write/list
role_id
*/
+ (void)requestExampleWriteListData:(UIView *)view
role_id:(NSString *)role_id
Callback:(completeModeBlock)callback
{
NSMutableDictionary *dicQuery = [NSMutableDictionary new];
[dicQuery setObject:[Tools isStringnil:role_id] forKey:@"role_id"];
NSMutableDictionary *dicHeader = [NSMutableDictionary new];
NSMutableDictionary *dicpush = [NSMutableDictionary new];
[YSAPIClient requestWithRequestBaseUrl:BaseUrl Type:1 url:@"api/example/write/list" paraments:dicpush Headers:dicHeader Query:dicQuery completeBlock:^(id _Nullable responseObject, NSError * _Nullable error) {
BOOL state = NO;
NSString *describle = @"";
if (responseObject==nil) {
describle = @"网络错误";
BaseModel *model = [BaseModel new];
model.message =describle;
callback(state,model,describle);
}else{
NSDictionary *dicAll=responseObject;
describle = dicAll[@"message"];
if ([[NSString stringWithFormat:@"%@",dicAll[@"code"]] intValue] == 0) {
state = YES;
}
callback(state,[ExampleWriteList yy_modelWithJSON:dicAll],describle);
}
}];
}
/*

View File

@ -0,0 +1,17 @@
//
// SSENetWorkManager.h
// ProductApp
//
// Created by 工作 on 2024/10/21.
//
#import <Foundation/Foundation.h>
#import "YSAPIClient.h"
NS_ASSUME_NONNULL_BEGIN
@interface SSENetWorkManager : NSObject
+ (instancetype)shareManager;
- (void)requestTo:(NSString*)host stage:(NSString *)stage title:(NSString *)title require:(NSString *)require title_id:(NSString *)title_id;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,104 @@
//
// SSENetWorkManager.m
// ProductApp
//
// Created by on 2024/10/21.
//
#import "SSENetWorkManager.h"
@interface SSENetWorkManager ()<NSURLSessionDelegate>
@end
@implementation SSENetWorkManager
+ (instancetype)shareManager
{
static SSENetWorkManager *_instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[self alloc]init];
});
return _instance;
}
- (void)requestTo:(NSString*)host stage:(NSString *)stage title:(NSString *)title require:(NSString *)require title_id:(NSString *)title_id
{
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil];
NSMutableDictionary *dicpush = [NSMutableDictionary new];
[dicpush setObject:[Tools isStringnil:stage] forKey:@"stage"];
[dicpush setObject:[Tools isStringnil:title] forKey:@"title"];
[dicpush setObject:[Tools isStringnil:require] forKey:@"require"];
[dicpush setObject:[Tools isStringnil:title_id] forKey:@"title_id"];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:host]];
[request setValue:@"text/event-stream" forHTTPHeaderField:@"Content-Type"];
[request setHTTPMethod:@"POST"];
NSMutableDictionary *dicheadertemp = [NSMutableDictionary new];
[dicheadertemp setObject:@"com.batiao.aiwrite" forKey:@"x-package"];
NSArray *arrkeys = [dicheadertemp allKeys];
for(NSString *key in arrkeys)
{
[request setValue:[Tools isStringnil:[dicheadertemp objectForKey:key]] forHTTPHeaderField:key];
}
NSString *strtoken = [UserInfoModel shareModel].token;
if([Tools isStringnil:strtoken].length==0)
{
[request setValue:@"" forHTTPHeaderField:@"x-token"];
}
else
{
[request setValue:[Tools isStringnil:strtoken] forHTTPHeaderField:@"x-token"];
}
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dicpush options:kNilOptions error:nil];
NSString *bodyString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
[request setHTTPBody:[bodyString dataUsingEncoding:NSUTF8StringEncoding]];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request];
// NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
// if(error)
// {
// return;
// }
//
// NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
// if(httpResponse.statusCode != 200)return;
//
// if([httpResponse.MIMEType isEqualToString:@"text/event-stream"])
// {
// NSString *strtemp = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
// NSLog(@"%@",strtemp);
// }
// }];
//
[task resume];
}
#pragma mark - NSURLSessionDelegate
- (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(nullable NSError *)error
{
}
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
completionHandler:(void (NS_SWIFT_SENDABLE ^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler
{
}
- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session
{
}
@end

View File

@ -0,0 +1,44 @@
//
// WebSocketManager.h
// WebsocketExample
//
// Created by sunguangfeng on 2019/6/23.
// Copyright © 2019 sgf. All rights reserved.
//
#import <Foundation/Foundation.h>
@class SRWebSocket;
@class WebSocketManager;
typedef NS_ENUM(NSUInteger,WebSocketConnectType){
WebSocketDefault = 0, //初始状态,未连接
WebSocketConnect, //已连接
WebSocketDisconnect //连接后断开
};
@protocol WebSocketManagerDelegate <NSObject>
- (void)webSocketManagerDidReceiveMessageWithString:(NSString *)string;
@end
NS_ASSUME_NONNULL_BEGIN
@interface WebSocketManager : NSObject
@property(nonatomic,weak) id<WebSocketManagerDelegate > delegate;
@property (nonatomic, assign, readonly) WebSocketConnectType connectType;
+(instancetype)shared;
/// host 请求链接 tage年级 title标题 require写作要求 title_id标题ID重新的时候不传
- (void)connectTo:(NSString*)host stage:(NSString *)stage title:(NSString *)title require:(NSString *)require title_id:(NSString *)title_id;
- (void)reConnect;
- (void)disconnect;
- (void)sendStringToServer:(NSString *)string;
-(BOOL) isConnect;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,453 @@
//
// WebSocketManager.m
// WebsocketExample
//
// Created by sunguangfeng on 2019/6/23.
// Copyright © 2019 sgf. All rights reserved.
//
#import "WebSocketManager.h"
#import <SocketRocket/SocketRocket.h>
#import <AFNetworking/AFNetworking.h>
#define WeakSelf __weak typeof(self) weakSelf = self;
#ifndef dispatch_main_async_safe
#define dispatch_main_async_safe(block)\
if (dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL) == dispatch_queue_get_label(dispatch_get_main_queue())) {\
block();\
} else {\
dispatch_async(dispatch_get_main_queue(), block);\
}
#endif
@interface WebSocketManager ()<SRWebSocketDelegate>
@property (nonatomic, copy) NSString* host;
@property (nonatomic, copy) NSDictionary* dicpush;
@property (nonatomic, strong, readonly) SRWebSocket *webSocket;
@property (nonatomic, assign) WebSocketConnectType connectType;
@property (nonatomic, strong) NSTimer *heartBeatTimer; //
@property (nonatomic, strong) NSTimer *netWorkTestingTimer; //
@property (nonatomic, assign) NSTimeInterval reConnectTime; //
@property (nonatomic, strong) NSMutableArray *sendQueue; //
@property (nonatomic, assign) BOOL isActivelyClose; //
@end
@implementation WebSocketManager
+(instancetype)shared{
static WebSocketManager *_instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[self alloc]init];
});
return _instance;
}
- (instancetype)init
{
self = [super init];
if(self){
self.reConnectTime = 0;
self.isActivelyClose = NO;
self.sendQueue = [[NSMutableArray alloc] init];
}
return self;
}
/// host tage title require title_idID
- (void)connectTo:(NSString*)host stage:(NSString *)stage title:(NSString *)title require:(NSString *)require title_id:(NSString *)title_id
{
self.host = host;
///
NSMutableDictionary *dicpush = [NSMutableDictionary new];
[dicpush setObject:[Tools isStringnil:stage] forKey:@"stage"];
[dicpush setObject:[Tools isStringnil:title] forKey:@"title"];
[dicpush setObject:[Tools isStringnil:require] forKey:@"require"];
[dicpush setObject:[Tools isStringnil:title_id] forKey:@"title_id"];
self.dicpush = dicpush;
[self connect];
}
-(void) connect
{
self.isActivelyClose = NO;
self.webSocket.delegate = nil;
[self.webSocket close];
_webSocket = nil;
///URL
NSString *strurltemp = [NSString stringWithFormat:@"%@",self.host];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:strurltemp]];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPMethod:@"POST"];
NSMutableDictionary *dicheadertemp = [NSMutableDictionary new];
[dicheadertemp setObject:@"com.batiao.aiwrite" forKey:@"x-package"];
NSArray *arrkeys = [dicheadertemp allKeys];
for(NSString *key in arrkeys)
{
[request setValue:[Tools isStringnil:[dicheadertemp objectForKey:key]] forHTTPHeaderField:key];
}
NSString *strtoken = [UserInfoModel shareModel].token;
if([Tools isStringnil:strtoken].length==0)
{
[request setValue:@"" forHTTPHeaderField:@"x-token"];
}
else
{
[request setValue:[Tools isStringnil:strtoken] forHTTPHeaderField:@"x-token"];
}
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:self.dicpush options:kNilOptions error:nil];
NSString *bodyString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
[request setHTTPBody:[bodyString dataUsingEncoding:NSUTF8StringEncoding]];
_webSocket = [[SRWebSocket alloc] initWithURLRequest:request];
self.webSocket.delegate = self;
[self.webSocket open];
}
- (void)reConnect
{
if(self.webSocket.readyState == SR_OPEN){
return;
}
if(self.reConnectTime > 1024){
self.reConnectTime = 0;
return;
}
WeakSelf
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.reConnectTime *NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if(weakSelf.webSocket.readyState == SR_OPEN && weakSelf.webSocket.readyState == SR_CONNECTING) {
return;
}
[weakSelf connect];
//THLog(@"正在重连......");
if(weakSelf.reConnectTime == 0){ //2
weakSelf.reConnectTime = 2;
}else{
weakSelf.reConnectTime *= 2;
if(weakSelf.reConnectTime>10)
{
weakSelf.reConnectTime = 10;
}
}
});
}
- (void)disconnect
{
if(self.webSocket==nil)
{
//
[self _destoryHeartBeat];
//
[self _destoryNetWorkStartTesting];
return;
}
Byte byte[] = {0x01};
NSData *data = [NSData dataWithBytes:byte length:1];
[_webSocket send:data];
_isActivelyClose = YES;
self.connectType = WebSocketDefault;
if(self.webSocket)
{
[self.webSocket close];
_webSocket = nil;
}
//
[self _destoryHeartBeat];
//
[self _destoryNetWorkStartTesting];
}
-(void) sendStringToServer:(NSString *)string
{
if([WebSocketManager shared].isConnect==NO)
{
return;
}
[self.sendQueue addObject:string];
[self _sendQueue];
}
-(void) _sendQueue
{
if(_sendQueue.count == 0)
{
return;
}
//
if (AFNetworkReachabilityManager.sharedManager.networkReachabilityStatus == AFNetworkReachabilityStatusNotReachable)
{
//
[self _noNetWorkStartTestingTimer];
}
else
{
if(self.webSocket != nil)
{
if(self.webSocket.readyState == SR_OPEN)
{
NSString *data = _sendQueue.firstObject;
[_webSocket send:data];
[_sendQueue removeObjectAtIndex:0];
if(_sendQueue.count>0)
{
[self _sendQueue];
}
}
else if (self.webSocket.readyState == SR_CONNECTING) //
{
//DLog(@"正在连接中,重连后会去自动同步数据");
}
else if (self.webSocket.readyState == SR_CLOSING || self.webSocket.readyState == SR_CLOSED) //
{
[self reConnect];
}
}
else
{
[self connect];
}
}
}
- (void)sendPing
{
Byte byte[] = {0x02};
NSData *data = [NSData dataWithBytes:byte length:1];
[_webSocket send:data];
}
#pragma makr - private functions
- (void) _startHeartBeat
{
//
if(self.heartBeatTimer) {
return;
}
[self _destoryHeartBeat];
dispatch_main_async_safe(^{
self.heartBeatTimer = [NSTimer timerWithTimeInterval:10.f target:self selector:@selector(_senderheartBeat) userInfo:nil repeats:true];
[[NSRunLoop currentRunLoop] addTimer:self.heartBeatTimer forMode:NSRunLoopCommonModes];
});
}
- (void)_destoryHeartBeat{
WeakSelf
dispatch_main_async_safe(^{
if(weakSelf.heartBeatTimer)
{
[weakSelf.heartBeatTimer invalidate];
weakSelf.heartBeatTimer = nil;
}
});
}
- (void)_senderheartBeat{
//
WeakSelf
dispatch_main_async_safe(^{
if(weakSelf.webSocket.readyState == SR_OPEN){
[weakSelf sendPing];
}
});
}
- (void) _noNetWorkStartTestingTimer{
WeakSelf
dispatch_main_async_safe(^{
weakSelf.netWorkTestingTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:weakSelf selector:@selector(_noNetWorkStartTesting) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:weakSelf.netWorkTestingTimer forMode:NSDefaultRunLoopMode];
});
}
- (void) _noNetWorkStartTesting{
//
if(AFNetworkReachabilityManager.sharedManager.networkReachabilityStatus != AFNetworkReachabilityStatusNotReachable)
{
//
[self _destoryNetWorkStartTesting];
//
[self reConnect];
}
}
- (void) _destoryNetWorkStartTesting{
WeakSelf
dispatch_main_async_safe(^{
if(weakSelf.netWorkTestingTimer)
{
[weakSelf.netWorkTestingTimer invalidate];
weakSelf.netWorkTestingTimer = nil;
}
});
}
#pragma mark - SRWebSocketDelegate
////
- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message
{
NSLog(@"%@",message);
if ([self.delegate respondsToSelector:@selector(webSocketManagerDidReceiveMessageWithString:)] && [message isKindOfClass:[NSString class]]) {
[self.delegate webSocketManagerDidReceiveMessageWithString:message];
}
}
- (void)webSocketDidOpen:(SRWebSocket *)webSocket
{
NSLog(@"socket 开始连接");
self.connectType = WebSocketConnect;
[self _startHeartBeat];///
[self _sendQueue];
}
- (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error
{
NSLog(@"连接失败");
self.connectType = WebSocketDisconnect;
if (AFNetworkReachabilityManager.sharedManager.networkReachabilityStatus == AFNetworkReachabilityStatusNotReachable){
[self _noNetWorkStartTestingTimer];
}else{
[self reConnect];
}
}
- (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean
{
if(self.isActivelyClose)
{
self.connectType = WebSocketDefault;
return;
}
self.connectType = WebSocketDisconnect;
[self _destoryHeartBeat]; //
if (AFNetworkReachabilityManager.sharedManager.networkReachabilityStatus == AFNetworkReachabilityStatusNotReachable){ //
[self _noNetWorkStartTestingTimer];//
}else{ //
NSLog(@"关闭连接");
_webSocket = nil;
if(_isActivelyClose==NO)
{
[self reConnect];//
}
}
}
- (void)webSocket:(SRWebSocket *)webSocket didReceivePong:(NSData *)pongPayload
{
NSLog(@"接受pong数据--> %@",pongPayload);
}
-(BOOL) isConnect
{
return _connectType == WebSocketConnect;
}
///URL
-(NSString *)signQuerInfo:(NSMutableDictionary *)dicadd body:(NSString *)body
{
NSString *strpathtemp = [self dicSort:dicadd];
NSString *strsign;
if(body.length>0)
{
strsign = [strpathtemp stringByAppendingFormat:@"%@", [NSString stringWithFormat:@"&%@&%@",body,[Tools getMd5_32Bit_String:MDPassword isUppercase:NO]]];
}
else
{
strsign = [strpathtemp stringByAppendingFormat:@"%@", [NSString stringWithFormat:@"&%@",[Tools getMd5_32Bit_String:MDPassword isUppercase:NO]]];
}
//
strsign = [Tools getMd5_32Bit_String:strsign isUppercase:NO];
NSString *strback = [NSString stringWithFormat:@"?%@&signature=%@",strpathtemp,strsign];
// strback = [[NSString alloc] initWithCString:[strback cStringUsingEncoding:NSUTF8StringEncoding] encoding:NSUTF8StringEncoding];
// strback = [Tools stringEncode:strback];
return strback;
}
///key
-(NSString *)dicSort:(NSDictionary *)dicadd
{
NSArray *arrkeys = dicadd.allKeys;
//
NSArray *arrtesult = [arrkeys sortedArrayUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
return [obj1 compare:obj2 options:NSLiteralSearch]; //
}];
NSString *strpathtemp = @"";
for(NSString *key in arrtesult)
{
if(strpathtemp.length==0)
{
strpathtemp = [NSString stringWithFormat:@"%@=%@",key,[dicadd objectForKey:key]];
}
else
{
strpathtemp = [strpathtemp stringByAppendingFormat:@"&%@=%@",key,[dicadd objectForKey:key]];
}
}
return strpathtemp;
}
@end

View File

@ -0,0 +1,36 @@
//
// ExampleCorrectList.h
// ProductApp
//
// Created by 工作 on 2024/10/21.
//
#import "BaseModel.h"
#import "TextbookInfoModel.h"
NS_ASSUME_NONNULL_BEGIN
@class ExampleCorrectListData,ExampleCorrectListDataItems;
@interface ExampleCorrectList : BaseModel
///
@property (nonatomic , strong) ExampleCorrectListData *data;
@end
@interface ExampleCorrectListData : NSObject
///
@property (nonatomic , strong) NSArray *items;
@end
@interface ExampleCorrectListDataItems : NSObject
///
@property (nonatomic , strong) NSString *ID;
///
@property (nonatomic , strong) NSString *role_id;
///
@property (nonatomic , strong) NSString *title;
@property (nonatomic , strong) NSString *content;
///
@property (nonatomic , strong) NSArray *input_image;
///
@property (nonatomic , strong) NSArray *output_image;
///
@property (nonatomic , strong) TextbookInfoModelDataResult *result;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,28 @@
//
// ExampleCorrectList.m
// ProductApp
//
// Created by on 2024/10/21.
//
#import "ExampleCorrectList.h"
@implementation ExampleCorrectList
+ (NSDictionary *)modelContainerPropertyGenericClass {
return @{@"data" : [ExampleCorrectListData class]};
}
@end
@implementation ExampleCorrectListData
+ (NSDictionary *)modelContainerPropertyGenericClass {
return @{@"items" : [ExampleCorrectListDataItems class]};
}
@end
@implementation ExampleCorrectListDataItems
+ (nullable NSDictionary<NSString *, id> *)modelCustomPropertyMapper
{
return @{@"ID" : @"id"};
}
+ (NSDictionary *)modelContainerPropertyGenericClass {
return @{@"result" : [TextbookInfoModelDataResult class]};
}
@end

View File

@ -0,0 +1,31 @@
//
// ExampleWriteList.h
// ProductApp
//
// Created by 工作 on 2024/10/21.
//
#import "BaseModel.h"
NS_ASSUME_NONNULL_BEGIN
@class ExampleWriteListData,ExampleWriteListDataItems;
@interface ExampleWriteList : BaseModel
///
@property (nonatomic , strong) ExampleWriteListData *data;
@end
@interface ExampleWriteListData : NSObject
///
@property (nonatomic , strong) NSArray *items;
@end
@interface ExampleWriteListDataItems : NSObject
///
@property (nonatomic , strong) NSString *ID;
///
@property (nonatomic , strong) NSString *role_id;
///
@property (nonatomic , strong) NSString *title;
///
@property (nonatomic , strong) NSArray *condition;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,25 @@
//
// ExampleWriteList.m
// ProductApp
//
// Created by on 2024/10/21.
//
#import "ExampleWriteList.h"
@implementation ExampleWriteList
+ (NSDictionary *)modelContainerPropertyGenericClass {
return @{@"data" : [ExampleWriteListData class]};
}
@end
@implementation ExampleWriteListData
+ (NSDictionary *)modelContainerPropertyGenericClass {
return @{@"items" : [ExampleWriteListDataItems class]};
}
@end
@implementation ExampleWriteListDataItems
+ (nullable NSDictionary<NSString *, id> *)modelCustomPropertyMapper
{
return @{@"ID" : @"id"};
}
@end

View File

@ -25,6 +25,8 @@ NS_ASSUME_NONNULL_BEGIN
///
@property (nonatomic , strong) NSArray *node;
@property (nonatomic , assign) BOOL select;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,40 @@
//
// TextbookDetailModel.h
// ProductApp
//
// Created by 工作 on 2024/10/21.
//
#import "BaseModel.h"
NS_ASSUME_NONNULL_BEGIN
@class TextbookDetailModelData;
@interface TextbookDetailModel : BaseModel
///
@property (nonatomic , strong) TextbookDetailModelData *data;
@end
@interface TextbookDetailModelData : NSObject
///
@property (nonatomic , strong) NSString *ID;
///
@property (nonatomic , strong) NSString *grade;
///
@property (nonatomic , strong) NSString *season;
///
@property (nonatomic , strong) NSString *unit;
///
@property (nonatomic , strong) NSString *genre;
///
@property (nonatomic , strong) NSString *total_score;
///
@property (nonatomic , strong) NSString *word_count;
///
@property (nonatomic , strong) NSString *title;
///
@property (nonatomic , strong) NSString *content;
///
@property (nonatomic , strong) NSString *standard;
///年级
@property (nonatomic , strong) NSString *grade_name;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,21 @@
//
// TextbookDetailModel.m
// ProductApp
//
// Created by on 2024/10/21.
//
#import "TextbookDetailModel.h"
@implementation TextbookDetailModel
+ (NSDictionary *)modelContainerPropertyGenericClass {
return @{@"data" : [TextbookDetailModelData class]};
}
@end
@implementation TextbookDetailModelData
+ (nullable NSDictionary<NSString *, id> *)modelCustomPropertyMapper
{
return @{@"ID" : @"id"};
}
@end

View File

@ -41,6 +41,10 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic , strong) NSArray *split_review;
///
@property (nonatomic , strong) NSString *total_score;
///角度
@property (nonatomic , strong) NSString *outline;
///建议
@property (nonatomic , strong) NSString *suggest;
@end

View File

@ -0,0 +1,17 @@
//
// XieYiAlterView.h
// ProductApp
//
// Created by 工作 on 2024/10/21.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
typedef void(^XieYiAlterViewBack)(void);
@interface XieYiAlterView : UIView
///
@property (nonatomic , strong) XieYiAlterViewBack backValue;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,132 @@
//
// XieYiAlterView.m
// ProductApp
//
// Created by on 2024/10/21.
//
#import "XieYiAlterView.h"
#import "WkWebviewViewController.h"
@interface XieYiAlterView ()
@end
@implementation XieYiAlterView
-(id)initWithFrame:(CGRect)frame
{
if(self = [super initWithFrame:frame])
{
[self setBackgroundColor:RGBACOLOR(0, 0, 0, 0.4)];
UIView *viewback = [[UIView alloc] init];
[viewback setBackgroundColor:[UIColor whiteColor]];
[self addSubview:viewback];
[viewback mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.offset(50);
make.right.equalTo(self).offset(-50);
make.centerY.equalTo(self);
}];
[viewback.layer setMasksToBounds:YES];
[viewback.layer setCornerRadius:15];
UILabel *lbname = [[UILabel alloc] init];
[lbname setText:@"感谢您使用极光写作APP"];
[lbname setTextColor:RGBCOLOR(108, 119, 246)];
[lbname setTextAlignment:NSTextAlignmentCenter];
[lbname setFont:[UIFont boldSystemFontOfSize:16]];
[viewback addSubview:lbname];
[lbname mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.offset(20);
make.centerX.equalTo(viewback);
}];
YYLabel *lbinfo = [[YYLabel alloc] init];
[lbinfo setText:@"请你务必审慎阅读、充分理解服务协议和隐私政策各条款,包括但不限于:为了更好的向你提供服务,我们需要访问你的相册、录屏、位置信息等。你可阅读《隐私政策》了解详细信息。如果你同意,请点击下面同意按钮开始接受我们的服务。"];
[lbinfo setTextColor:RGBCOLOR(60, 60, 60)];
[lbinfo setTextAlignment:NSTextAlignmentLeft];
[lbinfo setFont:[UIFont systemFontOfSize:12]];
[lbinfo setNumberOfLines:0];
[viewback addSubview:lbinfo];
float fh = [Tools getLabelHeightWithText:lbinfo.text width:UISCREEN_WIDTH-128 font:12 linHeight:5]+2;
[lbinfo mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.offset(20);
make.right.equalTo(viewback).offset(-20);
make.top.equalTo(lbname.mas_bottom).offset(20);
make.height.offset(fh);
}];
NSMutableAttributedString *noteStr = [[NSMutableAttributedString alloc]initWithString:lbinfo.text];
NSMutableParagraphStyle *style = [NSMutableParagraphStyle new];
style.lineSpacing = 5;
style.lineBreakMode = NSLineBreakByTruncatingTail;
[noteStr addAttribute:NSParagraphStyleAttributeName value:style range:NSMakeRange(0, lbinfo.text.length)];
noteStr.yy_font = [UIFont boldSystemFontOfSize:12.0f];
noteStr.yy_color = RGBCOLOR(60, 60, 60);
[noteStr yy_setTextHighlightRange:NSMakeRange(70, 6) color:MainColor backgroundColor:[UIColor whiteColor] tapAction:^(UIView * _Nonnull containerView, NSAttributedString * _Nonnull text, NSRange range, CGRect rect) {
NSLog(@"隐私政策");
[self pushXieYiTag];
}];
lbinfo.attributedText = noteStr;
UIButton *btok = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, UISCREEN_WIDTH-196, 40)];
[btok setTitle:@"同意并继续" forState:UIControlStateNormal];
[btok setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[btok.titleLabel setFont:[UIFont systemFontOfSize:14]];
[btok setBackgroundColor:MainColor];
[viewback addSubview:btok];
[btok mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.offset(48);
make.right.equalTo(viewback).offset(-48);
make.top.equalTo(lbinfo.mas_bottom).offset(20);
make.height.offset(40);
}];
[btok addTarget:self action:@selector(okAction) forControlEvents:UIControlEventTouchUpInside];
[btok.layer setMasksToBounds:YES];
[btok.layer setCornerRadius:20];
[Tools changedView:btok colors:MainJBColors startPoint:CGPointMake(0, 0) endPoint:CGPointMake(1, 0)];
UIButton *btdis = [[UIButton alloc] init];
[btdis setTitle:@"不同意" forState:UIControlStateNormal];
[btdis setTitleColor:RGBCOLOR(102, 102, 102) forState:UIControlStateNormal];
[btdis.titleLabel setFont:[UIFont systemFontOfSize:12]];
[viewback addSubview:btdis];
[btdis mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.equalTo(btok);
make.top.equalTo(btok.mas_bottom);
make.height.offset(42);
}];
[btdis addTarget:self action:@selector(disAction) forControlEvents:UIControlEventTouchUpInside];
[viewback mas_makeConstraints:^(MASConstraintMaker *make) {
make.bottom.equalTo(btdis);
}];
}
return self;
}
-(void)pushXieYiTag
{
WkWebviewViewController *vc = [[WkWebviewViewController alloc] init];
vc.strtitle = @"隐私政策";
vc.strurl = UserYinSiUrl;
[self.viewController.navigationController pushViewController:vc animated:YES];
}
-(void)okAction
{
if(self.backValue)
{
self.backValue();
}
[self removeFromSuperview];
}
-(void)disAction
{
[HXHud showMessage:@"需要同意才能使用APP" afterDelayType:0];
}
@end

View File

@ -14,8 +14,6 @@
@interface StartNJViewController ()<UICollectionViewDelegate,UICollectionViewDataSource>
///
@property (nonatomic , strong) UICollectionView *collect;
///
@property (nonatomic , strong) NSMutableArray *arrData;
///
@property (nonatomic , strong) NSArray *arrGetData;
@ -130,47 +128,30 @@
[scvback mas_makeConstraints:^(MASConstraintMaker *make) {
make.bottom.equalTo(btnext).offset(30);
}];
[self setdata];
[self getNianJiData];
}
-(void)setdata
{
NSArray *arr = @[@[@"一年级",@"二年级",@"三年级",@"四年级",@"五年级",@"六年级"],@[@"七年级",@"八年级",@"九年级"],@[@"高一",@"高二",@"高三"]];
self.arrData = [NSMutableArray new];
for(NSArray *arrtemp in arr)
{
NSMutableArray *arritem = [NSMutableArray new];
for(NSString *str in arrtemp)
{
baseInfoModel *model = [baseInfoModel new];
model.title = str;
[arritem addObject:model];
}
[self.arrData addObject:arritem];
}
[self.collect reloadData];
}
-(void)nextAction
{
NSMutableArray *arrselect = [NSMutableArray new];
for(NSArray *arr in self.arrData)
for(RoleTreeModelData *modelone in self.arrGetData)
{
for(baseInfoModel *model in arr)
for(RoleTreeModelData *model in modelone.node)
{
if(model.select)
{
[arrselect addObject:model.title];
[arrselect addObject:model];
}
}
}
if(arrselect.count==0)
{
[HXHud showMessage:@"请选择年级" afterDelayType:0];
return;
}
RoleTreeModelData *modelfirst = arrselect.firstObject;
NSString *strpid = @"";
NSString *strtitle = arrselect.firstObject;
NSString *strtitle = modelfirst.name;
if(arrselect.count>1)
{
NSString *strnj = @"";
@ -216,16 +197,16 @@
-(void)btHeaderAction:(UIButton *)sender
{
sender.selected = YES;
for(NSArray *arr in self.arrData)
for(RoleTreeModelData *modelone in self.arrGetData)
{
for(baseInfoModel *model in arr)
for(RoleTreeModelData *model in modelone.node)
{
model.select = NO;
}
}
NSArray *arr = self.arrData[sender.tag];
for(baseInfoModel *model in arr)
RoleTreeModelData *modelone = self.arrGetData[sender.tag];
for(RoleTreeModelData *model in modelone.node)
{
model.select = sender.selected;
}
@ -234,18 +215,18 @@
#pragma mark - UICollectionView
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return self.arrData.count;
return self.arrGetData.count;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
NSArray *arr = self.arrData[section];
return arr.count;
RoleTreeModelData *modelone = self.arrGetData[section];
return modelone.node.count;
}
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
TextCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"TextCollectionViewCell" forIndexPath:indexPath];
NSArray *arr = self.arrData[indexPath.section];
cell.model = arr[indexPath.row];
RoleTreeModelData *modelone = self.arrGetData[indexPath.section];
cell.model = modelone.node[indexPath.row];
return cell;
}
//section
@ -293,9 +274,11 @@
[header.btselect setTag:indexPath.section];
[header.btselect addTarget:self action:@selector(btHeaderAction:) forControlEvents:UIControlEventTouchUpInside];
NSArray *arr = self.arrData[indexPath.section];
RoleTreeModelData *modelone = self.arrGetData[indexPath.section];
NSArray *arr = modelone.node;
BOOL isselectAll = YES;
for(baseInfoModel *model in arr)
for(RoleTreeModelData *model in arr)
{
if(model.select == NO)
{
@ -323,8 +306,9 @@
}
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSArray *arr = self.arrData[indexPath.section];
baseInfoModel *model = arr[indexPath.row];
RoleTreeModelData *modelone = self.arrGetData[indexPath.section];
NSArray *arr = modelone.node;
RoleTreeModelData *model = arr[indexPath.row];
[self setSelectNoModel];
model.select = YES;
[self.collect reloadData];
@ -332,9 +316,9 @@
-(void)setSelectNoModel
{
for(NSArray *arr in self.arrData)
for(RoleTreeModelData *modelone in self.arrGetData)
{
for(baseInfoModel *model in arr)
for(RoleTreeModelData *model in modelone.node)
{
model.select = NO;
}
@ -343,12 +327,13 @@
-(void)getNianJiData
{
[HXLoadingHUD showWithStatus:@"" maskType:0];
[LoadAlterView show];
[NetWorkManager requestRoleTreeData:self.view Callback:^(BOOL state, RoleTreeModel *responseObject, NSString * _Nullable describle) {
[HXLoadingHUD dismiss];
[LoadAlterView dismiss];
if(state)
{
self.arrGetData = responseObject.data;
[self.collect reloadData];
}
}];
}

View File

@ -17,7 +17,11 @@
#import <AppTrackingTransparency/AppTrackingTransparency.h>
#import "TabBarController.h"
#import "AppDelegate.h"
#import "XieYiAlterView.h"
#import <UMCommon/UMCommon.h>
#import <UMCommonLog/UMCommonLogHeaders.h>
#import <UMLink/UMLink.h>
@interface StartViewController ()
///
@ -114,6 +118,23 @@
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(network) name:@"huoquidfanotifi" object:nil];
if([[[NSUserDefaults standardUserDefaults] objectForKey:UserXieYiOk] intValue] != 1)
{
XieYiAlterView *viewxy = [[XieYiAlterView alloc] initWithFrame:CGRectMake(0, 0, UISCREEN_WIDTH, UISCREEN_HEIGHT)];
[self.view addSubview:viewxy];
[viewxy setBackValue:^{
[[NSUserDefaults standardUserDefaults] setObject:@"1" forKey:UserXieYiOk];
[self pushVC];
}];
}
if([UserInfoModel shareModel].isloadconfig)
{
if([UserInfoModel shareModel].loginState.intValue == 1)
{
[self pushVC];
}
}
}
-(UILabel *)drawItemView:(UIView *)view title:(NSString *)title tag:(int)tag
@ -293,7 +314,7 @@
[UserInfoModel setConfig:responseObject.data.config];
[UserInfoModel shareModel].isloadconfig = YES;
[self.imgvmeng setHidden:YES];
[self pushVC];
}
else
@ -306,9 +327,23 @@
-(void)pushVC
{
TabBarController *vc = [TabBarController new];
AppDelegate *appde = (AppDelegate *)[UIApplication sharedApplication].delegate;
[appde.window setRootViewController:vc];
if([[[NSUserDefaults standardUserDefaults] objectForKey:UserXieYiOk] intValue] == 1)
{
///
[UMConfigure initWithAppkey:YouMengAppKey channel:@"App Store"];
[UMCommonLogManager setUpUMCommonLogManager];
if([UserInfoModel shareModel].isloadconfig)
{
[self.imgvmeng setHidden:YES];
}
if([[[NSUserDefaults standardUserDefaults] objectForKey:YingDaoYe] intValue] == 1)
{
AppDelegate *appd = (AppDelegate *)[UIApplication sharedApplication].delegate;
[appd.window setRootViewController:[TabBarController new]];
}
}
}
@end

View File

@ -6,12 +6,12 @@
//
#import <UIKit/UIKit.h>
#import "RoleTreeModel.h"
NS_ASSUME_NONNULL_BEGIN
@interface TextCollectionViewCell : UICollectionViewCell
///
@property (nonatomic , strong) baseInfoModel *model;
@property (nonatomic , strong) RoleTreeModelData *model;
@end
NS_ASSUME_NONNULL_END

View File

@ -42,9 +42,9 @@
}
return self;
}
-(void)setModel:(baseInfoModel *)model
-(void)setModel:(RoleTreeModelData *)model
{
self.lbname.text = model.title;
self.lbname.text = [Tools isStringnilkong:model.name];
[self.viewback setBackgroundColor:[UIColor whiteColor]];
[self.lbname setTextColor:RGBCOLOR(26, 26, 26)];
if(model.select)

View File

@ -14,6 +14,7 @@
#import "StartZNPPTViewController.h"
#import "StartPayViewController.h"
#import "RoleTreeModel.h"
@interface StartGNView ()<UIScrollViewDelegate>
///
@ -201,10 +202,15 @@
-(void)setArrNJ:(NSArray *)arrNJ
{
if(arrNJ.count==0)return;
NSString *strvalue = arrNJ.firstObject;
RoleTreeModelData *modeltemp = arrNJ.firstObject;
self.role_id = modeltemp.ID;
NSString *strvalue = modeltemp.name;
if(arrNJ.count>1)
{
strvalue = arrNJ[arrNJ.count/2];
modeltemp = arrNJ[arrNJ.count/2];
strvalue = modeltemp.name;
}
if([strvalue isEqualToString:@"七年级"])
{
@ -238,8 +244,6 @@
}
}
self.role_id = strid;
NSString *strurl = @"";
NSArray *arrbox = [[UserInfoModel shareModel].config objectForKey:@"client.textbook.tabs"];
for(NSDictionary *dic in arrbox)
@ -293,16 +297,25 @@
else if([str isEqualToString:@"yd_xs_2"])
{///
StartPZXZViewController *vc = [StartPZXZViewController new];
vc.strpid = self.strpid;
vc.role_id = self.role_id;
vc.strtitle = self.strtitle;
[self.viewController.navigationController pushViewController:vc animated:YES];
}
else if([str isEqualToString:@"yd_xs_1"])
{///
StartZWPIViewController *vc = [StartZWPIViewController new];
vc.strpid = self.strpid;
vc.role_id = self.role_id;
vc.strtitle = self.strtitle;
[self.viewController.navigationController pushViewController:vc animated:YES];
}
else
{///
StartZNXZViewController *vc = [StartZNXZViewController new];
vc.strpid = self.strpid;
vc.role_id = self.role_id;
vc.strtitle = self.strtitle;
[self.viewController.navigationController pushViewController:vc animated:YES];
}
}

View File

@ -10,7 +10,11 @@
NS_ASSUME_NONNULL_BEGIN
@interface StartZWPIViewController : BaseViewController
@property (nonatomic , strong) NSString *strtitle;
///
@property (nonatomic , strong) NSString *role_id;
///选中了整个年级的教师
@property (nonatomic , strong) NSString *strpid;
@end
NS_ASSUME_NONNULL_END

View File

@ -7,7 +7,7 @@
#import "StartZWPIViewController.h"
#import "StartZWPIView.h"
#import "NetWorkManager.h"
@interface StartZWPIViewController ()
@ -35,7 +35,22 @@
[view mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view);
}];
[view setHidden:YES];
view.strtitle = self.strtitle;
[LoadAlterView show];
[NetWorkManager requestExampleCorrectListData:self.view role_id:[Tools isStringnil:self.strpid].length>0?self.strpid:self.role_id Callback:^(BOOL state, ExampleCorrectList *responseObject, NSString * _Nullable describle) {
[LoadAlterView dismiss];
if(state)
{
[view setHidden:NO];
view.arrdata = responseObject.data.items;
}
else
{
[HXHud showMessage:responseObject.message afterDelayType:1];
}
}];
}

View File

@ -6,11 +6,12 @@
//
#import "JhtBannerCardView.h"
#import "ExampleCorrectList.h"
NS_ASSUME_NONNULL_BEGIN
@interface StartZWPIViewCell : JhtBannerCardView
///
@property (nonatomic , strong) ExampleCorrectListDataItems *model;
@end
NS_ASSUME_NONNULL_END

View File

@ -9,7 +9,10 @@
@interface StartZWPIViewCell ()
///
@property (nonatomic , strong) UILabel *lbname;
///
@property (nonatomic , strong) UIImageView *imgvback;
@end
@implementation StartZWPIViewCell
@ -29,9 +32,10 @@
make.left.right.equalTo(self);
make.height.offset(22);
}];
_lbname = lbname;
UIImageView *imgvback = [[UIImageView alloc] init];
[imgvback setImage:[UIImage imageNamed:@"yd_xs_1"]];
[imgvback setContentMode:UIViewContentModeScaleAspectFill];
[self addSubview:imgvback];
[imgvback mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.equalTo(self);
@ -40,9 +44,19 @@
}];
[imgvback.layer setMasksToBounds:YES];
[imgvback.layer setCornerRadius:20];
_imgvback = imgvback;
}
return self;
}
-(void)setModel:(ExampleCorrectListDataItems *)model
{
_model = model;
self.lbname.text = [Tools isStringnilkong:model.title];
if(model.input_image.count>0)
{
[self.imgvback sd_setImageWithURL:[NSURL URLWithString:model.input_image.firstObject] placeholderImage:nil];
}
}
@end

View File

@ -10,7 +10,9 @@
NS_ASSUME_NONNULL_BEGIN
@interface StartZWPIView : UIView
@property (nonatomic , strong) NSString *strtitle;
///
@property (nonatomic , strong) NSArray *arrdata;
@end
NS_ASSUME_NONNULL_END

Some files were not shown because too many files have changed in this diff Show More