Break the build. Continue switch to submodules. Remove local copy of RSWeb.

This commit is contained in:
Brent Simmons 2018-06-18 16:45:29 -07:00
parent d597631bd6
commit 2927422f1f
43 changed files with 0 additions and 2297 deletions

View File

@ -113,8 +113,6 @@
84AD1EBC2032AF5C00BC20B7 /* SidebarOutlineDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84AD1EBB2032AF5C00BC20B7 /* SidebarOutlineDataSource.swift */; };
84B06FB21ED37DBD00F0B54B /* RSDatabase.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84B06F9D1ED37DA000F0B54B /* RSDatabase.framework */; };
84B06FB31ED37DBD00F0B54B /* RSDatabase.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 84B06F9D1ED37DA000F0B54B /* RSDatabase.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
84B06FC21ED37E9600F0B54B /* RSWeb.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84B06FBD1ED37E8C00F0B54B /* RSWeb.framework */; };
84B06FC31ED37E9600F0B54B /* RSWeb.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 84B06FBD1ED37E8C00F0B54B /* RSWeb.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
84B06FCF1ED37F7D00F0B54B /* DB5.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84B06FCC1ED37F7200F0B54B /* DB5.framework */; };
84B06FD01ED37F7D00F0B54B /* DB5.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 84B06FCC1ED37F7200F0B54B /* DB5.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
84B06FE91ED3803A00F0B54B /* RSFeedFinder.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84B06FE61ED3803200F0B54B /* RSFeedFinder.framework */; };
@ -311,34 +309,6 @@
remoteGlobalIDString = 84F22C541B52E0D9000060CE;
remoteInfo = RSDatabase;
};
84B06FBC1ED37E8C00F0B54B /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 84B06FB61ED37E8B00F0B54B /* RSWeb.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 849C08B61E0CAC85006B03FA;
remoteInfo = RSWeb;
};
84B06FBE1ED37E8C00F0B54B /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 84B06FB61ED37E8B00F0B54B /* RSWeb.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 849C08BF1E0CAC86006B03FA;
remoteInfo = RSWebTests;
};
84B06FC01ED37E8C00F0B54B /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 84B06FB61ED37E8B00F0B54B /* RSWeb.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 849C08D51E0CACA3006B03FA;
remoteInfo = RSWebiOS;
};
84B06FC41ED37E9600F0B54B /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 84B06FB61ED37E8B00F0B54B /* RSWeb.xcodeproj */;
proxyType = 1;
remoteGlobalIDString = 849C08B51E0CAC85006B03FA;
remoteInfo = RSWeb;
};
84B06FCB1ED37F7200F0B54B /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 84B06FC61ED37F7200F0B54B /* DB5.xcodeproj */;
@ -419,7 +389,6 @@
84B06FEA1ED3803A00F0B54B /* RSFeedFinder.framework in Embed Frameworks */,
846E773E1F6EF67A00A165E2 /* Account.framework in Embed Frameworks */,
84B06FD01ED37F7D00F0B54B /* DB5.framework in Embed Frameworks */,
84B06FC31ED37E9600F0B54B /* RSWeb.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
@ -569,7 +538,6 @@
84AD1EB92031649C00BC20B7 /* SmartFeedPasteboardWriter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SmartFeedPasteboardWriter.swift; sourceTree = "<group>"; };
84AD1EBB2032AF5C00BC20B7 /* SidebarOutlineDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SidebarOutlineDataSource.swift; sourceTree = "<group>"; };
84B06F961ED37DA000F0B54B /* RSDatabase.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RSDatabase.xcodeproj; path = Frameworks/RSDatabase/RSDatabase.xcodeproj; sourceTree = "<group>"; };
84B06FB61ED37E8B00F0B54B /* RSWeb.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RSWeb.xcodeproj; path = Frameworks/RSWeb/RSWeb.xcodeproj; sourceTree = "<group>"; };
84B06FC61ED37F7200F0B54B /* DB5.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = DB5.xcodeproj; path = Frameworks/DB5/DB5.xcodeproj; sourceTree = "<group>"; };
84B06FE01ED3803200F0B54B /* RSFeedFinder.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RSFeedFinder.xcodeproj; path = Frameworks/RSFeedFinder/RSFeedFinder.xcodeproj; sourceTree = "<group>"; };
84B7178B201E66580091657D /* SidebarViewController+ContextualMenus.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SidebarViewController+ContextualMenus.swift"; sourceTree = "<group>"; };
@ -676,7 +644,6 @@
84B06FCF1ED37F7D00F0B54B /* DB5.framework in Frameworks */,
846E773D1F6EF67A00A165E2 /* Account.framework in Frameworks */,
84FB9A2F1EDCD6C4003D53B9 /* Sparkle.framework in Frameworks */,
84B06FC21ED37E9600F0B54B /* RSWeb.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -1072,7 +1039,6 @@
84B06F961ED37DA000F0B54B /* RSDatabase.xcodeproj */,
84B06FE01ED3803200F0B54B /* RSFeedFinder.xcodeproj */,
849B89681F0349C100578A8D /* RSParser.xcodeproj */,
84B06FB61ED37E8B00F0B54B /* RSWeb.xcodeproj */,
);
sourceTree = "<group>";
};
@ -1127,16 +1093,6 @@
name = Products;
sourceTree = "<group>";
};
84B06FB71ED37E8B00F0B54B /* Products */ = {
isa = PBXGroup;
children = (
84B06FBD1ED37E8C00F0B54B /* RSWeb.framework */,
84B06FBF1ED37E8C00F0B54B /* RSWebTests.xctest */,
84B06FC11ED37E8C00F0B54B /* RSWeb.framework */,
);
name = Products;
sourceTree = "<group>";
};
84B06FC71ED37F7200F0B54B /* Products */ = {
isa = PBXGroup;
children = (
@ -1374,7 +1330,6 @@
);
dependencies = (
84B06FB51ED37DBD00F0B54B /* PBXTargetDependency */,
84B06FC51ED37E9600F0B54B /* PBXTargetDependency */,
84B06FD21ED37F7D00F0B54B /* PBXTargetDependency */,
84B06FEC1ED3803A00F0B54B /* PBXTargetDependency */,
849B897F1F0349D000578A8D /* PBXTargetDependency */,
@ -1486,10 +1441,6 @@
ProductGroup = 849B89691F0349C100578A8D /* Products */;
ProjectRef = 849B89681F0349C100578A8D /* RSParser.xcodeproj */;
},
{
ProductGroup = 84B06FB71ED37E8B00F0B54B /* Products */;
ProjectRef = 84B06FB61ED37E8B00F0B54B /* RSWeb.xcodeproj */;
},
);
projectRoot = "";
targets = (
@ -1566,27 +1517,6 @@
remoteRef = 84B06FA01ED37DA000F0B54B /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
84B06FBD1ED37E8C00F0B54B /* RSWeb.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = RSWeb.framework;
remoteRef = 84B06FBC1ED37E8C00F0B54B /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
84B06FBF1ED37E8C00F0B54B /* RSWebTests.xctest */ = {
isa = PBXReferenceProxy;
fileType = wrapper.cfbundle;
path = RSWebTests.xctest;
remoteRef = 84B06FBE1ED37E8C00F0B54B /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
84B06FC11ED37E8C00F0B54B /* RSWeb.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = RSWeb.framework;
remoteRef = 84B06FC01ED37E8C00F0B54B /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
84B06FCC1ED37F7200F0B54B /* DB5.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
@ -1915,11 +1845,6 @@
name = RSDatabase;
targetProxy = 84B06FB41ED37DBD00F0B54B /* PBXContainerItemProxy */;
};
84B06FC51ED37E9600F0B54B /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = RSWeb;
targetProxy = 84B06FC41ED37E9600F0B54B /* PBXContainerItemProxy */;
};
84B06FD21ED37F7D00F0B54B /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = DB5;

View File

@ -1,65 +0,0 @@
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
## Build generated
build/
DerivedData/
## Various settings
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata/
## Other
*.moved-aside
*.xcuserstate
## Obj-C/Swift specific
*.hmap
*.ipa
*.dSYM.zip
*.dSYM
## Playgrounds
timeline.xctimeline
playground.xcworkspace
# Swift Package Manager
#
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
# Packages/
.build/
# CocoaPods
#
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
#
# Pods/
# Carthage
#
# Add this line if you want to avoid checking in source code from Carthage dependencies.
# Carthage/Checkouts
Carthage/Build
# fastlane
#
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
# screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/test_output

View File

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2016 Brent Simmons
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
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 THE
AUTHORS OR COPYRIGHT HOLDERS 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.

View File

@ -1,19 +0,0 @@
# RSWeb
RSWeb is utility code — all Swift — for downloading things from the web. It builds a Mac framework and an iOS framework.
#### Easy way
See `OneShotDownload` for a top-level `download` function that takes a URL and a callback. The callback takes `Data`, `URLResponse`, and `Error` parameters. Its easy.
#### Slightly less easy way
See `DownloadSession` and `DownloadSessionDelegate` for when youre doing a bunch of downloads and you need to track progress.
#### Extras
`HTTPConditionalGetInfo` helps with supporting conditional GET, for when youre downloading things that may not have changed. See [HTTP Conditional Get for RSS Hackers](http://fishbowl.pastiche.org/2002/10/21/http_conditional_get_for_rss_hackers/) for more about conditional GET. This is especially critical when polling for changes, such as with an RSS reader.
`MimeType` could use expansion, but is useful for some cases right now.
`MacWebBrowser` makes it easy to open a URL in the default browser. You can specify whether or not to open in background.

View File

@ -1,568 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
8409DB2C200AE4D700CE879E /* Dictionary+RSWeb.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8409DB2B200AE4D700CE879E /* Dictionary+RSWeb.swift */; };
8409DB2E200AE74400CE879E /* DictionaryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8409DB2D200AE74400CE879E /* DictionaryTests.swift */; };
8409DB30200AE81400CE879E /* String+RSWeb.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8409DB2F200AE81400CE879E /* String+RSWeb.swift */; };
84245C5A1FDC690A0074AFBB /* WebServiceProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84245C591FDC690A0074AFBB /* WebServiceProvider.swift */; };
84245C5B1FDC690A0074AFBB /* WebServiceProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84245C591FDC690A0074AFBB /* WebServiceProvider.swift */; };
84245C5D1FDC697A0074AFBB /* Credentials.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84245C5C1FDC697A0074AFBB /* Credentials.swift */; };
84245C5E1FDC697A0074AFBB /* Credentials.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84245C5C1FDC697A0074AFBB /* Credentials.swift */; };
84245C601FDC69F20074AFBB /* APICall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84245C5F1FDC69F20074AFBB /* APICall.swift */; };
84245C611FDC69F20074AFBB /* APICall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84245C5F1FDC69F20074AFBB /* APICall.swift */; };
84245C6F1FDDCD8C0074AFBB /* HTTPResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84245C6E1FDDCD8C0074AFBB /* HTTPResult.swift */; };
84245C701FDDCD8C0074AFBB /* HTTPResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84245C6E1FDDCD8C0074AFBB /* HTTPResult.swift */; };
84261183200AE918004D89DD /* StringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84261182200AE918004D89DD /* StringTests.swift */; };
842ED2E71E12FB8A000CF738 /* HTTPRequestHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842ED2E61E12FB8A000CF738 /* HTTPRequestHeader.swift */; };
842ED2E81E12FB8A000CF738 /* HTTPRequestHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842ED2E61E12FB8A000CF738 /* HTTPRequestHeader.swift */; };
842ED2EA1E12FB91000CF738 /* HTTPMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842ED2E91E12FB91000CF738 /* HTTPMethod.swift */; };
842ED2EB1E12FB91000CF738 /* HTTPMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842ED2E91E12FB91000CF738 /* HTTPMethod.swift */; };
842ED2ED1E12FB97000CF738 /* HTTPResponseCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842ED2EC1E12FB97000CF738 /* HTTPResponseCode.swift */; };
842ED2EE1E12FB97000CF738 /* HTTPResponseCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842ED2EC1E12FB97000CF738 /* HTTPResponseCode.swift */; };
842ED2F01E12FB9B000CF738 /* HTTPResponseHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842ED2EF1E12FB9B000CF738 /* HTTPResponseHeader.swift */; };
842ED2F11E12FB9B000CF738 /* HTTPResponseHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842ED2EF1E12FB9B000CF738 /* HTTPResponseHeader.swift */; };
842ED2F31E12FBAA000CF738 /* DownloadSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842ED2F21E12FBAA000CF738 /* DownloadSession.swift */; };
842ED2F41E12FBAA000CF738 /* DownloadSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842ED2F21E12FBAA000CF738 /* DownloadSession.swift */; };
842ED2F61E12FBAF000CF738 /* OneShotDownload.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842ED2F51E12FBAF000CF738 /* OneShotDownload.swift */; };
842ED2F71E12FBAF000CF738 /* OneShotDownload.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842ED2F51E12FBAF000CF738 /* OneShotDownload.swift */; };
842ED2F91E12FBB5000CF738 /* DownloadProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842ED2F81E12FBB5000CF738 /* DownloadProgress.swift */; };
842ED2FA1E12FBB5000CF738 /* DownloadProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842ED2F81E12FBB5000CF738 /* DownloadProgress.swift */; };
842ED2FC1E12FBBB000CF738 /* DownloadObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842ED2FB1E12FBBB000CF738 /* DownloadObject.swift */; };
842ED2FD1E12FBBB000CF738 /* DownloadObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842ED2FB1E12FBBB000CF738 /* DownloadObject.swift */; };
842ED2FF1E12FBC1000CF738 /* UserAgent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842ED2FE1E12FBC1000CF738 /* UserAgent.swift */; };
842ED3001E12FBC1000CF738 /* UserAgent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842ED2FE1E12FBC1000CF738 /* UserAgent.swift */; };
842ED3021E12FBC7000CF738 /* HTTPConditionalGetInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842ED3011E12FBC7000CF738 /* HTTPConditionalGetInfo.swift */; };
842ED3031E12FBC7000CF738 /* HTTPConditionalGetInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842ED3011E12FBC7000CF738 /* HTTPConditionalGetInfo.swift */; };
842ED3051E12FBCC000CF738 /* NSMutableURLRequest+RSWeb.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842ED3041E12FBCC000CF738 /* NSMutableURLRequest+RSWeb.swift */; };
842ED3061E12FBCC000CF738 /* NSMutableURLRequest+RSWeb.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842ED3041E12FBCC000CF738 /* NSMutableURLRequest+RSWeb.swift */; };
842ED3081E12FBD2000CF738 /* URLRequest+RSWeb.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842ED3071E12FBD2000CF738 /* URLRequest+RSWeb.swift */; };
842ED3091E12FBD2000CF738 /* URLRequest+RSWeb.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842ED3071E12FBD2000CF738 /* URLRequest+RSWeb.swift */; };
842ED30B1E12FBD8000CF738 /* URL+RSWeb.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842ED30A1E12FBD8000CF738 /* URL+RSWeb.swift */; };
842ED30C1E12FBD8000CF738 /* URL+RSWeb.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842ED30A1E12FBD8000CF738 /* URL+RSWeb.swift */; };
842ED30E1E12FBDD000CF738 /* URLResponse+RSWeb.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842ED30D1E12FBDD000CF738 /* URLResponse+RSWeb.swift */; };
842ED30F1E12FBDD000CF738 /* URLResponse+RSWeb.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842ED30D1E12FBDD000CF738 /* URLResponse+RSWeb.swift */; };
842ED3111E12FBE1000CF738 /* MacWebBrowser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842ED3101E12FBE1000CF738 /* MacWebBrowser.swift */; };
842ED3141E12FBE7000CF738 /* MimeType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842ED3131E12FBE7000CF738 /* MimeType.swift */; };
842ED3151E12FBE7000CF738 /* MimeType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842ED3131E12FBE7000CF738 /* MimeType.swift */; };
849C08C01E0CAC86006B03FA /* RSWeb.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 849C08B61E0CAC85006B03FA /* RSWeb.framework */; };
849C08C51E0CAC86006B03FA /* RSWebTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849C08C41E0CAC86006B03FA /* RSWebTests.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
849C08C11E0CAC86006B03FA /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 849C08AD1E0CAC85006B03FA /* Project object */;
proxyType = 1;
remoteGlobalIDString = 849C08B51E0CAC85006B03FA;
remoteInfo = RSWeb;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
8409DB2B200AE4D700CE879E /* Dictionary+RSWeb.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "Dictionary+RSWeb.swift"; path = "RSWeb/Dictionary+RSWeb.swift"; sourceTree = "<group>"; };
8409DB2D200AE74400CE879E /* DictionaryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DictionaryTests.swift; sourceTree = "<group>"; };
8409DB2F200AE81400CE879E /* String+RSWeb.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "String+RSWeb.swift"; path = "RSWeb/String+RSWeb.swift"; sourceTree = "<group>"; };
84245C591FDC690A0074AFBB /* WebServiceProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebServiceProvider.swift; sourceTree = "<group>"; };
84245C5C1FDC697A0074AFBB /* Credentials.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Credentials.swift; path = RSWeb/Credentials.swift; sourceTree = "<group>"; };
84245C5F1FDC69F20074AFBB /* APICall.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APICall.swift; sourceTree = "<group>"; };
84245C6E1FDDCD8C0074AFBB /* HTTPResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = HTTPResult.swift; path = RSWeb/HTTPResult.swift; sourceTree = "<group>"; };
84261182200AE918004D89DD /* StringTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringTests.swift; sourceTree = "<group>"; };
842ED2E61E12FB8A000CF738 /* HTTPRequestHeader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = HTTPRequestHeader.swift; path = RSWeb/HTTPRequestHeader.swift; sourceTree = "<group>"; };
842ED2E91E12FB91000CF738 /* HTTPMethod.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = HTTPMethod.swift; path = RSWeb/HTTPMethod.swift; sourceTree = "<group>"; };
842ED2EC1E12FB97000CF738 /* HTTPResponseCode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = HTTPResponseCode.swift; path = RSWeb/HTTPResponseCode.swift; sourceTree = "<group>"; };
842ED2EF1E12FB9B000CF738 /* HTTPResponseHeader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = HTTPResponseHeader.swift; path = RSWeb/HTTPResponseHeader.swift; sourceTree = "<group>"; };
842ED2F21E12FBAA000CF738 /* DownloadSession.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DownloadSession.swift; path = RSWeb/DownloadSession.swift; sourceTree = "<group>"; };
842ED2F51E12FBAF000CF738 /* OneShotDownload.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = OneShotDownload.swift; path = RSWeb/OneShotDownload.swift; sourceTree = "<group>"; };
842ED2F81E12FBB5000CF738 /* DownloadProgress.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DownloadProgress.swift; path = RSWeb/DownloadProgress.swift; sourceTree = "<group>"; };
842ED2FB1E12FBBB000CF738 /* DownloadObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DownloadObject.swift; path = RSWeb/DownloadObject.swift; sourceTree = "<group>"; };
842ED2FE1E12FBC1000CF738 /* UserAgent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = UserAgent.swift; path = RSWeb/UserAgent.swift; sourceTree = "<group>"; };
842ED3011E12FBC7000CF738 /* HTTPConditionalGetInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = HTTPConditionalGetInfo.swift; path = RSWeb/HTTPConditionalGetInfo.swift; sourceTree = "<group>"; };
842ED3041E12FBCC000CF738 /* NSMutableURLRequest+RSWeb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "NSMutableURLRequest+RSWeb.swift"; path = "RSWeb/NSMutableURLRequest+RSWeb.swift"; sourceTree = "<group>"; };
842ED3071E12FBD2000CF738 /* URLRequest+RSWeb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "URLRequest+RSWeb.swift"; path = "RSWeb/URLRequest+RSWeb.swift"; sourceTree = "<group>"; };
842ED30A1E12FBD8000CF738 /* URL+RSWeb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "URL+RSWeb.swift"; path = "RSWeb/URL+RSWeb.swift"; sourceTree = "<group>"; };
842ED30D1E12FBDD000CF738 /* URLResponse+RSWeb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "URLResponse+RSWeb.swift"; path = "RSWeb/URLResponse+RSWeb.swift"; sourceTree = "<group>"; };
842ED3101E12FBE1000CF738 /* MacWebBrowser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MacWebBrowser.swift; path = RSWeb/MacWebBrowser.swift; sourceTree = "<group>"; };
842ED3131E12FBE7000CF738 /* MimeType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MimeType.swift; path = RSWeb/MimeType.swift; sourceTree = "<group>"; };
849C08B61E0CAC85006B03FA /* RSWeb.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = RSWeb.framework; sourceTree = BUILT_PRODUCTS_DIR; };
849C08BA1E0CAC85006B03FA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
849C08BF1E0CAC86006B03FA /* RSWebTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RSWebTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
849C08C41E0CAC86006B03FA /* RSWebTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSWebTests.swift; sourceTree = "<group>"; };
849C08C61E0CAC86006B03FA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
849C08D51E0CACA3006B03FA /* RSWeb.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = RSWeb.framework; sourceTree = BUILT_PRODUCTS_DIR; };
849C08D81E0CACA3006B03FA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
D511EF2120242EDA00712EC3 /* RSWeb_project_debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = RSWeb_project_debug.xcconfig; sourceTree = "<group>"; };
D511EF2220242EDA00712EC3 /* RSWeb_project.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = RSWeb_project.xcconfig; sourceTree = "<group>"; };
D511EF2320242EDA00712EC3 /* RSWeb_target.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = RSWeb_target.xcconfig; sourceTree = "<group>"; };
D511EF2420242EDA00712EC3 /* RSWeb_project_release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = RSWeb_project_release.xcconfig; sourceTree = "<group>"; };
D511EF2520242EDA00712EC3 /* RSWebTests_target.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = RSWebTests_target.xcconfig; sourceTree = "<group>"; };
D511EF32202464A100712EC3 /* RSWeb_mac_target.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = RSWeb_mac_target.xcconfig; sourceTree = "<group>"; };
D511EF33202464A200712EC3 /* RSWeb_ios_target.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = RSWeb_ios_target.xcconfig; sourceTree = "<group>"; };
D511EF34202464A200712EC3 /* RSWeb_ios_target_release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = RSWeb_ios_target_release.xcconfig; sourceTree = "<group>"; };
D511EF35202464A200712EC3 /* RSWeb_ios_target_debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = RSWeb_ios_target_debug.xcconfig; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
849C08B21E0CAC85006B03FA /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
849C08BC1E0CAC86006B03FA /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
849C08C01E0CAC86006B03FA /* RSWeb.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
849C08D11E0CACA3006B03FA /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
84245C581FDC690A0074AFBB /* WebServices */ = {
isa = PBXGroup;
children = (
84245C591FDC690A0074AFBB /* WebServiceProvider.swift */,
84245C5F1FDC69F20074AFBB /* APICall.swift */,
);
name = WebServices;
path = RSWeb/WebServices;
sourceTree = "<group>";
};
842ED2D41E11FE8B000CF738 /* Constants */ = {
isa = PBXGroup;
children = (
842ED2E61E12FB8A000CF738 /* HTTPRequestHeader.swift */,
842ED2E91E12FB91000CF738 /* HTTPMethod.swift */,
842ED2EC1E12FB97000CF738 /* HTTPResponseCode.swift */,
842ED2EF1E12FB9B000CF738 /* HTTPResponseHeader.swift */,
);
name = Constants;
sourceTree = "<group>";
};
849C08AC1E0CAC85006B03FA = {
isa = PBXGroup;
children = (
842ED2D41E11FE8B000CF738 /* Constants */,
849C09231E0CAD67006B03FA /* Downloading */,
842ED30A1E12FBD8000CF738 /* URL+RSWeb.swift */,
8409DB2B200AE4D700CE879E /* Dictionary+RSWeb.swift */,
8409DB2F200AE81400CE879E /* String+RSWeb.swift */,
842ED3131E12FBE7000CF738 /* MimeType.swift */,
842ED3101E12FBE1000CF738 /* MacWebBrowser.swift */,
84245C5C1FDC697A0074AFBB /* Credentials.swift */,
84245C6E1FDDCD8C0074AFBB /* HTTPResult.swift */,
84245C581FDC690A0074AFBB /* WebServices */,
849C08B81E0CAC85006B03FA /* RSWeb */,
849C08C31E0CAC86006B03FA /* RSWebTests */,
849C08D61E0CACA3006B03FA /* RSWebiOS */,
849C08B71E0CAC85006B03FA /* Products */,
D511EF2020242EDA00712EC3 /* xcconfig */,
);
sourceTree = "<group>";
};
849C08B71E0CAC85006B03FA /* Products */ = {
isa = PBXGroup;
children = (
849C08B61E0CAC85006B03FA /* RSWeb.framework */,
849C08BF1E0CAC86006B03FA /* RSWebTests.xctest */,
849C08D51E0CACA3006B03FA /* RSWeb.framework */,
);
name = Products;
sourceTree = "<group>";
};
849C08B81E0CAC85006B03FA /* RSWeb */ = {
isa = PBXGroup;
children = (
849C08BA1E0CAC85006B03FA /* Info.plist */,
);
path = RSWeb;
sourceTree = "<group>";
};
849C08C31E0CAC86006B03FA /* RSWebTests */ = {
isa = PBXGroup;
children = (
849C08C41E0CAC86006B03FA /* RSWebTests.swift */,
8409DB2D200AE74400CE879E /* DictionaryTests.swift */,
84261182200AE918004D89DD /* StringTests.swift */,
849C08C61E0CAC86006B03FA /* Info.plist */,
);
path = RSWebTests;
sourceTree = "<group>";
};
849C08D61E0CACA3006B03FA /* RSWebiOS */ = {
isa = PBXGroup;
children = (
849C08D81E0CACA3006B03FA /* Info.plist */,
);
path = RSWebiOS;
sourceTree = "<group>";
};
849C09231E0CAD67006B03FA /* Downloading */ = {
isa = PBXGroup;
children = (
842ED2F21E12FBAA000CF738 /* DownloadSession.swift */,
842ED2F81E12FBB5000CF738 /* DownloadProgress.swift */,
842ED2F51E12FBAF000CF738 /* OneShotDownload.swift */,
842ED2FB1E12FBBB000CF738 /* DownloadObject.swift */,
842ED2FE1E12FBC1000CF738 /* UserAgent.swift */,
842ED3011E12FBC7000CF738 /* HTTPConditionalGetInfo.swift */,
842ED3071E12FBD2000CF738 /* URLRequest+RSWeb.swift */,
842ED3041E12FBCC000CF738 /* NSMutableURLRequest+RSWeb.swift */,
842ED30D1E12FBDD000CF738 /* URLResponse+RSWeb.swift */,
);
name = Downloading;
sourceTree = "<group>";
};
D511EF2020242EDA00712EC3 /* xcconfig */ = {
isa = PBXGroup;
children = (
D511EF2220242EDA00712EC3 /* RSWeb_project.xcconfig */,
D511EF2120242EDA00712EC3 /* RSWeb_project_debug.xcconfig */,
D511EF2420242EDA00712EC3 /* RSWeb_project_release.xcconfig */,
D511EF2320242EDA00712EC3 /* RSWeb_target.xcconfig */,
D511EF33202464A200712EC3 /* RSWeb_ios_target.xcconfig */,
D511EF35202464A200712EC3 /* RSWeb_ios_target_debug.xcconfig */,
D511EF34202464A200712EC3 /* RSWeb_ios_target_release.xcconfig */,
D511EF32202464A100712EC3 /* RSWeb_mac_target.xcconfig */,
D511EF2520242EDA00712EC3 /* RSWebTests_target.xcconfig */,
);
path = xcconfig;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
849C08B31E0CAC85006B03FA /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
849C08D21E0CACA3006B03FA /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
849C08B51E0CAC85006B03FA /* RSWeb */ = {
isa = PBXNativeTarget;
buildConfigurationList = 849C08CA1E0CAC86006B03FA /* Build configuration list for PBXNativeTarget "RSWeb" */;
buildPhases = (
849C08B11E0CAC85006B03FA /* Sources */,
849C08B21E0CAC85006B03FA /* Frameworks */,
849C08B31E0CAC85006B03FA /* Headers */,
849C08B41E0CAC85006B03FA /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = RSWeb;
productName = RSWeb;
productReference = 849C08B61E0CAC85006B03FA /* RSWeb.framework */;
productType = "com.apple.product-type.framework";
};
849C08BE1E0CAC86006B03FA /* RSWebTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 849C08CD1E0CAC86006B03FA /* Build configuration list for PBXNativeTarget "RSWebTests" */;
buildPhases = (
849C08BB1E0CAC86006B03FA /* Sources */,
849C08BC1E0CAC86006B03FA /* Frameworks */,
849C08BD1E0CAC86006B03FA /* Resources */,
);
buildRules = (
);
dependencies = (
849C08C21E0CAC86006B03FA /* PBXTargetDependency */,
);
name = RSWebTests;
productName = RSWebTests;
productReference = 849C08BF1E0CAC86006B03FA /* RSWebTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
849C08D41E0CACA3006B03FA /* RSWebiOS */ = {
isa = PBXNativeTarget;
buildConfigurationList = 849C08DA1E0CACA3006B03FA /* Build configuration list for PBXNativeTarget "RSWebiOS" */;
buildPhases = (
849C08D01E0CACA3006B03FA /* Sources */,
849C08D11E0CACA3006B03FA /* Frameworks */,
849C08D21E0CACA3006B03FA /* Headers */,
849C08D31E0CACA3006B03FA /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = RSWebiOS;
productName = RSWebiOS;
productReference = 849C08D51E0CACA3006B03FA /* RSWeb.framework */;
productType = "com.apple.product-type.framework";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
849C08AD1E0CAC85006B03FA /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0820;
LastUpgradeCheck = 0930;
ORGANIZATIONNAME = "Ranchero Software";
TargetAttributes = {
849C08B51E0CAC85006B03FA = {
CreatedOnToolsVersion = 8.2.1;
DevelopmentTeam = 9C84TZ7Q6Z;
LastSwiftMigration = 0820;
ProvisioningStyle = Automatic;
};
849C08BE1E0CAC86006B03FA = {
CreatedOnToolsVersion = 8.2.1;
DevelopmentTeam = 9C84TZ7Q6Z;
ProvisioningStyle = Automatic;
};
849C08D41E0CACA3006B03FA = {
CreatedOnToolsVersion = 8.2.1;
DevelopmentTeam = 9C84TZ7Q6Z;
LastSwiftMigration = 0820;
ProvisioningStyle = Automatic;
};
};
};
buildConfigurationList = 849C08B01E0CAC85006B03FA /* Build configuration list for PBXProject "RSWeb" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = 849C08AC1E0CAC85006B03FA;
productRefGroup = 849C08B71E0CAC85006B03FA /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
849C08B51E0CAC85006B03FA /* RSWeb */,
849C08BE1E0CAC86006B03FA /* RSWebTests */,
849C08D41E0CACA3006B03FA /* RSWebiOS */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
849C08B41E0CAC85006B03FA /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
849C08BD1E0CAC86006B03FA /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
849C08D31E0CACA3006B03FA /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
849C08B11E0CAC85006B03FA /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
84245C5A1FDC690A0074AFBB /* WebServiceProvider.swift in Sources */,
842ED2F01E12FB9B000CF738 /* HTTPResponseHeader.swift in Sources */,
842ED2FF1E12FBC1000CF738 /* UserAgent.swift in Sources */,
842ED2FC1E12FBBB000CF738 /* DownloadObject.swift in Sources */,
842ED30E1E12FBDD000CF738 /* URLResponse+RSWeb.swift in Sources */,
842ED2F61E12FBAF000CF738 /* OneShotDownload.swift in Sources */,
842ED2F31E12FBAA000CF738 /* DownloadSession.swift in Sources */,
842ED3081E12FBD2000CF738 /* URLRequest+RSWeb.swift in Sources */,
842ED3051E12FBCC000CF738 /* NSMutableURLRequest+RSWeb.swift in Sources */,
842ED2E71E12FB8A000CF738 /* HTTPRequestHeader.swift in Sources */,
8409DB30200AE81400CE879E /* String+RSWeb.swift in Sources */,
842ED3111E12FBE1000CF738 /* MacWebBrowser.swift in Sources */,
842ED3141E12FBE7000CF738 /* MimeType.swift in Sources */,
84245C5D1FDC697A0074AFBB /* Credentials.swift in Sources */,
84245C6F1FDDCD8C0074AFBB /* HTTPResult.swift in Sources */,
84245C601FDC69F20074AFBB /* APICall.swift in Sources */,
842ED30B1E12FBD8000CF738 /* URL+RSWeb.swift in Sources */,
842ED2F91E12FBB5000CF738 /* DownloadProgress.swift in Sources */,
842ED2EA1E12FB91000CF738 /* HTTPMethod.swift in Sources */,
842ED3021E12FBC7000CF738 /* HTTPConditionalGetInfo.swift in Sources */,
8409DB2C200AE4D700CE879E /* Dictionary+RSWeb.swift in Sources */,
842ED2ED1E12FB97000CF738 /* HTTPResponseCode.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
849C08BB1E0CAC86006B03FA /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
849C08C51E0CAC86006B03FA /* RSWebTests.swift in Sources */,
84261183200AE918004D89DD /* StringTests.swift in Sources */,
8409DB2E200AE74400CE879E /* DictionaryTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
849C08D01E0CACA3006B03FA /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
842ED3091E12FBD2000CF738 /* URLRequest+RSWeb.swift in Sources */,
842ED2F71E12FBAF000CF738 /* OneShotDownload.swift in Sources */,
842ED30F1E12FBDD000CF738 /* URLResponse+RSWeb.swift in Sources */,
842ED2E81E12FB8A000CF738 /* HTTPRequestHeader.swift in Sources */,
842ED3001E12FBC1000CF738 /* UserAgent.swift in Sources */,
842ED2FA1E12FBB5000CF738 /* DownloadProgress.swift in Sources */,
842ED2EB1E12FB91000CF738 /* HTTPMethod.swift in Sources */,
84245C701FDDCD8C0074AFBB /* HTTPResult.swift in Sources */,
842ED2F11E12FB9B000CF738 /* HTTPResponseHeader.swift in Sources */,
84245C611FDC69F20074AFBB /* APICall.swift in Sources */,
842ED3061E12FBCC000CF738 /* NSMutableURLRequest+RSWeb.swift in Sources */,
842ED2F41E12FBAA000CF738 /* DownloadSession.swift in Sources */,
84245C5E1FDC697A0074AFBB /* Credentials.swift in Sources */,
842ED2EE1E12FB97000CF738 /* HTTPResponseCode.swift in Sources */,
842ED30C1E12FBD8000CF738 /* URL+RSWeb.swift in Sources */,
842ED3151E12FBE7000CF738 /* MimeType.swift in Sources */,
84245C5B1FDC690A0074AFBB /* WebServiceProvider.swift in Sources */,
842ED3031E12FBC7000CF738 /* HTTPConditionalGetInfo.swift in Sources */,
842ED2FD1E12FBBB000CF738 /* DownloadObject.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
849C08C21E0CAC86006B03FA /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 849C08B51E0CAC85006B03FA /* RSWeb */;
targetProxy = 849C08C11E0CAC86006B03FA /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
849C08C81E0CAC86006B03FA /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = D511EF2120242EDA00712EC3 /* RSWeb_project_debug.xcconfig */;
buildSettings = {
};
name = Debug;
};
849C08C91E0CAC86006B03FA /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = D511EF2420242EDA00712EC3 /* RSWeb_project_release.xcconfig */;
buildSettings = {
};
name = Release;
};
849C08CB1E0CAC86006B03FA /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = D511EF32202464A100712EC3 /* RSWeb_mac_target.xcconfig */;
buildSettings = {
};
name = Debug;
};
849C08CC1E0CAC86006B03FA /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = D511EF32202464A100712EC3 /* RSWeb_mac_target.xcconfig */;
buildSettings = {
};
name = Release;
};
849C08CE1E0CAC86006B03FA /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = D511EF2520242EDA00712EC3 /* RSWebTests_target.xcconfig */;
buildSettings = {
};
name = Debug;
};
849C08CF1E0CAC86006B03FA /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = D511EF2520242EDA00712EC3 /* RSWebTests_target.xcconfig */;
buildSettings = {
};
name = Release;
};
849C08DB1E0CACA3006B03FA /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = D511EF35202464A200712EC3 /* RSWeb_ios_target_debug.xcconfig */;
buildSettings = {
};
name = Debug;
};
849C08DC1E0CACA3006B03FA /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = D511EF34202464A200712EC3 /* RSWeb_ios_target_release.xcconfig */;
buildSettings = {
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
849C08B01E0CAC85006B03FA /* Build configuration list for PBXProject "RSWeb" */ = {
isa = XCConfigurationList;
buildConfigurations = (
849C08C81E0CAC86006B03FA /* Debug */,
849C08C91E0CAC86006B03FA /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
849C08CA1E0CAC86006B03FA /* Build configuration list for PBXNativeTarget "RSWeb" */ = {
isa = XCConfigurationList;
buildConfigurations = (
849C08CB1E0CAC86006B03FA /* Debug */,
849C08CC1E0CAC86006B03FA /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
849C08CD1E0CAC86006B03FA /* Build configuration list for PBXNativeTarget "RSWebTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
849C08CE1E0CAC86006B03FA /* Debug */,
849C08CF1E0CAC86006B03FA /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
849C08DA1E0CACA3006B03FA /* Build configuration list for PBXNativeTarget "RSWebiOS" */ = {
isa = XCConfigurationList;
buildConfigurations = (
849C08DB1E0CACA3006B03FA /* Debug */,
849C08DC1E0CACA3006B03FA /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 849C08AD1E0CAC85006B03FA /* Project object */;
}

View File

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:RSWeb.xcodeproj">
</FileRef>
</Workspace>

View File

@ -1,16 +0,0 @@
//
// Credentials.swift
// RSWeb
//
// Created by Brent Simmons on 12/9/17.
// Copyright © 2017 Ranchero Software. All rights reserved.
//
import Foundation
public protocol Credentials {
var username: String? { get set }
var password: String? { get set }
}

View File

@ -1,46 +0,0 @@
//
// Dictionary+RSWeb.swift
// RSWeb
//
// Created by Brent Simmons on 1/13/18.
// Copyright © 2018 Ranchero Software. All rights reserved.
//
import Foundation
public extension Dictionary {
public func urlQueryString() -> String? {
// Turn a dictionary into string like foo=bar&param2=some%20thing
// Return nil if empty dictionary.
if isEmpty {
return nil
}
var s = ""
var numberAdded = 0
for (key, value) in self {
guard let key = key as? String, let value = value as? String else {
continue
}
guard let encodedKey = key.encodedForURLQuery(), let encodedValue = value.encodedForURLQuery() else {
continue
}
if numberAdded > 0 {
s += "&"
}
s += "\(encodedKey)=\(encodedValue)"
numberAdded += 1
}
if numberAdded < 1 {
return nil
}
return s
}
}

View File

@ -1,30 +0,0 @@
//
// DownloadObject.swift
// RSWeb
//
// Created by Brent Simmons on 8/3/16.
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
//
import Foundation
public final class DownloadObject: Hashable {
public let url: URL
public var data = Data()
public var hashValue: Int {
return url.hashValue
}
public init(url: URL) {
self.url = url
}
public static func ==(lhs: DownloadObject, rhs: DownloadObject) -> Bool {
return lhs.url == rhs.url && lhs.data == rhs.data
}
}

View File

@ -1,76 +0,0 @@
//
// DownloadProgress.swift
// RSWeb
//
// Created by Brent Simmons on 9/17/16.
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
//
import Foundation
public extension Notification.Name {
public static let DownloadProgressDidChange = Notification.Name(rawValue: "DownloadProgressDidChange")
}
public final class DownloadProgress {
public var numberOfTasks = 0 {
didSet {
if numberOfTasks == 0 {
numberRemaining = 0
}
if numberOfTasks != oldValue {
postDidChangeNotification()
}
}
}
public var numberRemaining = 0 {
didSet {
if numberRemaining != oldValue {
postDidChangeNotification()
}
}
}
public var numberCompleted: Int {
var n = numberOfTasks - numberRemaining
if n < 0 {
n = 0
}
if n > numberOfTasks {
n = numberOfTasks
}
return n
}
public var isComplete: Bool {
return numberRemaining < 1
}
public init(numberOfTasks: Int) {
self.numberOfTasks = numberOfTasks
}
public func addToNumberOfTasks(_ n: Int) {
numberOfTasks = numberOfTasks + n
}
public func clear() {
numberOfTasks = 0
}
}
// MARK: - Private
private extension DownloadProgress {
func postDidChangeNotification() {
NotificationCenter.default.post(name: .DownloadProgressDidChange, object: self)
}
}

View File

@ -1,311 +0,0 @@
//
// DownloadSession.swift
// RSWeb
//
// Created by Brent Simmons on 3/12/16.
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
//
import Foundation
// Create a DownloadSessionDelegate, then create a DownloadSession.
// To download things: call downloadObjects, with a set of represented objects, to download things. DownloadSession will call the various delegate methods.
public protocol DownloadSessionDelegate {
func downloadSession(_ downloadSession: DownloadSession, requestForRepresentedObject: AnyObject) -> URLRequest?
func downloadSession(_ downloadSession: DownloadSession, downloadDidCompleteForRepresentedObject: AnyObject, response: URLResponse?, data: Data, error: NSError?)
func downloadSession(_ downloadSession: DownloadSession, shouldContinueAfterReceivingData: Data, representedObject: AnyObject) -> Bool
func downloadSession(_ downloadSession: DownloadSession, didReceiveUnexpectedResponse: URLResponse, representedObject: AnyObject)
func downloadSession(_ downloadSession: DownloadSession, didReceiveNotModifiedResponse: URLResponse, representedObject: AnyObject)
}
@objc public final class DownloadSession: NSObject {
public var progress = DownloadProgress(numberOfTasks: 0)
private var urlSession: URLSession!
private var tasksInProgress = Set<URLSessionTask>()
private var tasksPending = Set<URLSessionTask>()
private var taskIdentifierToInfoDictionary = [Int: DownloadInfo]()
private let representedObjects = NSMutableSet()
private let delegate: DownloadSessionDelegate
private var redirectCache = [String: String]()
public init(delegate: DownloadSessionDelegate) {
self.delegate = delegate
super.init()
let sessionConfiguration = URLSessionConfiguration.default
sessionConfiguration.requestCachePolicy = .reloadIgnoringLocalCacheData
sessionConfiguration.timeoutIntervalForRequest = 60.0
sessionConfiguration.httpShouldSetCookies = false
sessionConfiguration.httpCookieAcceptPolicy = .never
sessionConfiguration.httpMaximumConnectionsPerHost = 2
sessionConfiguration.httpCookieStorage = nil
sessionConfiguration.urlCache = nil
if let userAgentHeaders = UserAgent.headers() {
sessionConfiguration.httpAdditionalHeaders = userAgentHeaders
}
urlSession = URLSession(configuration: sessionConfiguration, delegate: self, delegateQueue: OperationQueue.main)
}
deinit {
urlSession.invalidateAndCancel()
}
// MARK: - API
public func cancel() {
// TODO
}
public func downloadObjects(_ objects: NSSet) {
var numberOfTasksAdded = 0
for oneObject in objects {
if !representedObjects.contains(oneObject) {
representedObjects.add(oneObject)
addDataTask(oneObject as AnyObject)
numberOfTasksAdded += 1
}
}
progress.addToNumberOfTasks(numberOfTasksAdded)
updateProgress()
}
}
// MARK: - URLSessionTaskDelegate
extension DownloadSession: URLSessionTaskDelegate {
public func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
tasksInProgress.remove(task)
guard let info = infoForTask(task) else {
return
}
info.error = error
delegate.downloadSession(self, downloadDidCompleteForRepresentedObject: info.representedObject, response: info.urlResponse, data: info.data as Data, error: error as NSError?)
removeTask(task)
}
public func urlSession(_ session: URLSession, task: URLSessionTask, willPerformHTTPRedirection response: HTTPURLResponse, newRequest request: URLRequest, completionHandler: @escaping (URLRequest?) -> Void) {
if response.statusCode == 301 || response.statusCode == 308 {
if let oldURLString = task.originalRequest?.url?.absoluteString, let newURLString = request.url?.absoluteString {
cacheRedirect(oldURLString, newURLString)
}
}
completionHandler(request)
}
}
// MARK: - URLSessionDataDelegate
extension DownloadSession: URLSessionDataDelegate {
public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
tasksInProgress.insert(dataTask)
tasksPending.remove(dataTask)
if let info = infoForTask(dataTask) {
info.urlResponse = response
}
if response.forcedStatusCode == 304 {
if let representedObject = infoForTask(dataTask)?.representedObject {
delegate.downloadSession(self, didReceiveNotModifiedResponse: response, representedObject: representedObject)
}
completionHandler(.cancel)
removeTask(dataTask)
return
}
if !response.statusIsOK {
if let representedObject = infoForTask(dataTask)?.representedObject {
delegate.downloadSession(self, didReceiveUnexpectedResponse: response, representedObject: representedObject)
}
completionHandler(.cancel)
removeTask(dataTask)
return
}
completionHandler(.allow)
}
public func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
guard let info = infoForTask(dataTask) else {
return
}
info.addData(data)
if !delegate.downloadSession(self, shouldContinueAfterReceivingData: info.data as Data, representedObject: info.representedObject) {
info.canceled = true
dataTask.cancel()
removeTask(dataTask)
}
}
}
// MARK: - Private
private extension DownloadSession {
func updateProgress() {
progress.numberRemaining = tasksInProgress.count + tasksPending.count
if progress.numberRemaining < 1 {
progress.clear()
representedObjects.removeAllObjects()
}
}
func addDataTask(_ representedObject: AnyObject) {
guard let request = delegate.downloadSession(self, requestForRepresentedObject: representedObject) else {
return
}
var requestToUse = request
// If received permanent redirect earlier, use that URL.
if let urlString = request.url?.absoluteString, let redirectedURLString = cachedRedirectForURLString(urlString) {
if let redirectedURL = URL(string: redirectedURLString) {
requestToUse.url = redirectedURL
}
}
let task = urlSession.dataTask(with: requestToUse)
let info = DownloadInfo(representedObject, urlRequest: requestToUse)
taskIdentifierToInfoDictionary[task.taskIdentifier] = info
tasksPending.insert(task)
task.resume()
}
func infoForTask(_ task: URLSessionTask) -> DownloadInfo? {
return taskIdentifierToInfoDictionary[task.taskIdentifier]
}
func removeTask(_ task: URLSessionTask) {
tasksInProgress.remove(task)
tasksPending.remove(task)
taskIdentifierToInfoDictionary[task.taskIdentifier] = nil
updateProgress()
}
func urlStringIsBlackListedRedirect(_ urlString: String) -> Bool {
// Hotels and similar often do permanent redirects. We can catch some of those.
let s = urlString.lowercased()
let badStrings = ["solutionip", "lodgenet", "monzoon", "landingpage", "btopenzone", "register", "login", "authentic"]
for oneBadString in badStrings {
if s.contains(oneBadString) {
return true
}
}
return false
}
func cacheRedirect(_ oldURLString: String, _ newURLString: String) {
if urlStringIsBlackListedRedirect(newURLString) {
return
}
redirectCache[oldURLString] = newURLString
}
func cachedRedirectForURLString(_ urlString: String) -> String? {
// Follow chains of redirects, but avoid loops.
var urlStrings = Set<String>()
urlStrings.insert(urlString)
var currentString = urlString
while(true) {
if let oneRedirectString = redirectCache[currentString] {
if urlStrings.contains(oneRedirectString) {
// Cycle. Bail.
return nil
}
urlStrings.insert(oneRedirectString)
currentString = oneRedirectString
}
else {
break
}
}
return currentString == urlString ? nil : currentString
}
}
// MARK: - DownloadInfo
private final class DownloadInfo {
let representedObject: AnyObject
let urlRequest: URLRequest
let data = NSMutableData()
var error: Error?
var urlResponse: URLResponse?
var canceled = false
var statusCode: Int {
return urlResponse?.forcedStatusCode ?? 0
}
init(_ representedObject: AnyObject, urlRequest: URLRequest) {
self.representedObject = representedObject
self.urlRequest = urlRequest
}
func addData(_ d: Data) {
data.append(d)
}
}

View File

@ -1,58 +0,0 @@
//
// HTTPConditionalGetInfo.swift
// RSWeb
//
// Created by Brent Simmons on 4/11/16.
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
//
import Foundation
public struct HTTPConditionalGetInfo {
public let lastModified: String?
public let etag: String?
public var dictionary: [String: String] {
var d = [String: String]()
if let lastModified = lastModified {
d[HTTPResponseHeader.lastModified] = lastModified
}
if let etag = etag {
d[HTTPResponseHeader.etag] = etag
}
return d
}
public init?(lastModified: String?, etag: String?) {
if lastModified == nil && etag == nil {
return nil
}
self.lastModified = lastModified
self.etag = etag
}
public init?(urlResponse: HTTPURLResponse) {
let lastModified = urlResponse.valueForHTTPHeaderField(HTTPResponseHeader.lastModified)
let etag = urlResponse.valueForHTTPHeaderField(HTTPResponseHeader.etag)
self.init(lastModified: lastModified, etag: etag)
}
public init?(dictionary: [String: String]) {
self.init(lastModified: dictionary[HTTPResponseHeader.lastModified], etag: dictionary[HTTPResponseHeader.etag])
}
public func addRequestHeadersToURLRequest(_ urlRequest: NSMutableURLRequest) {
if let lastModified = lastModified {
urlRequest.addValue(lastModified, forHTTPHeaderField: HTTPRequestHeader.ifModifiedSince)
}
if let etag = etag {
urlRequest.addValue(etag, forHTTPHeaderField: HTTPRequestHeader.ifNoneMatch)
}
}
}

View File

@ -1,18 +0,0 @@
//
// HTTPMethod.swift
// RSWeb
//
// Created by Brent Simmons on 12/26/16.
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
//
import Foundation
public struct HTTPMethod {
public static let get = "GET"
public static let post = "POST"
public static let put = "PUT"
public static let patch = "PATCH"
public static let delete = "DELETE"
}

View File

@ -1,21 +0,0 @@
//
// HTTPRequestHeader.swift
// RSWeb
//
// Created by Brent Simmons on 12/26/16.
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
//
import Foundation
public struct HTTPRequestHeader {
public static let userAgent = "User-Agent"
public static let authorization = "Authorization"
public static let contentType = "Content-Type"
// Conditional GET
public static let ifModifiedSince = "If-Modified-Since"
public static let ifNoneMatch = "If-None-Match" //Etag
}

View File

@ -1,61 +0,0 @@
//
// HTTPResponseCode.swift
// RSWeb
//
// Created by Brent Simmons on 12/26/16.
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
//
import Foundation
public struct HTTPResponseCode {
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
// Not an enum because the main interest is the actual values.
public static let responseContinue = 100 //"continue" is a language keyword, hence the weird name
public static let switchingProtocols = 101
public static let OK = 200
public static let created = 201
public static let accepted = 202
public static let nonAuthoritativeInformation = 203
public static let noContent = 204
public static let resetContent = 205
public static let partialContent = 206
public static let redirectMultipleChoices = 300
public static let redirectPermanent = 301
public static let redirectTemporary = 302
public static let redirectSeeOther = 303
public static let notModified = 304
public static let useProxy = 305
public static let unused = 306
public static let redirectVeryTemporary = 307
public static let badRequest = 400
public static let unauthorized = 401
public static let paymentRequired = 402
public static let forbidden = 403
public static let notFound = 404
public static let methodNotAllowed = 405
public static let notAcceptable = 406
public static let proxyAuthenticationRequired = 407
public static let requestTimeout = 408
public static let conflict = 409
public static let gone = 410
public static let lengthRequired = 411
public static let preconditionFailed = 412
public static let entityTooLarge = 413
public static let URITooLong = 414
public static let unsupportedMediaType = 415
public static let requestedRangeNotSatisfiable = 416
public static let expectationFailed = 417
public static let internalServerError = 500
public static let notImplemented = 501
public static let badGateway = 502
public static let serviceUnavailable = 503
public static let gatewayTimeout = 504
public static let HTTPVersionNotSupported = 505
}

View File

@ -1,20 +0,0 @@
//
// HTTPResponseHeader.swift
// RSWeb
//
// Created by Brent Simmons on 12/26/16.
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
//
import Foundation
public struct HTTPResponseHeader {
public static let contentType = "Content-Type"
// Conditional GET. See:
// http://fishbowl.pastiche.org/2002/10/21/http_conditional_get_for_rss_hackers/
public static let lastModified = "Last-Modified"
public static let etag = "ETag"
}

View File

@ -1,25 +0,0 @@
//
// HTTPResult.swift
// RSWeb
//
// Created by Brent Simmons on 12/10/17.
// Copyright © 2017 Ranchero Software. All rights reserved.
//
import Foundation
public struct HTTPResult {
public let url: URL
public let data: Data?
public let response: URLResponse?
public let error: Error?
public init(url: URL, data: Data?, response: URLResponse?, error: Error?) {
self.url = url
self.data = data
self.response = response
self.error = error
}
}

View File

@ -1,26 +0,0 @@
<?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>en</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>1.0</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2016 Ranchero Software, LLC. All rights reserved.</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>

View File

@ -1,44 +0,0 @@
//
// MacWebBrowser.swift
// RSWeb
//
// Created by Brent Simmons on 12/27/16.
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
//
import AppKit
public class MacWebBrowser {
@discardableResult public class func openURL(_ url: URL, inBackground: Bool) -> Bool {
guard let preparedURL = url.preparedForOpeningInBrowser() else {
return false
}
if (inBackground) {
do {
try NSWorkspace.shared.open(preparedURL, options: [.withoutActivation], configuration: [:])
return true
}
catch {
return false
}
}
return NSWorkspace.shared.open(preparedURL)
}
}
private extension URL {
func preparedForOpeningInBrowser() -> URL? {
var urlString = absoluteString.replacingOccurrences(of: " ", with: "%20")
urlString = urlString.replacingOccurrences(of: "^", with: "%5E")
urlString = urlString.replacingOccurrences(of: "&amp;", with: "&")
urlString = urlString.replacingOccurrences(of: "&#38;", with: "&")
return URL(string: urlString)
}
}

View File

@ -1,55 +0,0 @@
//
// MimeType.swift
// RSWeb
//
// Created by Brent Simmons on 12/26/16.
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
//
import Foundation
public struct MimeType {
// This could certainly use expansion.
public static let png = "image/png"
public static let jpeg = "image/jpeg"
public static let jpg = "image/jpg"
public static let gif = "image/gif"
public static let tiff = "image/tiff"
}
public extension String {
public func isMimeTypeImage() -> Bool {
return self.isOfGeneralMimeType("image")
}
public func isMimeTypeAudio() -> Bool {
return self.isOfGeneralMimeType("audio")
}
public func isMimeTypeVideo() -> Bool {
return self.isOfGeneralMimeType("video")
}
public func isMimeTypeTimeBasedMedia() -> Bool {
return self.isMimeTypeAudio() || self.isMimeTypeVideo()
}
private func isOfGeneralMimeType(_ type: String) -> Bool {
let lower = self.lowercased()
if lower.hasPrefix(type) {
return true
}
if lower.hasPrefix("x-\(type)") {
return true
}
return false
}
}

View File

@ -1,28 +0,0 @@
//
// NSMutableURLRequest+RSWeb.swift
// RSWeb
//
// Created by Brent Simmons on 12/27/16.
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
//
import Foundation
public extension NSMutableURLRequest {
public func addBasicAuthorization(username: String, password: String) -> Bool {
// Do this *only* with https. And not even then if you can help it.
let s = "\(username):\(password)"
guard let d = s.data(using: String.Encoding.utf8, allowLossyConversion: false) else {
return false
}
let base64EncodedString = d.base64EncodedString()
let authorization = "Basic \(base64EncodedString)"
setValue(authorization, forHTTPHeaderField: HTTPRequestHeader.authorization)
return true
}
}

View File

@ -1,146 +0,0 @@
//
// OneShotDownload.swift
// RSWeb
//
// Created by Brent Simmons on 8/27/16.
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
//
import Foundation
public typealias OneShotDownloadCallback = (Data?, URLResponse?, Error?) -> Swift.Void
private final class OneShotDownloadManager {
private let urlSession: URLSession
fileprivate static let shared = OneShotDownloadManager()
public init() {
let sessionConfiguration = URLSessionConfiguration.ephemeral
sessionConfiguration.requestCachePolicy = .reloadIgnoringLocalCacheData
sessionConfiguration.httpShouldSetCookies = false
sessionConfiguration.httpCookieAcceptPolicy = .never
sessionConfiguration.httpMaximumConnectionsPerHost = 2
sessionConfiguration.httpCookieStorage = nil
sessionConfiguration.urlCache = nil
sessionConfiguration.timeoutIntervalForRequest = 30
if let userAgentHeaders = UserAgent.headers() {
sessionConfiguration.httpAdditionalHeaders = userAgentHeaders
}
urlSession = URLSession(configuration: sessionConfiguration)
}
deinit {
urlSession.invalidateAndCancel()
}
public func download(_ url: URL, _ callback: @escaping OneShotDownloadCallback) {
let task = urlSession.dataTask(with: url) { (data, response, error) in
DispatchQueue.main.async() {
callback(data, response, error)
}
}
task.resume()
}
}
// Call this. Its easier than referring to OneShotDownloadManager.
// callback is called on the main queue.
public func download(_ url: URL, _ callback: @escaping OneShotDownloadCallback) {
OneShotDownloadManager.shared.download(url, callback)
}
// MARK: - Downloading using a cache
private struct WebCacheRecord {
let url: URL
let dateDownloaded: Date
let data: Data
let response: URLResponse
}
private final class WebCache {
private var cache = [URL: WebCacheRecord]()
func cleanup(_ cleanupInterval: TimeInterval) {
let cutoffDate = Date(timeInterval: -cleanupInterval, since: Date())
cache.keys.forEach { (key) in
let cacheRecord = self[key]!
if shouldDelete(cacheRecord, cutoffDate) {
cache[key] = nil
}
}
}
private func shouldDelete(_ cacheRecord: WebCacheRecord, _ cutoffDate: Date) -> Bool {
return cacheRecord.dateDownloaded < cutoffDate
}
subscript(_ url: URL) -> WebCacheRecord? {
get {
return cache[url]
}
set {
if let cacheRecord = newValue {
cache[url] = cacheRecord
}
else {
cache[url] = nil
}
}
}
}
// URLSessionConfiguration has a cache policy.
// But we dont know how it works, and the unimplemented parts spook us a bit.
// So we use a cache that works exactly as we want it to work.
private final class DownloadWithCacheManager {
static let shared = DownloadWithCacheManager()
private var cache = WebCache()
private static let timeToLive: TimeInterval = 10 * 60 // 10 minutes
private static let cleanupInterval: TimeInterval = 5 * 60 // clean up the cache at most every 5 minutes
private var lastCleanupDate = Date()
func download(_ url: URL, _ callback: @escaping OneShotDownloadCallback) {
if lastCleanupDate.timeIntervalSinceNow < -(5 * 60) {
lastCleanupDate = Date()
cache.cleanup(DownloadWithCacheManager.timeToLive)
}
let cacheRecord: WebCacheRecord? = cache[url]
if let cacheRecord = cacheRecord {
callback(cacheRecord.data, cacheRecord.response, nil)
return
}
OneShotDownloadManager.shared.download(url) { (data, response, error) in
if let data = data, let response = response, response.statusIsOK, error == nil {
let cacheRecord = WebCacheRecord(url: url, dateDownloaded: Date(), data: data, response: response)
self.cache[url] = cacheRecord
}
callback(data, response, error)
}
}
}
public func downloadUsingCache(_ url: URL, _ callback: @escaping OneShotDownloadCallback) {
DownloadWithCacheManager.shared.download(url, callback)
}

View File

@ -1,20 +0,0 @@
//
// String+RSWeb.swift
// RSWeb
//
// Created by Brent Simmons on 1/13/18.
// Copyright © 2018 Ranchero Software. All rights reserved.
//
import Foundation
public extension String {
public func encodedForURLQuery() -> String? {
guard let encodedString = addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {
return nil
}
return encodedString.replacingOccurrences(of: "&", with: "%38")
}
}

View File

@ -1,69 +0,0 @@
//
// NSURL+RSWeb.swift
// RSWeb
//
// Created by Brent Simmons on 12/26/16.
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
//
import Foundation
private struct URLConstants {
static let schemeHTTP = "http"
static let schemeHTTPS = "https"
static let prefixHTTP = "http://"
static let prefixHTTPS = "https://"
}
public extension URL {
public func isHTTPSURL() -> Bool {
return self.scheme?.lowercased() == URLConstants.schemeHTTPS
}
public func isHTTPURL() -> Bool {
return self.scheme?.lowercased() == URLConstants.schemeHTTP
}
public func isHTTPOrHTTPSURL() -> Bool {
return self.isHTTPSURL() || self.isHTTPURL()
}
public func absoluteStringWithHTTPOrHTTPSPrefixRemoved() -> String? {
// Case-inensitive. Turns http://example.com/foo into example.com/foo
if isHTTPSURL() {
return absoluteString.stringByRemovingCaseInsensitivePrefix(URLConstants.prefixHTTPS)
}
else if isHTTPURL() {
return absoluteString.stringByRemovingCaseInsensitivePrefix(URLConstants.prefixHTTP)
}
return nil
}
}
private extension String {
func stringByRemovingCaseInsensitivePrefix(_ prefix: String) -> String {
// Returns self if it doesnt have the given prefix.
let lowerPrefix = prefix.lowercased()
let lowerSelf = self.lowercased()
if (lowerSelf == lowerPrefix) {
return ""
}
if !lowerSelf.hasPrefix(lowerPrefix) {
return self
}
let index = self.index(self.startIndex, offsetBy: prefix.count)
return String(self[..<index])
}
}

View File

@ -1,29 +0,0 @@
//
// URLRequest+RSWeb.swift
// RSWeb
//
// Created by Brent Simmons on 12/27/16.
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
//
import Foundation
public extension URLRequest {
// Experimental. Returns nil if scheme isn't http or https (about:blank, for instance).
public func loadingURL() -> URL? {
guard let url = mainDocumentURL else {
return nil
}
guard url.isHTTPOrHTTPSURL() else {
return nil
}
guard !url.absoluteString.isEmpty else {
return nil
}
return url
}
}

View File

@ -1,45 +0,0 @@
//
// URLResponse+RSWeb.swift
// RSWeb
//
// Created by Brent Simmons on 8/14/16.
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
//
import Foundation
public extension URLResponse {
public var statusIsOK: Bool {
return forcedStatusCode >= 200 && forcedStatusCode <= 299
}
public var forcedStatusCode: Int {
// Return actual statusCode or -1 if there isnt one.
if let response = self as? HTTPURLResponse {
return response.statusCode
}
return 0
}
}
public extension HTTPURLResponse {
public func valueForHTTPHeaderField(_ headerField: String) -> String? {
// Case-insensitive. HTTP headers may not be in the case you expect.
let lowerHeaderField = headerField.lowercased()
for (key, value) in allHeaderFields {
if lowerHeaderField == (key as? String)?.lowercased() {
return value as? String
}
}
return nil
}
}

View File

@ -1,26 +0,0 @@
//
// UserAgent.swift
// RSWeb
//
// Created by Brent Simmons on 8/27/16.
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
//
import Foundation
public struct UserAgent {
public static func fromInfoPlist() -> String? {
return Bundle.main.object(forInfoDictionaryKey: "UserAgent") as? String
}
public static func headers() -> [AnyHashable: String]? {
guard let userAgent = fromInfoPlist() else {
return nil
}
return [HTTPRequestHeader.userAgent: userAgent]
}
}

View File

@ -1,39 +0,0 @@
//
// APICall.swift
// RSWeb
//
// Created by Brent Simmons on 12/9/17.
// Copyright © 2017 Ranchero Software. All rights reserved.
//
import Foundation
// Main thread only.
public protocol APICallDelegate {
func apiCallURLRequest(_ call: APICall) -> URLRequest?
func apiCall(_ call: APICall, parseReturnedObjectWith: HTTPResult) -> Any?
func apiCall(_ call: APICall, handleErrorWith: HTTPResult, returnedObject: Any?)
func apiCall(_ call: APICall, performActionWith: HTTPResult, returnedObject: Any?)
}
public struct APICall {
public let provider: WebServiceProvider
public let methodName: String
public let identifier: Int
private let delegate: APICallDelegate
private static var incrementingIdentifier = 0
public init(provider: WebServiceProvider, methodName: String, delegate: APICallDelegate) {
self.provider = provider
self.methodName = methodName
self.delegate = delegate
self.identifier = APICall.incrementingIdentifier
APICall.incrementingIdentifier += 1
}
}

View File

@ -1,15 +0,0 @@
//
// WebServiceProvider.swift
// RSWeb
//
// Created by Brent Simmons on 12/9/17.
// Copyright © 2017 Ranchero Software. All rights reserved.
//
import Foundation
public protocol WebServiceProvider {
}

View File

@ -1,45 +0,0 @@
//
// DictionaryTests.swift
// RSWebTests
//
// Created by Brent Simmons on 1/13/18.
// Copyright © 2018 Ranchero Software. All rights reserved.
//
import XCTest
class DictionaryTests: XCTestCase {
func testSimpleQueryString() {
let d = ["foo": "bar", "param1": "This is a value."]
let s = d.urlQueryString()
XCTAssertTrue(s == "foo=bar&param1=This%20is%20a%20value." || s == "param1=This%20is%20a%20value.&foo=bar")
}
func testQueryStringWithAmpersand() {
let d = ["fo&o": "bar", "param1": "This is a&value."]
let s = d.urlQueryString()
XCTAssertTrue(s == "fo%38o=bar&param1=This%20is%20a%38value." || s == "param1=This%20is%20a%38value.&fo%38o=bar")
}
func testQueryStringWithAccentedCharacters() {
let d = ["fée": "bør"]
let s = d.urlQueryString()
XCTAssertTrue(s == "f%C3%A9e=b%C3%B8r")
}
func testQueryStringWithEmoji() {
let d = ["🌴e": "bar🎩🌴"]
let s = d.urlQueryString()
XCTAssertTrue(s == "%F0%9F%8C%B4e=bar%F0%9F%8E%A9%F0%9F%8C%B4")
}
}

View File

@ -1,22 +0,0 @@
<?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>en</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>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>

View File

@ -1,36 +0,0 @@
//
// RSWebTests.swift
// RSWebTests
//
// Created by Brent Simmons on 12/22/16.
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
//
import XCTest
@testable import RSWeb
class RSWebTests: XCTestCase {
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
super.tearDown()
}
func testExample() {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
}
func testPerformanceExample() {
// This is an example of a performance test case.
self.measure {
// Put the code you want to measure the time of here.
}
}
}

View File

@ -1,24 +0,0 @@
//
// StringTests.swift
// RSWebTests
//
// Created by Brent Simmons on 1/13/18.
// Copyright © 2018 Ranchero Software. All rights reserved.
//
import XCTest
class StringTests: XCTestCase {
func testURLQueryEncoding() {
var s = "foo".encodedForURLQuery()
XCTAssertEqual(s, "foo")
s = "foo bar".encodedForURLQuery()
XCTAssertEqual(s, "foo%20bar")
s = "foo bar &well".encodedForURLQuery()
XCTAssertEqual(s, "foo%20bar%20%38well")
}
}

View File

@ -1,26 +0,0 @@
<?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>en</string>
<key>CFBundleDisplayName</key>
<string>RSWeb</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>1.0</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>

View File

@ -1,18 +0,0 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/../Frameworks @loader_path/../Frameworks
INFOPLIST_FILE = RSWebTests/Info.plist
PRODUCT_BUNDLE_IDENTIFIER = com.ranchero.RSWebTests
PRODUCT_NAME = $(TARGET_NAME)
CLANG_ENABLE_OBJC_WEAK = YES

View File

@ -1,19 +0,0 @@
#include "./RSWeb_target.xcconfig"
CODE_SIGN_IDENTITY =
DEVELOPMENT_TEAM = 9C84TZ7Q6Z
// See the notes in Evergreen_target.xcconfig on why the
// DeveloperSettings.xcconfig is #included here
#include? "../../../SharedXcodeSettings/DeveloperSettings.xcconfig"
SDKROOT = iphoneos
TARGETED_DEVICE_FAMILY = 1,2
IPHONEOS_DEPLOYMENT_TARGET = 10.2
LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @loader_path/Frameworks
INFOPLIST_FILE = RSWebiOS/Info.plist
PRODUCT_BUNDLE_IDENTIFIER = com.ranchero.RSWebiOS
PRODUCT_NAME = RSWeb
CLANG_ENABLE_MODULES = YES

View File

@ -1,5 +0,0 @@
#include "./RSWeb_ios_target.xcconfig"
VALIDATE_PRODUCT = NO

View File

@ -1,4 +0,0 @@
#include "./RSWeb_ios_target.xcconfig"
VALIDATE_PRODUCT = YES

View File

@ -1,13 +0,0 @@
#include "./RSWeb_target.xcconfig"
CODE_SIGN_IDENTITY =
DEVELOPMENT_TEAM = 9C84TZ7Q6Z
// See the notes in Evergreen_target.xcconfig on why the
// DeveloperSettings.xcconfig is #included here
#include? "../../../SharedXcodeSettings/DeveloperSettings.xcconfig"
INFOPLIST_FILE = RSWeb/Info.plist
PRODUCT_BUNDLE_IDENTIFIER = com.ranchero.RSWeb

View File

@ -1,69 +0,0 @@
CODE_SIGN_IDENTITY =
SDKROOT = macosx
MACOSX_DEPLOYMENT_TARGET = 10.13
CLANG_ENABLE_OBJC_WEAK = YES
SWIFT_VERSION = 4.0
COMBINE_HIDPI_IMAGES = YES
COPY_PHASE_STRIP = NO
MACOSX_DEPLOYMENT_TARGET = 10.13
ALWAYS_SEARCH_USER_PATHS = NO
CURRENT_PROJECT_VERSION = 1
VERSION_INFO_PREFIX =
VERSIONING_SYSTEM = apple-generic
GCC_NO_COMMON_BLOCKS = YES
GCC_C_LANGUAGE_STANDARD = gnu99
CLANG_CXX_LANGUAGE_STANDARD = gnu++0x
CLANG_CXX_LIBRARY = libc++
CLANG_ENABLE_MODULES = YES
CLANG_ENABLE_OBJC_ARC = YES
ENABLE_STRICT_OBJC_MSGSEND = YES
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES
CLANG_WARN_DOCUMENTATION_COMMENTS = YES
CLANG_WARN_EMPTY_BODY = YES
GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES
GCC_WARN_SHADOW = YES
CLANG_WARN_BOOL_CONVERSION = YES
CLANG_WARN_CONSTANT_CONVERSION = YES
GCC_WARN_64_TO_32_BIT_CONVERSION = YES
CLANG_WARN_ENUM_CONVERSION = YES
CLANG_WARN_INT_CONVERSION = YES
CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES
CLANG_WARN_INFINITE_RECURSION = YES
GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR
GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES
GCC_WARN_ABOUT_MISSING_NEWLINE = YES
CLANG_WARN_ASSIGN_ENUM = YES
GCC_WARN_SIGN_COMPARE = YES
CLANG_WARN_STRICT_PROTOTYPES = YES
CLANG_WARN_COMMA = YES
CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES
GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE
GCC_WARN_UNKNOWN_PRAGMAS = YES
CLANG_WARN_UNREACHABLE_CODE = YES
GCC_WARN_UNUSED_FUNCTION = YES
GCC_WARN_UNUSED_LABEL = YES
GCC_WARN_UNUSED_PARAMETER = YES
GCC_WARN_UNUSED_VARIABLE = YES
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES
CLANG_WARN_SUSPICIOUS_MOVE = YES
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES
GCC_WARN_STRICT_SELECTOR_MATCH = YES
GCC_WARN_UNDECLARED_SELECTOR = YES
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES
RUN_CLANG_STATIC_ANALYZER = YES
CLANG_STATIC_ANALYZER_MODE = deep
CLANG_ANALYZER_NONNULL = YES
CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES
CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES
CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES
SWIFT_TREAT_WARNINGS_AS_ERRORS = YES

View File

@ -1,16 +0,0 @@
#include "./RSWeb_project.xcconfig"
DEBUG_INFORMATION_FORMAT = dwarf
ENABLE_TESTABILITY = YES
GCC_DYNAMIC_NO_PIC = NO
GCC_OPTIMIZATION_LEVEL = 0
GCC_PREPROCESSOR_DEFINITIONS = DEBUG=1 $(inherited)
GCC_TREAT_WARNINGS_AS_ERRORS = YES
MTL_ENABLE_DEBUG_INFO = YES
SWIFT_COMPILATION_MODE = singlefile
SWIFT_OPTIMIZATION_LEVEL = -Onone
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG
ONLY_ACTIVE_ARCH = YES

View File

@ -1,9 +0,0 @@
#include "./RSWeb_project.xcconfig"
DEBUG_INFORMATION_FORMAT = dwarf-with-dsym
ENABLE_NS_ASSERTIONS = NO
MTL_ENABLE_DEBUG_INFO = NO
SWIFT_OPTIMIZATION_LEVEL = -O
SWIFT_COMPILATION_MODE = wholemodule

View File

@ -1,12 +0,0 @@
INSTALL_PATH = $(LOCAL_LIBRARY_DIR)/Frameworks
SKIP_INSTALL = YES
DYLIB_COMPATIBILITY_VERSION = 1
DYLIB_CURRENT_VERSION = 1
DYLIB_INSTALL_NAME_BASE = @rpath
LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/../Frameworks @loader_path/Frameworks
DEFINES_MODULE = YES
FRAMEWORK_VERSION = A
PRODUCT_NAME = $(TARGET_NAME)
CLANG_ENABLE_MODULES = YES