├── Bridging-Header.h
├── Constants.swift
├── Credits.html
├── FileHashMethod.swift
├── Languages.swift
├── MainWindowController.swift
├── MainWindowController.xib
├── OpenSubsAccess.swift
├── Podfile
├── Pods
├── GZIP
│ └── GZIP
│ │ ├── GZIP.h
│ │ └── GZIP.m
├── NSData+Base64
│ ├── NSData+Base64.h
│ └── NSData+Base64.m
├── Pods.xcodeproj
│ ├── project.pbxproj
│ └── xcuserdata
│ │ └── spilja.xcuserdatad
│ │ └── xcschemes
│ │ ├── GZIP.xcscheme
│ │ ├── NSData+Base64.xcscheme
│ │ ├── Pods-Subtitlr.xcscheme
│ │ ├── xcschememanagement.plist
│ │ └── xmlrpc.xcscheme
├── Target Support Files
│ └── Pods-Subtitlr
│ │ ├── Pods-Subtitlr.debug.xcconfig
│ │ └── Pods-Subtitlr.release.xcconfig
└── xmlrpc
│ ├── NSStringAdditions.h
│ ├── NSStringAdditions.m
│ ├── XMLRPC.h
│ ├── XMLRPCConnection.h
│ ├── XMLRPCConnection.m
│ ├── XMLRPCConnectionDelegate.h
│ ├── XMLRPCConnectionManager.h
│ ├── XMLRPCConnectionManager.m
│ ├── XMLRPCDefaultEncoder.h
│ ├── XMLRPCDefaultEncoder.m
│ ├── XMLRPCEncoder.h
│ ├── XMLRPCEventBasedParser.h
│ ├── XMLRPCEventBasedParser.m
│ ├── XMLRPCEventBasedParserDelegate.h
│ ├── XMLRPCEventBasedParserDelegate.m
│ ├── XMLRPCRequest.h
│ ├── XMLRPCRequest.m
│ ├── XMLRPCResponse.h
│ └── XMLRPCResponse.m
├── PopoverController.swift
├── PopoverController.xib
├── README.md
├── Subtitle.swift
├── Subtitlr 2.0
├── AppDelegate.swift
├── Assets.xcassets
│ └── AppIcon.appiconset
│ │ ├── Contents.json
│ │ ├── logo.png
│ │ ├── logo_128.png
│ │ ├── logo_16.png
│ │ ├── logo_256-1.png
│ │ ├── logo_256.png
│ │ ├── logo_32-1.png
│ │ ├── logo_32.png
│ │ ├── logo_512-1.png
│ │ ├── logo_512.png
│ │ └── logo_64.png
├── Info.plist
└── MainMenu.xib
├── Subtitlr 2.0Tests
├── Info.plist
├── OpenSubsAccessTests.swift
└── SubtitlrTests.swift
├── Subtitlr 2.0UITests
├── Info.plist
└── UITests.swift
├── Subtitlr.entitlements
├── Subtitlr.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
└── xcuserdata
│ └── spilja.xcuserdatad
│ └── xcschemes
│ ├── Subtitlr 2.0.xcscheme
│ └── xcschememanagement.plist
├── Video.swift
├── dropzone_img.png
├── dropzone_img@2x.png
├── opensubs-logo.gif
└── opensubs-logo.png
/Bridging-Header.h:
--------------------------------------------------------------------------------
1 | //
2 | // Bridging-Header.h
3 | // subs
4 | //
5 | // Created by Lucija Frković on 22/07/15.
6 | // Copyright © 2015 Lucija Frković. All rights reserved.
7 | //
8 |
9 | #ifndef Bridging_Header_h
10 | #define Bridging_Header_h
11 |
12 |
13 | #import "XMLRPC/XMLRPCConnection.h"
14 | #import "XMLRPC/XMLRPCConnectionDelegate.h"
15 | #import "XMLRPC/XMLRPCConnectionManager.h"
16 | #import "XMLRPC/XMLRPCResponse.h"
17 | #import "XMLRPC/XMLRPCRequest.h"
18 | #import "GZIP/GZIP.h"
19 |
20 | #endif /* Bridging_Header_h */
21 |
22 |
--------------------------------------------------------------------------------
/Constants.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Constants.swift
3 | // subs
4 | //
5 | // Created by Lucija Frković on 29/07/15.
6 | // Copyright © 2015 Lucija Frković. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | struct Constants {
12 |
13 | static let defaultSubtitleLanguage = "eng"
14 | static let OSUserAgent = "eagerMoose"
15 | static let OSconnectionString = "https://api.opensubtitles.org:443/xml-rpc"
16 |
17 | struct OSMethods {
18 | static let logIn = "LogIn"
19 | static let searchSubtitles = "SearchSubtitles"
20 | static let downloadSubtitles = "DownloadSubtitles"
21 | }
22 |
23 | struct Keys {
24 | static let subtitleLanguage = "subtitleLanguage"
25 | }
26 |
27 | static let fileTypes = ["3g2", "3gp", "3gp2", "3gpp", "60d", "ajp", "asf", "asx", "avchd", "avi", "bik", "bix", "box", "cam", "dat", "divx", "dmf", "dv", "dvr-ms", "evo", "flc", "fli", "flic", "flv", "flx", "gvi", "gvp", "h264", "m1v", "m2p", "m2ts", "m2v", "m4e", "m4v", "mjp", "mjpeg", "mjpg", "mkv", "moov", "mov", "movhd", "movie", "movx", "mp4", "mpe", "mpeg", "mpg", "mpv", "mpv2", "mxf", "nsv", "nut", "ogg", "ogm", "omf", "ps", "qt", "ram", "rm", "rmvb", "swf", "ts", "vfw", "vid", "video", "viv", "vivo", "vob", "vro", "wm", "wmv", "wmx", "wrap", "wvx", "wx", "x264", "xvid"]
28 |
29 |
30 | static func getLanguages() -> NSDictionary {
31 | var languages = [String: String]()
32 |
33 | // languages["afr"] = "Afrikaans"
34 | // languages["alb"] = "Albanian"
35 | // languages["ara"] = "Arabic"
36 | // languages["arm"] = "Armenian"
37 | // languages["baq"] = "Basque"
38 | // languages["bel"] = "Belarusian"
39 | // languages["ben"] = "Bengali"
40 | // languages["bos"] = "Bosnian"
41 | // languages["bre"] = "Breton"
42 | // languages["bul"] = "Bulgarian"
43 | // languages["bur"] = "Burmese"
44 | // languages["cat"] = "Catalan"
45 | // languages["chi"] = "Chinese (simplified)"
46 | // languages["zht"] = "Chinese (traditional)"
47 | // languages["zhe"] = "Chinese bilingual"
48 | // languages["hrv"] = "Croatian"
49 | // languages["cze"] = "Czech"
50 | // languages["dan"] = "Danish"
51 | // languages["dut"] = "Dutch"
52 | // languages["eng"] = "English"
53 | // languages["epo"] = "Esperanto"
54 | // languages["est"] = "Estonian"
55 | // languages["fin"] = "Finnish"
56 | // languages["fre"] = "French"
57 | // languages["glg"] = "Galician"
58 | // languages["geo"] = "Georgian"
59 | // languages["ger"] = "German"
60 | // languages["ell"] = "Greek"
61 | // languages["heb"] = "Hebrew"
62 | // languages["hin"] = "Hindi"
63 | // languages["hun"] = "Hungarian"
64 | // languages["ice"] = "Icelandic"
65 | // languages["ind"] = "Indonesian"
66 | // languages["ita"] = "Italian"
67 | // languages["jpn"] = "Japanese"
68 | // languages["kaz"] = "Kazakh"
69 | // languages["khm"] = "Khmer"
70 | // languages["kor"] = "Korean"
71 | // languages["lav"] = "Latvian"
72 | // languages["lit"] = "Lithuanian"
73 | // languages["ltz"] = "Luxembourgish"
74 | // languages["mac"] = "Macedonian"
75 | // languages["may"] = "Malay"
76 | // languages["mal"] = "Malayalam"
77 | // languages["mni"] = "Manipuri"
78 | // languages["mon"] = "Mongolian"
79 | // languages["mne"] = "Montenegrin"
80 | // languages["nor"] = "Norwegian"
81 | // languages["oci"] = "Occitan"
82 | // languages["per"] = "Persian"
83 | // languages["pol"] = "Polish"
84 | // languages["por"] = "Portuguese"
85 | // languages["pob"] = "Portuguese (BR)"
86 | // languages["rum"] = "Romanian"
87 | // languages["rus"] = "Russian"
88 | // languages["scc"] = "Serbian"
89 | // languages["sin"] = "Sinhalese"
90 | // languages["slo"] = "Slovak"
91 | // languages["slv"] = "Slovenian"
92 | // languages["spa"] = "Spanish"
93 | // languages["swa"] = "Swahili"
94 | // languages["swe"] = "Swedish"
95 | // languages["syr"] = "Syriac"
96 | // languages["tgl"] = "Tagalog"
97 | // languages["tam"] = "Tamil"
98 | // languages["tel"] = "Telugu"
99 | // languages["tha"] = "Thai"
100 | // languages["tur"] = "Turkish"
101 | // languages["ukr"] = "Ukrainian"
102 | // languages["urd"] = "Urdu"
103 | // languages["vie"] = "Vietnamese"
104 |
105 | languages["Afrikaans"] = "afr"
106 | languages["Albanian"] = "alb"
107 | languages["Arabic"] = "ara"
108 | languages["Armenian"] = "arm"
109 | languages["Basque"] = "baq"
110 | languages["Belarusian"] = "bel"
111 | languages["Bengali"] = "ben"
112 | languages["Bosnian"] = "bos"
113 | languages["Breton"] = "bre"
114 | languages["Bulgarian"] = "bul"
115 | languages["Burmese"] = "bur"
116 | languages["Catalan"] = "cat"
117 | languages["Chinese (simplified)"] = "chi"
118 | languages["Chinese (traditional)"] = "zht"
119 | languages["Chinese bilingual"] = "zhe"
120 | languages["Croatian"] = "hrv"
121 | languages["Czech"] = "cze"
122 | languages["Danish"] = "dan"
123 | languages["Dutch"] = "dut"
124 | languages["English"] = "eng"
125 | languages["Esperanto"] = "epo"
126 | languages["Estonian"] = "est"
127 | languages["Finnish"] = "fin"
128 | languages["French"] = "fre"
129 | languages["Galician"] = "glg"
130 | languages["Georgian"] = "geo"
131 | languages["German"] = "ger"
132 | languages["Greek"] = "ell"
133 | languages["Hebrew"] = "heb"
134 | languages["Hindi"] = "hin"
135 | languages["Hungarian"] = "hun"
136 | languages["Icelandic"] = "ice"
137 | languages["Indonesian"] = "ind"
138 | languages["Italian"] = "ita"
139 | languages["Japanese"] = "jpn"
140 | languages["Kazakh"] = "kaz"
141 | languages["Khmer"] = "khm"
142 | languages["Korean"] = "kor"
143 | languages["Latvian"] = "lav"
144 | languages["Lithuanian"] = "lit"
145 | languages["Luxembourgish"] = "ltz"
146 | languages["Macedonian"] = "mac"
147 | languages["Malay"] = "may"
148 | languages["Malayalam"] = "mal"
149 | languages["Manipuri"] = "mni"
150 | languages["Mongolian"] = "mon"
151 | languages["Montenegrin"] = "mne"
152 | languages["Norwegian"] = "nor"
153 | languages["Occitan"] = "oci"
154 | languages["Persian"] = "per"
155 | languages["Polish"] = "pol"
156 | languages["Portuguese"] = "por"
157 | languages["Portuguese (BR)"] = "pob"
158 | languages["Romanian"] = "rum"
159 | languages["Russian"] = "rus"
160 | languages["Serbian"] = "scc"
161 | languages["Sinhalese"] = "sin"
162 | languages["Slovak"] = "slo"
163 | languages["Slovenian"] = "slv"
164 | languages["Spanish"] = "spa"
165 | languages["Swahili"] = "swa"
166 | languages["Swedish"] = "swe"
167 | languages["Syriac"] = "syr"
168 | languages["Tagalog"] = "tgl"
169 | languages["Tamil"] = "tam"
170 | languages["Telugu"] = "tel"
171 | languages["Thai"] = "tha"
172 | languages["Turkish"] = "tur"
173 | languages["Ukrainian"] = "ukr"
174 | languages["Urdu"] = "urd"
175 | languages["Vietnamese"] = "vie"
176 |
177 | return languages
178 | }
179 |
180 | }
--------------------------------------------------------------------------------
/Credits.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
18 |
19 |
20 |
21 |
Nikac Nikac, mali bik!
22 |
23 |
Subtitle service provided by OpenSubtitles.org
24 |
25 |
OSX App Sandboxing & "Related Items" tutorial Copyright (c) 2015 Stefano Vettor
26 |
27 |
28 |
Cocoa XML-RPC Framework (MIT license - see below) Copyright (c) 2012 Eric Czarny
29 |
30 |
GZIP (zlib license - see below) Copyright (C) 2012 Charcoal Design
31 |
32 |
CocoaPods
33 | (MIT license - see below)
34 | Copyright (c) 2011 - 2015 Eloy Durán ,
35 | Fabio Pelosin ,
36 | Samuel Giddins ,
37 | Marius Rackwitz ,
38 | Kyle Fuller ,
39 | Boris Bügling ,
40 | Orta Therox , and
41 | Olivier Halligon .
42 |
43 |
44 |
45 |
MIT License
46 |
47 |
48 | Permission is hereby granted, free of charge, to any person obtaining a copy of
49 | this software and associated documentation files (the "Software"), to deal in
50 | the Software without restriction, including without limitation the rights to
51 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
52 | of the Software, and to permit persons to whom the Software is furnished to do
53 | so, subject to the following conditions:
54 |
55 | The above copyright notice and this permission notice shall be included in all
56 | copies or substantial portions of the Software.
57 |
58 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
59 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
60 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
61 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
62 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
63 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
64 | SOFTWARE.
65 |
66 |
67 |
68 |
BSD License
69 |
70 | This software is provided 'as-is', without any express or implied
71 | warranty. In no event will the authors be held liable for any damages
72 | arising from the use of this software.
73 |
74 | Permission is granted to anyone to use this software for any purpose,
75 | including commercial applications, and to alter it and redistribute it
76 | freely, subject to the following restrictions:
77 |
78 | 1. The origin of this software must not be misrepresented; you must not
79 | claim that you wrote the original software. If you use this software
80 | in a product, an acknowledgment in the product documentation would be
81 | appreciated but is not required.
82 |
83 | 2. Altered source versions must be plainly marked as such, and must not be
84 | misrepresented as being the original software.
85 |
86 | 3. This notice may not be removed or altered from any source distribution.
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/FileHashMethod.swift:
--------------------------------------------------------------------------------
1 | //
2 | // FileHashMethod.swift
3 | // OpenSubsProj
4 | //
5 | // Created by Lucija Frković on 26/03/15.
6 | // Copyright (c) 2015 Lucija Frković. All rights reserved.
7 | // Based on Objective-C hash implementation for Mac by subsmarine.com
8 |
9 | import Foundation
10 |
11 | class FileHash {
12 |
13 | struct VideoHash {
14 | var fileHash: UInt64;
15 | var fileSize: UInt64;
16 | init() {
17 | fileHash = 0;
18 | fileSize = 0;
19 | }
20 | }
21 |
22 | func stringForHash(hash: UInt64) -> NSString {
23 | return NSString(format: "%qx", hash)
24 | }
25 |
26 |
27 | func hashForPath(path: NSString) -> VideoHash {
28 | var hash = VideoHash();
29 |
30 | let readFile:NSFileHandle? = NSFileHandle(forReadingAtPath: path as String);
31 | hash = hashForFile(readFile!);
32 | return hash;
33 | }
34 |
35 | func hashForUrl(url: NSURL) -> VideoHash {
36 | var hash = VideoHash();
37 | let error = NSErrorPointer();
38 |
39 | var readFile: NSFileHandle?
40 | do {
41 | readFile = try NSFileHandle(forReadingFromURL: url)
42 | } catch let error1 as NSError {
43 | error.memory = error1
44 | readFile = nil
45 | };
46 | hash = hashForFile(readFile!);
47 | return hash;
48 | }
49 |
50 | func hashForFile(handle: NSFileHandle) -> VideoHash {
51 | var returnHash = VideoHash();
52 |
53 | let CHUNK_SIZE:UInt64 = 65536;
54 | var fileDataBegin, fileDataEnd:NSData;
55 | var hash:UInt64 = 0;
56 |
57 | fileDataBegin = handle.readDataOfLength(Int(CHUNK_SIZE));
58 | handle.seekToEndOfFile();
59 |
60 | let fileSize = handle.offsetInFile;
61 | if (fileSize < CHUNK_SIZE) {
62 | return returnHash;
63 | }
64 |
65 | handle.seekToFileOffset(max(0, (fileSize - CHUNK_SIZE)));
66 | fileDataEnd = handle.readDataOfLength(Int(CHUNK_SIZE));
67 |
68 | var data_bytes = UnsafeBufferPointer
(
69 | start: UnsafePointer(fileDataBegin.bytes),
70 | count: Int(CHUNK_SIZE)/sizeof(UInt64)
71 | )
72 |
73 | hash = data_bytes.reduce(hash) { $0 &+ $1 }
74 |
75 | data_bytes = UnsafeBufferPointer(
76 | start: UnsafePointer(fileDataEnd.bytes),
77 | count: Int(CHUNK_SIZE)/sizeof(UInt64)
78 | )
79 |
80 | hash = data_bytes.reduce(hash) { $0 &+ $1 }
81 |
82 | hash = hash &+ fileSize
83 |
84 | returnHash.fileHash = hash;
85 | returnHash.fileSize = fileSize;
86 |
87 | return returnHash;
88 |
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/Languages.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Languages.swift
3 | // subs
4 | //
5 | // Created by Lucija Frković on 28/07/15.
6 | // Copyright © 2015 Lucija Frković. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 | class Language {
12 |
13 | class func getLanguages() -> NSDictionary {
14 | var languages = [String: String]()
15 |
16 | // languages["afr"] = "Afrikaans"
17 | // languages["alb"] = "Albanian"
18 | // languages["ara"] = "Arabic"
19 | // languages["arm"] = "Armenian"
20 | // languages["baq"] = "Basque"
21 | // languages["bel"] = "Belarusian"
22 | // languages["ben"] = "Bengali"
23 | // languages["bos"] = "Bosnian"
24 | // languages["bre"] = "Breton"
25 | // languages["bul"] = "Bulgarian"
26 | // languages["bur"] = "Burmese"
27 | // languages["cat"] = "Catalan"
28 | // languages["chi"] = "Chinese (simplified)"
29 | // languages["zht"] = "Chinese (traditional)"
30 | // languages["zhe"] = "Chinese bilingual"
31 | // languages["hrv"] = "Croatian"
32 | // languages["cze"] = "Czech"
33 | // languages["dan"] = "Danish"
34 | // languages["dut"] = "Dutch"
35 | // languages["eng"] = "English"
36 | // languages["epo"] = "Esperanto"
37 | // languages["est"] = "Estonian"
38 | // languages["fin"] = "Finnish"
39 | // languages["fre"] = "French"
40 | // languages["glg"] = "Galician"
41 | // languages["geo"] = "Georgian"
42 | // languages["ger"] = "German"
43 | // languages["ell"] = "Greek"
44 | // languages["heb"] = "Hebrew"
45 | // languages["hin"] = "Hindi"
46 | // languages["hun"] = "Hungarian"
47 | // languages["ice"] = "Icelandic"
48 | // languages["ind"] = "Indonesian"
49 | // languages["ita"] = "Italian"
50 | // languages["jpn"] = "Japanese"
51 | // languages["kaz"] = "Kazakh"
52 | // languages["khm"] = "Khmer"
53 | // languages["kor"] = "Korean"
54 | // languages["lav"] = "Latvian"
55 | // languages["lit"] = "Lithuanian"
56 | // languages["ltz"] = "Luxembourgish"
57 | // languages["mac"] = "Macedonian"
58 | // languages["may"] = "Malay"
59 | // languages["mal"] = "Malayalam"
60 | // languages["mni"] = "Manipuri"
61 | // languages["mon"] = "Mongolian"
62 | // languages["mne"] = "Montenegrin"
63 | // languages["nor"] = "Norwegian"
64 | // languages["oci"] = "Occitan"
65 | // languages["per"] = "Persian"
66 | // languages["pol"] = "Polish"
67 | // languages["por"] = "Portuguese"
68 | // languages["pob"] = "Portuguese (BR)"
69 | // languages["rum"] = "Romanian"
70 | // languages["rus"] = "Russian"
71 | // languages["scc"] = "Serbian"
72 | // languages["sin"] = "Sinhalese"
73 | // languages["slo"] = "Slovak"
74 | // languages["slv"] = "Slovenian"
75 | // languages["spa"] = "Spanish"
76 | // languages["swa"] = "Swahili"
77 | // languages["swe"] = "Swedish"
78 | // languages["syr"] = "Syriac"
79 | // languages["tgl"] = "Tagalog"
80 | // languages["tam"] = "Tamil"
81 | // languages["tel"] = "Telugu"
82 | // languages["tha"] = "Thai"
83 | // languages["tur"] = "Turkish"
84 | // languages["ukr"] = "Ukrainian"
85 | // languages["urd"] = "Urdu"
86 | // languages["vie"] = "Vietnamese"
87 |
88 | languages["Afrikaans"] = "afr"
89 | languages["Albanian"] = "alb"
90 | languages["Arabic"] = "ara"
91 | languages["Armenian"] = "arm"
92 | languages["Basque"] = "baq"
93 | languages["Belarusian"] = "bel"
94 | languages["Bengali"] = "ben"
95 | languages["Bosnian"] = "bos"
96 | languages["Breton"] = "bre"
97 | languages["Bulgarian"] = "bul"
98 | languages["Burmese"] = "bur"
99 | languages["Catalan"] = "cat"
100 | languages["Chinese (simplified)"] = "chi"
101 | languages["Chinese (traditional)"] = "zht"
102 | languages["Chinese bilingual"] = "zhe"
103 | languages["Croatian"] = "hrv"
104 | languages["Czech"] = "cze"
105 | languages["Danish"] = "dan"
106 | languages["Dutch"] = "dut"
107 | languages["English"] = "eng"
108 | languages["Esperanto"] = "epo"
109 | languages["Estonian"] = "est"
110 | languages["Finnish"] = "fin"
111 | languages["French"] = "fre"
112 | languages["Galician"] = "glg"
113 | languages["Georgian"] = "geo"
114 | languages["German"] = "ger"
115 | languages["Greek"] = "ell"
116 | languages["Hebrew"] = "heb"
117 | languages["Hindi"] = "hin"
118 | languages["Hungarian"] = "hun"
119 | languages["Icelandic"] = "ice"
120 | languages["Indonesian"] = "ind"
121 | languages["Italian"] = "ita"
122 | languages["Japanese"] = "jpn"
123 | languages["Kazakh"] = "kaz"
124 | languages["Khmer"] = "khm"
125 | languages["Korean"] = "kor"
126 | languages["Latvian"] = "lav"
127 | languages["Lithuanian"] = "lit"
128 | languages["Luxembourgish"] = "ltz"
129 | languages["Macedonian"] = "mac"
130 | languages["Malay"] = "may"
131 | languages["Malayalam"] = "mal"
132 | languages["Manipuri"] = "mni"
133 | languages["Mongolian"] = "mon"
134 | languages["Montenegrin"] = "mne"
135 | languages["Norwegian"] = "nor"
136 | languages["Occitan"] = "oci"
137 | languages["Persian"] = "per"
138 | languages["Polish"] = "pol"
139 | languages["Portuguese"] = "por"
140 | languages["Portuguese (BR)"] = "pob"
141 | languages["Romanian"] = "rum"
142 | languages["Russian"] = "rus"
143 | languages["Serbian"] = "scc"
144 | languages["Sinhalese"] = "sin"
145 | languages["Slovak"] = "slo"
146 | languages["Slovenian"] = "slv"
147 | languages["Spanish"] = "spa"
148 | languages["Swahili"] = "swa"
149 | languages["Swedish"] = "swe"
150 | languages["Syriac"] = "syr"
151 | languages["Tagalog"] = "tgl"
152 | languages["Tamil"] = "tam"
153 | languages["Telugu"] = "tel"
154 | languages["Thai"] = "tha"
155 | languages["Turkish"] = "tur"
156 | languages["Ukrainian"] = "ukr"
157 | languages["Urdu"] = "urd"
158 | languages["Vietnamese"] = "vie"
159 |
160 | return languages
161 | }
162 | }
163 |
164 |
--------------------------------------------------------------------------------
/MainWindowController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MainWindowController.swift
3 | // Subtitlr
4 | //
5 | // Created by Lucija Frković on 11/10/15.
6 | // Copyright © 2015 Lucija Frković. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 |
11 | class MainWindowController: NSWindowController, NSTableViewDataSource, NSTableViewDelegate {
12 |
13 | @IBOutlet weak var dropzone: NSView!
14 | @IBOutlet weak var tableView: NSTableView!
15 | @IBOutlet weak var tableContainer: NSView!
16 | @IBOutlet weak var containerView: NSView!
17 | @IBOutlet weak var dropzoneImage: NSImageView!
18 |
19 | let popover = NSPopover()
20 |
21 | var showDropzone = true
22 |
23 | var videos = [Video]()
24 |
25 | override var windowNibName: String {
26 | return "MainWindowController"
27 | }
28 |
29 | override func windowDidLoad() {
30 | super.windowDidLoad()
31 | self.window!.registerForDraggedTypes([NSFilenamesPboardType])
32 |
33 | //color the container view white, so the dropzone gets white as well
34 | containerView.wantsLayer = true
35 | containerView.layer?.backgroundColor = NSColor.whiteColor().CGColor
36 |
37 | //unregister NSImageView in dropzone view from receiving dragging operation
38 | //otherwise it interferes with dragging files to the whole dropzone area
39 | dropzoneImage.unregisterDraggedTypes()
40 |
41 | tableView.setDelegate(self)
42 |
43 | //bind popover to its controller
44 | popover.contentViewController = PopoverController()
45 | popover.behavior = NSPopoverBehavior.Transient
46 |
47 | }
48 |
49 |
50 | func draggingEntered(sender: NSDraggingInfo) -> NSDragOperation {
51 | return .Copy
52 | }
53 |
54 | func performDragOperation(sender: NSDraggingInfo) -> Bool {
55 | if let board = sender.draggingPasteboard().propertyListForType("NSFilenamesPboardType") as? NSArray {
56 | if let filePaths = board as? [String] {
57 |
58 | //geting the path of dropped file
59 | for path in filePaths {
60 | //only videos are allowed
61 | if Constants.fileTypes.contains((path as NSString).pathExtension.lowercaseString){
62 | videos.append(Video(path: path))
63 | }
64 | }
65 |
66 | if videos.count > 0 {
67 | checkAndSwitchToTableView()
68 |
69 | tableView.reloadData()
70 | }
71 |
72 | return true
73 | }
74 | }
75 | return false
76 | }
77 |
78 | //Switches to table view if dropzone is active
79 | func checkAndSwitchToTableView() {
80 | if showDropzone {
81 | showDropzone = false
82 | //remove dropzone and show table with files
83 | containerView.animator().replaceSubview(dropzone, with: tableContainer)
84 | tableContainer!.hidden = false
85 | }
86 | }
87 |
88 | func concludeDragOperation(sender: NSDraggingInfo) {
89 | getSubtitlesForDroppedFiles()
90 | }
91 |
92 | //counters to help with displaying proper notification info
93 | var videoFoundCount = 0
94 | var videoNotFoundCount = 0
95 | var videoNotSearchedCount = 0
96 |
97 | func getSubtitlesForDroppedFiles(){
98 | for (index, video) in videos.enumerate() {
99 | if video.subStatus == Video.SubtitleStauts.NotSearched {
100 | videoNotSearchedCount += 1
101 |
102 | // Subtitle search and download is done in a separate thread on a lower priority than
103 | // table reload. Otherwise, the application visually gets "stuck" until all subs are downloaded
104 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
105 | video.downloadSubtitle()
106 |
107 | dispatch_async(dispatch_get_main_queue()){
108 | if video.subStatus == Video.SubtitleStauts.Found {
109 | self.videoFoundCount += 1
110 | }
111 | else if video.subStatus == Video.SubtitleStauts.NotFound {
112 | self.videoNotFoundCount += 1
113 | }
114 |
115 | //refresh only the first (status) and third(finder icon/link to manual search) columns
116 | //of the table
117 | let columns = NSMutableIndexSet()
118 | columns.addIndex(0)
119 | columns.addIndex(2)
120 | self.tableView.reloadDataForRowIndexes(NSIndexSet(index: index), columnIndexes: columns)
121 |
122 | //if all videos are searched for, display notification
123 | if ((self.videoFoundCount + self.videoNotFoundCount) == self.videoNotSearchedCount){
124 | self.notifyUser()
125 | self.resetSearchResultCounters()
126 |
127 | }
128 |
129 | }
130 | })
131 | }
132 | }
133 |
134 | }
135 |
136 | func resetSearchResultCounters(){
137 | videoNotSearchedCount = 0
138 | videoNotFoundCount = 0
139 | videoFoundCount = 0
140 | }
141 |
142 | func notifyUser(){
143 | let notify = NSUserNotification()
144 | notify.title = "Finished searching for subtitles"
145 | notify.subtitle = "Subtitles found for \(videoFoundCount) of \(videoNotSearchedCount) videos"
146 | NSUserNotificationCenter.defaultUserNotificationCenter().deliverNotification(notify)
147 | }
148 |
149 | func numberOfRowsInTableView(tableView: NSTableView) -> Int {
150 | return videos.count
151 | }
152 |
153 | //prevents row selection
154 | func tableView(tableView: NSTableView, selectionIndexesForProposedSelection proposedSelectionIndexes: NSIndexSet) -> NSIndexSet {
155 | return NSIndexSet();
156 | }
157 |
158 |
159 | //Resolve table column values
160 | func tableView(tableView: NSTableView, viewForTableColumn tableColumn: NSTableColumn?, row: Int) -> NSView? {
161 |
162 | //middle column showing video path, middle of text is truncated to fit the cell
163 | if tableColumn?.identifier == "fileName" {
164 | var fileName: NSTextField? = tableView.makeViewWithIdentifier("fileName", owner: self) as? NSTextField
165 |
166 | if fileName == nil {
167 | fileName = NSTextField(frame: NSRect())
168 | fileName!.identifier = "fileName"
169 | fileName?.lineBreakMode = NSLineBreakMode.ByTruncatingMiddle
170 | }
171 | fileName?.stringValue = videos[row].fileName
172 | fileName?.bezeled = false
173 | fileName?.bordered = false
174 | fileName?.selectable = false
175 | fileName?.backgroundColor = NSColor.clearColor()
176 | return fileName
177 | }
178 | else if tableColumn?.identifier == "findSubtitle" {
179 | var findSubtitle: NSButton? = tableView.makeViewWithIdentifier("finder", owner: self) as? NSButton
180 |
181 | if findSubtitle == nil {
182 | findSubtitle = NSButton(frame: NSRect())
183 | findSubtitle!.identifier = "findSubtitle"
184 | }
185 |
186 |
187 | findSubtitle?.bordered = false
188 |
189 | findSubtitle?.setButtonType(NSButtonType.MomentaryChangeButton)
190 | findSubtitle?.bezelStyle = NSBezelStyle.RoundedDisclosureBezelStyle
191 | findSubtitle?.imagePosition = NSCellImagePosition.ImageOnly
192 | findSubtitle?.target = self
193 |
194 | findSubtitle?.tag = row
195 |
196 | if videos[row].subStatus == Video.SubtitleStauts.Found {
197 | findSubtitle?.image = NSImage(named: NSImageNameRevealFreestandingTemplate)
198 | findSubtitle?.toolTip = "Show subtitle in Finder"
199 | findSubtitle?.action = "revealInFinder:"
200 |
201 | return findSubtitle
202 | }
203 | //show direct search by filename on opensubtitles
204 | else if videos[row].subStatus == Video.SubtitleStauts.NotFound {
205 |
206 | findSubtitle?.image = NSImage(named: NSImageNameShareTemplate)
207 | findSubtitle?.bordered = false
208 | findSubtitle?.toolTip = "Search in browser on OpenSubtitles.org"
209 | findSubtitle?.action = "searchOpenSubs:"
210 |
211 | return findSubtitle
212 | }
213 |
214 |
215 | }
216 | else if tableColumn?.identifier == "status" {
217 | if (videos[row].subStatus == Video.SubtitleStauts.NotSearched) {
218 | var spinner: NSProgressIndicator? = tableView.makeViewWithIdentifier("status", owner: self) as? NSProgressIndicator
219 |
220 | if spinner == nil {
221 | spinner = NSProgressIndicator(frame: NSRect())
222 | spinner!.identifier = "status"
223 | }
224 | spinner?.style = NSProgressIndicatorStyle.SpinningStyle
225 | spinner?.controlSize = NSControlSize.SmallControlSize
226 | spinner?.startAnimation(nil)
227 | spinner?.bezeled = false
228 |
229 | spinner?.toolTip = "Searching subtitles..."
230 |
231 | return spinner
232 | }
233 | else {
234 | var status: NSTextField? = tableView.makeViewWithIdentifier("status", owner: self) as? NSTextField
235 |
236 | if status == nil {
237 | status = NSTextField(frame: NSRect())
238 | status!.identifier = "status"
239 | }
240 | status?.stringValue = videos[row].subStatus == Video.SubtitleStauts.Found ? "✓" : "x"
241 | status?.font = videos[row].subStatus == Video.SubtitleStauts.Found ? NSFont(name: "Devanagari MT", size: 12): NSFont(name: "Zapf Dingbats", size: 12)
242 | status?.alignment = NSTextAlignment.Center
243 | status?.bezeled = false
244 | status?.bordered = false
245 | status?.selectable = false
246 | status?.backgroundColor = NSColor.clearColor()
247 | status?.toolTip = videos[row].subStatus == Video.SubtitleStauts.Found ? "Subtitle was found and downloaded to video location.": "Subtitle was not found."
248 |
249 |
250 | return status
251 | }
252 |
253 | }
254 |
255 | return nil
256 | }
257 |
258 | /* Show subtitle in finder.
259 | Finder icon is assigned a tag value corresponding to matching file's array index
260 | */
261 | func revealInFinder(sender: NSButton){
262 | let url = NSURL.fileURLWithPath(videos[sender.tag].subtitle!.path)
263 | NSWorkspace.sharedWorkspace().activateFileViewerSelectingURLs([url])
264 | }
265 |
266 | func searchOpenSubs(sender: NSButton){
267 | let lang = NSUserDefaults.standardUserDefaults().valueForKey(Constants.Keys.subtitleLanguage) as! String
268 | let urlString = "http://www.opensubtitles.org/en/search2/sublanguageid-\(lang)/moviename-\(videos[sender.tag].fileName)"
269 | let safeUrl = urlString.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())!
270 | let url = NSURL(string: safeUrl)
271 | NSWorkspace.sharedWorkspace().openURL(url!)
272 | }
273 |
274 | //opens or closes settings popover
275 | @IBAction func togglePopover(sender: NSButton) {
276 | if popover.shown {
277 | popover.close()
278 | }
279 | else {
280 | popover.showRelativeToRect( sender.bounds, ofView: sender, preferredEdge: NSRectEdge(rawValue: 3)!)
281 | }
282 | }
283 |
284 | @IBAction func selectVideoFilesFromFinder(sender: NSButton) {
285 | sender.enabled = false
286 |
287 | let openPanel = NSOpenPanel()
288 | openPanel.allowsMultipleSelection = true
289 | openPanel.allowedFileTypes = Constants.fileTypes
290 | openPanel.allowsOtherFileTypes = false
291 | openPanel.canChooseFiles = true
292 | openPanel.canChooseDirectories = false
293 | openPanel.canCreateDirectories = false
294 | openPanel.allowsConcurrentViewDrawing = false
295 |
296 | openPanel.beginWithCompletionHandler{result -> Void in
297 | if result == NSFileHandlingPanelOKButton {
298 | for file in openPanel.URLs {
299 | self.videos.append(Video(path: file.path!))
300 | self.checkAndSwitchToTableView()
301 | }
302 | self.tableView.reloadData()
303 | self.getSubtitlesForDroppedFiles()
304 | }
305 | sender.enabled = true
306 | }
307 | }
308 |
309 | }
310 |
--------------------------------------------------------------------------------
/MainWindowController.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 | YnBsaXN0MDDUAQIDBAUGJCVYJHZlcnNpb25YJG9iamVjdHNZJGFyY2hpdmVyVCR0b3ASAAGGoKkHCBES
240 | EwsKGR9VJG51bGzUCQoLDA0ODxBWJGNsYXNzVHR5cGVXc3VidHlwZV8QEl9fQ0FDb2RpbmdDb250ZW50
241 | c4AIgAOAAoAEWWZyb21SaWdodFZtb3ZlSW7SFAkVGFpOUy5vYmplY3RzohYXgAWABoAH0hobHB1aJGNs
242 | YXNzbmFtZVgkY2xhc3Nlc1dOU0FycmF5ohweWE5TT2JqZWN00hobICFcQ0FUcmFuc2l0aW9uoyIjHlxD
243 | QVRyYW5zaXRpb25bQ0FBbmltYXRpb25fEA9OU0tleWVkQXJjaGl2ZXLRJidUcm9vdIABAAgAEQAaACMA
244 | LQAyADcAQQBHAFAAVwBcAGQAeQB7AH0AfwCBAIsAkgCXAKIApQCnAKkAqwCwALsAxADMAM8A2ADdAOoA
245 | 7gD7AQcBGQEcASEAAAAAAAACAQAAAAAAAAAoAAAAAAAAAAAAAAAAAAABIw
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
--------------------------------------------------------------------------------
/OpenSubsAccess.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OpenSubsAccess.swift
3 | // Subtitlr
4 | //
5 | // Created by Lucija Frković on 19/08/15.
6 | // Copyright © 2015 Lucija Frković. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 |
12 | class OpenSubsAccess {
13 |
14 | var token: String?
15 |
16 | /**
17 | Used to communicate to OpenSubtitles.org
18 | Synchronised requests are made to OpenSubtitles via HTTPS connection, using
19 | XML-RPC protocol (Cocoa XML-RPC framework is used)
20 |
21 | Timeout set to 30sec
22 | */
23 | func talkToOpenSubs(method: String, params: [AnyObject]) -> NSDictionary? {
24 |
25 | let url = NSURL(string: Constants.OSconnectionString)
26 | let request = XMLRPCRequest(URL: url)
27 |
28 | request.setMethod(method, withParameters: params)
29 | request.setTimeoutInterval(NSTimeInterval(30)) //Timeout set to 30sec
30 | do {
31 | //fuck yeah!!!
32 | let response = try XMLRPCConnection.sendSynchronousXMLRPCRequest(request)
33 | return response.object() as? NSDictionary
34 |
35 | } catch {
36 | //print(error)
37 | //TODO: error handling!
38 | //maybe unnecessary?
39 | }
40 |
41 | return nil
42 | }
43 |
44 | /**
45 | Tries to log in to OpenSubtitles.org, returns
46 | token to be reused in a single session
47 | */
48 | func logIn() {
49 | let resultDict = talkToOpenSubs(Constants.OSMethods.logIn, params: ["", "", "eng", Constants.OSUserAgent])
50 | if resultDict != nil && resultDict!.valueForKey("token") != nil {
51 | token = resultDict!.valueForKey("token") as? String
52 | }
53 |
54 | }
55 |
56 |
57 | /**
58 | Creates the appropriate OpenSubtitles structure to get subtitle info for a particular video.
59 | Checks whether a required subtitle exists, returns its ID and format
60 | */
61 |
62 | func getSubtitle(hash: String, size: Double) -> (id: Int, format: String)? {
63 | if (token != nil) {
64 | var params = [AnyObject]()
65 | params.append(token!)
66 |
67 | var video = [String:AnyObject]()
68 | video["sublanguageid"] = NSUserDefaults.standardUserDefaults().valueForKey(Constants.Keys.subtitleLanguage) as! String
69 | video["moviehash"] = hash
70 | video["moviesize"] = size
71 | var videos = [AnyObject]()
72 | videos.append(video)
73 |
74 | params.append(videos)
75 |
76 | if let resultDict = talkToOpenSubs(Constants.OSMethods.searchSubtitles, params: params) as NSDictionary! {
77 |
78 | if let firstResult = (resultDict["data"] as? NSArray) {
79 | if (firstResult.count > 0){
80 | let firstSubId = firstResult[0]["IDSubtitleFile"] as! String
81 | let subtitleFormat = firstResult[0]["SubFormat"] as! String
82 | return (Int(firstSubId)!, subtitleFormat)
83 | }
84 | }
85 |
86 | }
87 |
88 |
89 | }
90 | return nil
91 | }
92 |
93 |
94 |
95 | func downloadSub(subId: Int, format: String) -> NSData? {
96 | if token != nil {
97 | var params = [AnyObject]()
98 | params.append(token!)
99 |
100 | var subIds = [Int]()
101 | subIds.append(subId)
102 | params.append(subIds)
103 |
104 | let resultDict = talkToOpenSubs(Constants.OSMethods.downloadSubtitles, params: params) as NSDictionary!
105 |
106 | let subtitle = ((resultDict["data"] as! NSArray)[0] as! NSDictionary)["data"] as! String
107 | let subFile = NSData(base64EncodedString: subtitle, options: [])!.gunzippedData()
108 |
109 | return subFile
110 | }
111 |
112 | return nil
113 | }
114 | }
--------------------------------------------------------------------------------
/Podfile:
--------------------------------------------------------------------------------
1 | source 'https://github.com/CocoaPods/Specs.git'
2 | platform :osx, '10.10'
3 | use_frameworks!
4 |
5 | target "Subtitlr" do
6 | pod 'xmlrpc', '~> 2.3.4'
7 | pod 'GZIP', '~> 1.1.1'
8 | target 'SubtitlrTests' do
9 | inherit! :search_paths
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/Pods/GZIP/GZIP/GZIP.h:
--------------------------------------------------------------------------------
1 | //
2 | // GZIP.h
3 | //
4 | // Version 1.1.1
5 | //
6 | // Created by Nick Lockwood on 03/06/2012.
7 | // Copyright (C) 2012 Charcoal Design
8 | //
9 | // Distributed under the permissive zlib License
10 | // Get the latest version from here:
11 | //
12 | // https://github.com/nicklockwood/GZIP
13 | //
14 | // This software is provided 'as-is', without any express or implied
15 | // warranty. In no event will the authors be held liable for any damages
16 | // arising from the use of this software.
17 | //
18 | // Permission is granted to anyone to use this software for any purpose,
19 | // including commercial applications, and to alter it and redistribute it
20 | // freely, subject to the following restrictions:
21 | //
22 | // 1. The origin of this software must not be misrepresented; you must not
23 | // claim that you wrote the original software. If you use this software
24 | // in a product, an acknowledgment in the product documentation would be
25 | // appreciated but is not required.
26 | //
27 | // 2. Altered source versions must be plainly marked as such, and must not be
28 | // misrepresented as being the original software.
29 | //
30 | // 3. This notice may not be removed or altered from any source distribution.
31 | //
32 |
33 |
34 | #import
35 |
36 |
37 | @interface NSData (GZIP)
38 |
39 | - (nullable NSData *)gzippedDataWithCompressionLevel:(float)level;
40 | - (nullable NSData *)gzippedData;
41 | - (nullable NSData *)gunzippedData;
42 | - (BOOL)isGzippedData;
43 |
44 | @end
45 |
--------------------------------------------------------------------------------
/Pods/GZIP/GZIP/GZIP.m:
--------------------------------------------------------------------------------
1 | //
2 | // GZIP.m
3 | //
4 | // Version 1.1.1
5 | //
6 | // Created by Nick Lockwood on 03/06/2012.
7 | // Copyright (C) 2012 Charcoal Design
8 | //
9 | // Distributed under the permissive zlib License
10 | // Get the latest version from here:
11 | //
12 | // https://github.com/nicklockwood/GZIP
13 | //
14 | // This software is provided 'as-is', without any express or implied
15 | // warranty. In no event will the authors be held liable for any damages
16 | // arising from the use of this software.
17 | //
18 | // Permission is granted to anyone to use this software for any purpose,
19 | // including commercial applications, and to alter it and redistribute it
20 | // freely, subject to the following restrictions:
21 | //
22 | // 1. The origin of this software must not be misrepresented; you must not
23 | // claim that you wrote the original software. If you use this software
24 | // in a product, an acknowledgment in the product documentation would be
25 | // appreciated but is not required.
26 | //
27 | // 2. Altered source versions must be plainly marked as such, and must not be
28 | // misrepresented as being the original software.
29 | //
30 | // 3. This notice may not be removed or altered from any source distribution.
31 | //
32 |
33 |
34 | #import "GZIP.h"
35 | #import
36 | #import
37 |
38 |
39 | #pragma clang diagnostic ignored "-Wcast-qual"
40 |
41 |
42 | @implementation NSData (GZIP)
43 |
44 | static void *libzOpen()
45 | {
46 | static void *libz;
47 | static dispatch_once_t onceToken;
48 | dispatch_once(&onceToken, ^{
49 | libz = dlopen("/usr/lib/libz.dylib", RTLD_LAZY);
50 | });
51 | return libz;
52 | }
53 |
54 | - (NSData *)gzippedDataWithCompressionLevel:(float)level
55 | {
56 | if (self.length == 0 || [self isGzippedData])
57 | {
58 | return self;
59 | }
60 |
61 | void *libz = libzOpen();
62 | int (*deflateInit2_)(z_streamp, int, int, int, int, int, const char *, int) =
63 | (int (*)(z_streamp, int, int, int, int, int, const char *, int))dlsym(libz, "deflateInit2_");
64 | int (*deflate)(z_streamp, int) = (int (*)(z_streamp, int))dlsym(libz, "deflate");
65 | int (*deflateEnd)(z_streamp) = (int (*)(z_streamp))dlsym(libz, "deflateEnd");
66 |
67 | z_stream stream;
68 | stream.zalloc = Z_NULL;
69 | stream.zfree = Z_NULL;
70 | stream.opaque = Z_NULL;
71 | stream.avail_in = (uint)self.length;
72 | stream.next_in = (Bytef *)(void *)self.bytes;
73 | stream.total_out = 0;
74 | stream.avail_out = 0;
75 |
76 | static const NSUInteger ChunkSize = 16384;
77 |
78 | NSMutableData *output = nil;
79 | int compression = (level < 0.0f)? Z_DEFAULT_COMPRESSION: (int)(roundf(level * 9));
80 | if (deflateInit2(&stream, compression, Z_DEFLATED, 31, 8, Z_DEFAULT_STRATEGY) == Z_OK)
81 | {
82 | output = [NSMutableData dataWithLength:ChunkSize];
83 | while (stream.avail_out == 0)
84 | {
85 | if (stream.total_out >= output.length)
86 | {
87 | output.length += ChunkSize;
88 | }
89 | stream.next_out = (uint8_t *)output.mutableBytes + stream.total_out;
90 | stream.avail_out = (uInt)(output.length - stream.total_out);
91 | deflate(&stream, Z_FINISH);
92 | }
93 | deflateEnd(&stream);
94 | output.length = stream.total_out;
95 | }
96 |
97 | return output;
98 | }
99 |
100 | - (NSData *)gzippedData
101 | {
102 | return [self gzippedDataWithCompressionLevel:-1.0f];
103 | }
104 |
105 | - (NSData *)gunzippedData
106 | {
107 | if (self.length == 0 || ![self isGzippedData])
108 | {
109 | return self;
110 | }
111 |
112 | void *libz = libzOpen();
113 | int (*inflateInit2_)(z_streamp, int, const char *, int) =
114 | (int (*)(z_streamp, int, const char *, int))dlsym(libz, "inflateInit2_");
115 | int (*inflate)(z_streamp, int) = (int (*)(z_streamp, int))dlsym(libz, "inflate");
116 | int (*inflateEnd)(z_streamp) = (int (*)(z_streamp))dlsym(libz, "inflateEnd");
117 |
118 | z_stream stream;
119 | stream.zalloc = Z_NULL;
120 | stream.zfree = Z_NULL;
121 | stream.avail_in = (uint)self.length;
122 | stream.next_in = (Bytef *)self.bytes;
123 | stream.total_out = 0;
124 | stream.avail_out = 0;
125 |
126 | NSMutableData *output = nil;
127 | if (inflateInit2(&stream, 47) == Z_OK)
128 | {
129 | int status = Z_OK;
130 | output = [NSMutableData dataWithCapacity:self.length * 2];
131 | while (status == Z_OK)
132 | {
133 | if (stream.total_out >= output.length)
134 | {
135 | output.length += self.length / 2;
136 | }
137 | stream.next_out = (uint8_t *)output.mutableBytes + stream.total_out;
138 | stream.avail_out = (uInt)(output.length - stream.total_out);
139 | status = inflate (&stream, Z_SYNC_FLUSH);
140 | }
141 | if (inflateEnd(&stream) == Z_OK)
142 | {
143 | if (status == Z_STREAM_END)
144 | {
145 | output.length = stream.total_out;
146 | }
147 | }
148 | }
149 |
150 | return output;
151 | }
152 |
153 | - (BOOL)isGzippedData
154 | {
155 | const UInt8 *bytes = (const UInt8 *)self.bytes;
156 | return (self.length >= 2 && bytes[0] == 0x1f && bytes[1] == 0x8b);
157 | }
158 |
159 | @end
160 |
--------------------------------------------------------------------------------
/Pods/NSData+Base64/NSData+Base64.h:
--------------------------------------------------------------------------------
1 | //
2 | // NSData+Base64.h
3 | // base64
4 | //
5 | // Created by Matt Gallagher on 2009/06/03.
6 | // Copyright 2009 Matt Gallagher. All rights reserved.
7 | //
8 | // This software is provided 'as-is', without any express or implied
9 | // warranty. In no event will the authors be held liable for any damages
10 | // arising from the use of this software. Permission is granted to anyone to
11 | // use this software for any purpose, including commercial applications, and to
12 | // alter it and redistribute it freely, subject to the following restrictions:
13 | //
14 | // 1. The origin of this software must not be misrepresented; you must not
15 | // claim that you wrote the original software. If you use this software
16 | // in a product, an acknowledgment in the product documentation would be
17 | // appreciated but is not required.
18 | // 2. Altered source versions must be plainly marked as such, and must not be
19 | // misrepresented as being the original software.
20 | // 3. This notice may not be removed or altered from any source
21 | // distribution.
22 | //
23 |
24 | #import
25 |
26 | void *NewBase64Decode(
27 | const char *inputBuffer,
28 | size_t length,
29 | size_t *outputLength);
30 |
31 | char *NewBase64Encode(
32 | const void *inputBuffer,
33 | size_t length,
34 | bool separateLines,
35 | size_t *outputLength);
36 |
37 | @interface NSData (Base64)
38 |
39 | + (NSData *)dataFromBase64String:(NSString *)aString;
40 | - (NSString *)base64EncodedString;
41 |
42 | // added by Hiroshi Hashiguchi
43 | - (NSString *)base64EncodedStringWithSeparateLines:(BOOL)separateLines;
44 |
45 | @end
46 |
--------------------------------------------------------------------------------
/Pods/NSData+Base64/NSData+Base64.m:
--------------------------------------------------------------------------------
1 | //
2 | // NSData+Base64.m
3 | // base64
4 | //
5 | // Created by Matt Gallagher on 2009/06/03.
6 | // Copyright 2009 Matt Gallagher. All rights reserved.
7 | //
8 | // This software is provided 'as-is', without any express or implied
9 | // warranty. In no event will the authors be held liable for any damages
10 | // arising from the use of this software. Permission is granted to anyone to
11 | // use this software for any purpose, including commercial applications, and to
12 | // alter it and redistribute it freely, subject to the following restrictions:
13 | //
14 | // 1. The origin of this software must not be misrepresented; you must not
15 | // claim that you wrote the original software. If you use this software
16 | // in a product, an acknowledgment in the product documentation would be
17 | // appreciated but is not required.
18 | // 2. Altered source versions must be plainly marked as such, and must not be
19 | // misrepresented as being the original software.
20 | // 3. This notice may not be removed or altered from any source
21 | // distribution.
22 | //
23 |
24 | #import "NSData+Base64.h"
25 |
26 | //
27 | // Mapping from 6 bit pattern to ASCII character.
28 | //
29 | static unsigned char base64EncodeLookup[65] =
30 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
31 |
32 | //
33 | // Definition for "masked-out" areas of the base64DecodeLookup mapping
34 | //
35 | #define xx 65
36 |
37 | //
38 | // Mapping from ASCII character to 6 bit pattern.
39 | //
40 | static unsigned char base64DecodeLookup[256] =
41 | {
42 | xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
43 | xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
44 | xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, 62, xx, xx, xx, 63,
45 | 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, xx, xx, xx, xx, xx, xx,
46 | xx, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
47 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, xx, xx, xx, xx, xx,
48 | xx, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
49 | 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, xx, xx, xx, xx, xx,
50 | xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
51 | xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
52 | xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
53 | xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
54 | xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
55 | xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
56 | xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
57 | xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx,
58 | };
59 |
60 | //
61 | // Fundamental sizes of the binary and base64 encode/decode units in bytes
62 | //
63 | #define BINARY_UNIT_SIZE 3
64 | #define BASE64_UNIT_SIZE 4
65 |
66 | //
67 | // NewBase64Decode
68 | //
69 | // Decodes the base64 ASCII string in the inputBuffer to a newly malloced
70 | // output buffer.
71 | //
72 | // inputBuffer - the source ASCII string for the decode
73 | // length - the length of the string or -1 (to specify strlen should be used)
74 | // outputLength - if not-NULL, on output will contain the decoded length
75 | //
76 | // returns the decoded buffer. Must be free'd by caller. Length is given by
77 | // outputLength.
78 | //
79 | void *NewBase64Decode(
80 | const char *inputBuffer,
81 | size_t length,
82 | size_t *outputLength)
83 | {
84 | if (length == -1)
85 | {
86 | length = strlen(inputBuffer);
87 | }
88 |
89 | size_t outputBufferSize =
90 | ((length+BASE64_UNIT_SIZE-1) / BASE64_UNIT_SIZE) * BINARY_UNIT_SIZE;
91 | unsigned char *outputBuffer = (unsigned char *)malloc(outputBufferSize);
92 |
93 | size_t i = 0;
94 | size_t j = 0;
95 | while (i < length)
96 | {
97 | //
98 | // Accumulate 4 valid characters (ignore everything else)
99 | //
100 | unsigned char accumulated[BASE64_UNIT_SIZE];
101 | size_t accumulateIndex = 0;
102 | while (i < length)
103 | {
104 | unsigned char decode = base64DecodeLookup[inputBuffer[i++]];
105 | if (decode != xx)
106 | {
107 | accumulated[accumulateIndex] = decode;
108 | accumulateIndex++;
109 |
110 | if (accumulateIndex == BASE64_UNIT_SIZE)
111 | {
112 | break;
113 | }
114 | }
115 | }
116 |
117 | //
118 | // Store the 6 bits from each of the 4 characters as 3 bytes
119 | //
120 | // (Uses improved bounds checking suggested by Alexandre Colucci)
121 | //
122 | if(accumulateIndex >= 2)
123 | outputBuffer[j] = (accumulated[0] << 2) | (accumulated[1] >> 4);
124 | if(accumulateIndex >= 3)
125 | outputBuffer[j + 1] = (accumulated[1] << 4) | (accumulated[2] >> 2);
126 | if(accumulateIndex >= 4)
127 | outputBuffer[j + 2] = (accumulated[2] << 6) | accumulated[3];
128 | j += accumulateIndex - 1;
129 | }
130 |
131 | if (outputLength)
132 | {
133 | *outputLength = j;
134 | }
135 | return outputBuffer;
136 | }
137 |
138 | //
139 | // NewBase64Encode
140 | //
141 | // Encodes the arbitrary data in the inputBuffer as base64 into a newly malloced
142 | // output buffer.
143 | //
144 | // inputBuffer - the source data for the encode
145 | // length - the length of the input in bytes
146 | // separateLines - if zero, no CR/LF characters will be added. Otherwise
147 | // a CR/LF pair will be added every 64 encoded chars.
148 | // outputLength - if not-NULL, on output will contain the encoded length
149 | // (not including terminating 0 char)
150 | //
151 | // returns the encoded buffer. Must be free'd by caller. Length is given by
152 | // outputLength.
153 | //
154 | char *NewBase64Encode(
155 | const void *buffer,
156 | size_t length,
157 | bool separateLines,
158 | size_t *outputLength)
159 | {
160 | const unsigned char *inputBuffer = (const unsigned char *)buffer;
161 |
162 | #define MAX_NUM_PADDING_CHARS 2
163 | #define OUTPUT_LINE_LENGTH 64
164 | #define INPUT_LINE_LENGTH ((OUTPUT_LINE_LENGTH / BASE64_UNIT_SIZE) * BINARY_UNIT_SIZE)
165 | #define CR_LF_SIZE 2
166 |
167 | //
168 | // Byte accurate calculation of final buffer size
169 | //
170 | size_t outputBufferSize =
171 | ((length / BINARY_UNIT_SIZE)
172 | + ((length % BINARY_UNIT_SIZE) ? 1 : 0))
173 | * BASE64_UNIT_SIZE;
174 | if (separateLines)
175 | {
176 | outputBufferSize +=
177 | (outputBufferSize / OUTPUT_LINE_LENGTH) * CR_LF_SIZE;
178 | }
179 |
180 | //
181 | // Include space for a terminating zero
182 | //
183 | outputBufferSize += 1;
184 |
185 | //
186 | // Allocate the output buffer
187 | //
188 | char *outputBuffer = (char *)malloc(outputBufferSize);
189 | if (!outputBuffer)
190 | {
191 | return NULL;
192 | }
193 |
194 | size_t i = 0;
195 | size_t j = 0;
196 | const size_t lineLength = separateLines ? INPUT_LINE_LENGTH : length;
197 | size_t lineEnd = lineLength;
198 |
199 | while (true)
200 | {
201 | if (lineEnd > length)
202 | {
203 | lineEnd = length;
204 | }
205 |
206 | for (; i + BINARY_UNIT_SIZE - 1 < lineEnd; i += BINARY_UNIT_SIZE)
207 | {
208 | //
209 | // Inner loop: turn 48 bytes into 64 base64 characters
210 | //
211 | outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2];
212 | outputBuffer[j++] = base64EncodeLookup[((inputBuffer[i] & 0x03) << 4)
213 | | ((inputBuffer[i + 1] & 0xF0) >> 4)];
214 | outputBuffer[j++] = base64EncodeLookup[((inputBuffer[i + 1] & 0x0F) << 2)
215 | | ((inputBuffer[i + 2] & 0xC0) >> 6)];
216 | outputBuffer[j++] = base64EncodeLookup[inputBuffer[i + 2] & 0x3F];
217 | }
218 |
219 | if (lineEnd == length)
220 | {
221 | break;
222 | }
223 |
224 | //
225 | // Add the newline
226 | //
227 | outputBuffer[j++] = '\r';
228 | outputBuffer[j++] = '\n';
229 | lineEnd += lineLength;
230 | }
231 |
232 | if (i + 1 < length)
233 | {
234 | //
235 | // Handle the single '=' case
236 | //
237 | outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2];
238 | outputBuffer[j++] = base64EncodeLookup[((inputBuffer[i] & 0x03) << 4)
239 | | ((inputBuffer[i + 1] & 0xF0) >> 4)];
240 | outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i + 1] & 0x0F) << 2];
241 | outputBuffer[j++] = '=';
242 | }
243 | else if (i < length)
244 | {
245 | //
246 | // Handle the double '=' case
247 | //
248 | outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0xFC) >> 2];
249 | outputBuffer[j++] = base64EncodeLookup[(inputBuffer[i] & 0x03) << 4];
250 | outputBuffer[j++] = '=';
251 | outputBuffer[j++] = '=';
252 | }
253 | outputBuffer[j] = 0;
254 |
255 | //
256 | // Set the output length and return the buffer
257 | //
258 | if (outputLength)
259 | {
260 | *outputLength = j;
261 | }
262 | return outputBuffer;
263 | }
264 |
265 | @implementation NSData (Base64)
266 |
267 | //
268 | // dataFromBase64String:
269 | //
270 | // Creates an NSData object containing the base64 decoded representation of
271 | // the base64 string 'aString'
272 | //
273 | // Parameters:
274 | // aString - the base64 string to decode
275 | //
276 | // returns the autoreleased NSData representation of the base64 string
277 | //
278 | + (NSData *)dataFromBase64String:(NSString *)aString
279 | {
280 | NSData *data = [aString dataUsingEncoding:NSASCIIStringEncoding];
281 | size_t outputLength;
282 | void *outputBuffer = NewBase64Decode([data bytes], [data length], &outputLength);
283 | NSData *result = [NSData dataWithBytes:outputBuffer length:outputLength];
284 | free(outputBuffer);
285 | return result;
286 | }
287 |
288 | //
289 | // base64EncodedString
290 | //
291 | // Creates an NSString object that contains the base 64 encoding of the
292 | // receiver's data. Lines are broken at 64 characters long.
293 | //
294 | // returns an autoreleased NSString being the base 64 representation of the
295 | // receiver.
296 | //
297 | - (NSString *)base64EncodedString
298 | {
299 | size_t outputLength;
300 | char *outputBuffer =
301 | NewBase64Encode([self bytes], [self length], true, &outputLength);
302 |
303 | NSString *result =
304 | [[[NSString alloc]
305 | initWithBytes:outputBuffer
306 | length:outputLength
307 | encoding:NSASCIIStringEncoding]
308 | autorelease];
309 | free(outputBuffer);
310 | return result;
311 | }
312 |
313 | // added by Hiroshi Hashiguchi
314 | - (NSString *)base64EncodedStringWithSeparateLines:(BOOL)separateLines
315 | {
316 | size_t outputLength;
317 | char *outputBuffer =
318 | NewBase64Encode([self bytes], [self length], separateLines, &outputLength);
319 |
320 | NSString *result =
321 | [[[NSString alloc]
322 | initWithBytes:outputBuffer
323 | length:outputLength
324 | encoding:NSASCIIStringEncoding]
325 | autorelease];
326 | free(outputBuffer);
327 | return result;
328 | }
329 |
330 |
331 | @end
332 |
--------------------------------------------------------------------------------
/Pods/Pods.xcodeproj/xcuserdata/spilja.xcuserdatad/xcschemes/GZIP.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
35 |
45 |
46 |
47 |
48 |
54 |
55 |
57 |
58 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/Pods/Pods.xcodeproj/xcuserdata/spilja.xcuserdatad/xcschemes/NSData+Base64.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
35 |
45 |
46 |
47 |
48 |
54 |
55 |
57 |
58 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/Pods/Pods.xcodeproj/xcuserdata/spilja.xcuserdatad/xcschemes/Pods-Subtitlr.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
35 |
45 |
46 |
47 |
48 |
54 |
55 |
57 |
58 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/Pods/Pods.xcodeproj/xcuserdata/spilja.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | GZIP.xcscheme
8 |
9 | isShown
10 |
11 |
12 | NSData+Base64.xcscheme
13 |
14 | isShown
15 |
16 |
17 | Pods-Subtitlr.xcscheme
18 |
19 | isShown
20 |
21 |
22 | xmlrpc.xcscheme
23 |
24 | isShown
25 |
26 |
27 |
28 | SuppressBuildableAutocreation
29 |
30 | 1F98E46E9E64A5DBA3D6FE096D8FF04A
31 |
32 | primary
33 |
34 |
35 | 701D6F5D626C094A841AE2CEB07673C1
36 |
37 | primary
38 |
39 |
40 | 83DC367090DFF5512A7BBF0CA26C393D
41 |
42 | primary
43 |
44 |
45 | C709A40BDCA702C4FFF9216B0E7653DF
46 |
47 | primary
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/Pods/Pods.xcodeproj/xcuserdata/spilja.xcuserdatad/xcschemes/xmlrpc.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
35 |
45 |
46 |
47 |
48 |
54 |
55 |
57 |
58 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-Subtitlr/Pods-Subtitlr.debug.xcconfig:
--------------------------------------------------------------------------------
1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
2 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GZIP" "${PODS_ROOT}/Headers/Public/NSData+Base64" "${PODS_ROOT}/Headers/Public/xmlrpc"
3 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/GZIP" -isystem "${PODS_ROOT}/Headers/Public/NSData+Base64" -isystem "${PODS_ROOT}/Headers/Public/xmlrpc"
4 | OTHER_LDFLAGS = $(inherited) -ObjC -l"GZIP" -l"NSData+Base64" -l"xmlrpc"
5 | PODS_ROOT = ${SRCROOT}/Pods
--------------------------------------------------------------------------------
/Pods/Target Support Files/Pods-Subtitlr/Pods-Subtitlr.release.xcconfig:
--------------------------------------------------------------------------------
1 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
2 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/GZIP" "${PODS_ROOT}/Headers/Public/NSData+Base64" "${PODS_ROOT}/Headers/Public/xmlrpc"
3 | OTHER_CFLAGS = $(inherited) -isystem "${PODS_ROOT}/Headers/Public" -isystem "${PODS_ROOT}/Headers/Public/GZIP" -isystem "${PODS_ROOT}/Headers/Public/NSData+Base64" -isystem "${PODS_ROOT}/Headers/Public/xmlrpc"
4 | OTHER_LDFLAGS = $(inherited) -ObjC -l"GZIP" -l"NSData+Base64" -l"xmlrpc"
5 | PODS_ROOT = ${SRCROOT}/Pods
--------------------------------------------------------------------------------
/Pods/xmlrpc/NSStringAdditions.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | @interface NSString (NSStringAdditions)
4 |
5 | + (NSString *)stringByGeneratingUUID;
6 |
7 | #pragma mark -
8 |
9 | - (NSString *)unescapedString;
10 |
11 | - (NSString *)escapedString;
12 |
13 | @end
14 |
--------------------------------------------------------------------------------
/Pods/xmlrpc/NSStringAdditions.m:
--------------------------------------------------------------------------------
1 | #import "NSStringAdditions.h"
2 |
3 | @implementation NSString (NSStringAdditions)
4 |
5 | + (NSString *)stringByGeneratingUUID {
6 | CFUUIDRef UUIDReference = CFUUIDCreate(nil);
7 | CFStringRef temporaryUUIDString = CFUUIDCreateString(nil, UUIDReference);
8 |
9 | CFRelease(UUIDReference);
10 | #if ! __has_feature(objc_arc)
11 | return [NSMakeCollectable(temporaryUUIDString) autorelease];
12 | #else
13 | return (__bridge_transfer NSString*)temporaryUUIDString;
14 | #endif
15 | }
16 |
17 | #pragma mark -
18 |
19 | - (NSString *)unescapedString {
20 | NSMutableString *string = [NSMutableString stringWithString: self];
21 |
22 | [string replaceOccurrencesOfString: @"&" withString: @"&" options: NSLiteralSearch range: NSMakeRange(0, [string length])];
23 | [string replaceOccurrencesOfString: @""" withString: @"\"" options: NSLiteralSearch range: NSMakeRange(0, [string length])];
24 | [string replaceOccurrencesOfString: @"'" withString: @"'" options: NSLiteralSearch range: NSMakeRange(0, [string length])];
25 | [string replaceOccurrencesOfString: @"9" withString: @"'" options: NSLiteralSearch range: NSMakeRange(0, [string length])];
26 | [string replaceOccurrencesOfString: @"" withString: @"'" options: NSLiteralSearch range: NSMakeRange(0, [string length])];
27 | [string replaceOccurrencesOfString: @"" withString: @"'" options: NSLiteralSearch range: NSMakeRange(0, [string length])];
28 | [string replaceOccurrencesOfString: @">" withString: @">" options: NSLiteralSearch range: NSMakeRange(0, [string length])];
29 | [string replaceOccurrencesOfString: @"<" withString: @"<" options: NSLiteralSearch range: NSMakeRange(0, [string length])];
30 |
31 | return [NSString stringWithString: string];
32 | }
33 |
34 | - (NSString *)escapedString {
35 | NSMutableString *string = [NSMutableString stringWithString: self];
36 |
37 | // NOTE: we use unicode entities instead of & > < etc. since some hosts (powweb, fatcow, and similar)
38 | // have a weird PHP/libxml2 combination that ignores regular entities
39 | [string replaceOccurrencesOfString: @"&" withString: @"&" options: NSLiteralSearch range: NSMakeRange(0, [string length])];
40 | [string replaceOccurrencesOfString: @">" withString: @">" options: NSLiteralSearch range: NSMakeRange(0, [string length])];
41 | [string replaceOccurrencesOfString: @"<" withString: @"<" options: NSLiteralSearch range: NSMakeRange(0, [string length])];
42 |
43 | return [NSString stringWithString: string];
44 | }
45 |
46 | @end
47 |
--------------------------------------------------------------------------------
/Pods/xmlrpc/XMLRPC.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 | #import
4 | #import
5 | #import
6 |
--------------------------------------------------------------------------------
/Pods/xmlrpc/XMLRPCConnection.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import "XMLRPCConnectionDelegate.h"
3 |
4 | @class XMLRPCConnectionManager, XMLRPCRequest, XMLRPCResponse;
5 |
6 | @interface XMLRPCConnection : NSObject {
7 | XMLRPCConnectionManager *myManager;
8 | XMLRPCRequest *myRequest;
9 | NSString *myIdentifier;
10 | NSMutableData *myData;
11 | NSURLConnection *myConnection;
12 | id myDelegate;
13 | }
14 |
15 | - (id)initWithXMLRPCRequest: (XMLRPCRequest *)request delegate: (id)delegate manager: (XMLRPCConnectionManager *)manager;
16 |
17 | #pragma mark -
18 |
19 | + (XMLRPCResponse *)sendSynchronousXMLRPCRequest: (XMLRPCRequest *)request error: (NSError **)error;
20 |
21 | #pragma mark -
22 |
23 | - (NSString *)identifier;
24 |
25 | #pragma mark -
26 |
27 | - (id)delegate;
28 |
29 | #pragma mark -
30 |
31 | - (void)cancel;
32 |
33 | @end
34 |
--------------------------------------------------------------------------------
/Pods/xmlrpc/XMLRPCConnection.m:
--------------------------------------------------------------------------------
1 | #import "XMLRPCConnection.h"
2 | #import "XMLRPCConnectionManager.h"
3 | #import "XMLRPCRequest.h"
4 | #import "XMLRPCResponse.h"
5 | #import "NSStringAdditions.h"
6 |
7 | static NSOperationQueue *parsingQueue;
8 |
9 | @interface XMLRPCConnection (XMLRPCConnectionPrivate)
10 |
11 | - (void)connection: (NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
12 |
13 | - (void)connection: (NSURLConnection *)connection didReceiveData: (NSData *)data;
14 |
15 | - (void)connection: (NSURLConnection *)connection didSendBodyData: (NSInteger)bytesWritten totalBytesWritten: (NSInteger)totalBytesWritten totalBytesExpectedToWrite: (NSInteger)totalBytesExpectedToWrite;
16 |
17 | - (void)connection: (NSURLConnection *)connection didFailWithError: (NSError *)error;
18 |
19 | #pragma mark -
20 |
21 | - (BOOL)connection: (NSURLConnection *)connection canAuthenticateAgainstProtectionSpace: (NSURLProtectionSpace *)protectionSpace;
22 |
23 | - (void)connection: (NSURLConnection *)connection didReceiveAuthenticationChallenge: (NSURLAuthenticationChallenge *)challenge;
24 |
25 | - (void)connection: (NSURLConnection *)connection didCancelAuthenticationChallenge: (NSURLAuthenticationChallenge *)challenge;
26 |
27 | - (void)connectionDidFinishLoading: (NSURLConnection *)connection;
28 |
29 | #pragma mark -
30 |
31 | - (void)timeoutExpired;
32 | - (void)invalidateTimer;
33 |
34 | #pragma mark -
35 |
36 | + (NSOperationQueue *)parsingQueue;
37 |
38 | @end
39 |
40 | #pragma mark -
41 |
42 | @implementation XMLRPCConnection
43 |
44 | - (id)initWithXMLRPCRequest: (XMLRPCRequest *)request delegate: (id)delegate manager: (XMLRPCConnectionManager *)manager {
45 | self = [super init];
46 | if (self) {
47 | #if ! __has_feature(objc_arc)
48 | myManager = [manager retain];
49 | myRequest = [request retain];
50 | myIdentifier = [[NSString stringByGeneratingUUID] retain];
51 | #else
52 | myManager = manager;
53 | myRequest = request;
54 | myIdentifier = [NSString stringByGeneratingUUID];
55 | #endif
56 | myData = [[NSMutableData alloc] init];
57 |
58 | myConnection = [[NSURLConnection alloc] initWithRequest: [request request] delegate: self startImmediately:NO];
59 | [myConnection scheduleInRunLoop:[NSRunLoop mainRunLoop]
60 | forMode:NSDefaultRunLoopMode];
61 | [myConnection start];
62 |
63 | #if ! __has_feature(objc_arc)
64 | myDelegate = [delegate retain];
65 | #else
66 | myDelegate = delegate;
67 | #endif
68 |
69 | if (myConnection) {
70 | NSLog(@"The connection, %@, has been established!", myIdentifier);
71 |
72 | [self performSelector:@selector(timeoutExpired) withObject:nil afterDelay:[myRequest timeout]];
73 | } else {
74 | NSLog(@"The connection, %@, could not be established!", myIdentifier);
75 | #if ! __has_feature(objc_arc)
76 | [self release];
77 | #endif
78 | return nil;
79 | }
80 | }
81 |
82 | return self;
83 | }
84 |
85 | #pragma mark -
86 |
87 | + (XMLRPCResponse *)sendSynchronousXMLRPCRequest: (XMLRPCRequest *)request error: (NSError **)error {
88 | NSHTTPURLResponse *response = nil;
89 | #if ! __has_feature(objc_arc)
90 | NSData *data = [[[NSURLConnection sendSynchronousRequest: [request request] returningResponse: &response error: error] retain] autorelease];
91 | #else
92 | NSData *data = [NSURLConnection sendSynchronousRequest: [request request] returningResponse: &response error: error];
93 | #endif
94 |
95 | if (response) {
96 | NSInteger statusCode = [response statusCode];
97 |
98 | if ((statusCode < 400) && data) {
99 | #if ! __has_feature(objc_arc)
100 | return [[[XMLRPCResponse alloc] initWithData: data] autorelease];
101 | #else
102 | return [[XMLRPCResponse alloc] initWithData: data];
103 | #endif
104 | }
105 | }
106 |
107 | return nil;
108 | }
109 |
110 | #pragma mark -
111 |
112 | - (NSString *)identifier {
113 | #if ! __has_feature(objc_arc)
114 | return [[myIdentifier retain] autorelease];
115 | #else
116 | return myIdentifier;
117 | #endif
118 | }
119 |
120 | #pragma mark -
121 |
122 | - (id)delegate {
123 | return myDelegate;
124 | }
125 |
126 | #pragma mark -
127 |
128 | - (void)cancel {
129 | [myConnection cancel];
130 |
131 | [self invalidateTimer];
132 | }
133 |
134 | #pragma mark -
135 |
136 | - (void)dealloc {
137 | #if ! __has_feature(objc_arc)
138 | [myManager release];
139 | [myRequest release];
140 | [myIdentifier release];
141 | [myData release];
142 | [myConnection release];
143 | [myDelegate release];
144 |
145 | [super dealloc];
146 | #endif
147 | }
148 |
149 | @end
150 |
151 | #pragma mark -
152 |
153 | @implementation XMLRPCConnection (XMLRPCConnectionPrivate)
154 |
155 | - (void)connection: (NSURLConnection *)connection didReceiveResponse: (NSURLResponse *)response {
156 | if([response respondsToSelector: @selector(statusCode)]) {
157 | NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode];
158 |
159 | if(statusCode >= 400) {
160 | NSError *error = [NSError errorWithDomain: @"HTTP" code: statusCode userInfo: nil];
161 |
162 | [myDelegate request: myRequest didFailWithError: error];
163 | } else if (statusCode == 304) {
164 | [myManager closeConnectionForIdentifier: myIdentifier];
165 | }
166 | }
167 |
168 | [myData setLength: 0];
169 | }
170 |
171 | - (void)connection: (NSURLConnection *)connection didReceiveData: (NSData *)data {
172 | [myData appendData: data];
173 | }
174 |
175 | - (void)connection: (NSURLConnection *)connection didSendBodyData: (NSInteger)bytesWritten totalBytesWritten: (NSInteger)totalBytesWritten totalBytesExpectedToWrite: (NSInteger)totalBytesExpectedToWrite {
176 | if ([myDelegate respondsToSelector: @selector(request:didSendBodyData:)]) {
177 | float percent = totalBytesWritten / (float)totalBytesExpectedToWrite;
178 |
179 | [myDelegate request:myRequest didSendBodyData:percent];
180 | }
181 | }
182 |
183 | - (void)connection: (NSURLConnection *)connection didFailWithError: (NSError *)error {
184 | #if ! __has_feature(objc_arc)
185 | XMLRPCRequest *request = [[myRequest retain] autorelease];
186 | #else
187 | XMLRPCRequest *request = myRequest;
188 | #endif
189 |
190 | NSLog(@"The connection, %@, failed with the following error: %@", myIdentifier, [error localizedDescription]);
191 |
192 | [self invalidateTimer];
193 |
194 | [myDelegate request: request didFailWithError: error];
195 |
196 | [myManager closeConnectionForIdentifier: myIdentifier];
197 | }
198 |
199 | #pragma mark -
200 |
201 | - (BOOL)connection: (NSURLConnection *)connection canAuthenticateAgainstProtectionSpace: (NSURLProtectionSpace *)protectionSpace {
202 | return [myDelegate request: myRequest canAuthenticateAgainstProtectionSpace: protectionSpace];
203 | }
204 |
205 | - (void)connection: (NSURLConnection *)connection didReceiveAuthenticationChallenge: (NSURLAuthenticationChallenge *)challenge {
206 | [myDelegate request: myRequest didReceiveAuthenticationChallenge: challenge];
207 | }
208 |
209 | - (void)connection: (NSURLConnection *)connection didCancelAuthenticationChallenge: (NSURLAuthenticationChallenge *)challenge {
210 | [myDelegate request: myRequest didCancelAuthenticationChallenge: challenge];
211 | }
212 |
213 | - (void)connectionDidFinishLoading: (NSURLConnection *)connection {
214 | [self invalidateTimer];
215 | if (myData && ([myData length] > 0)) {
216 | NSBlockOperation *parsingOperation;
217 |
218 | #if ! __has_feature(objc_arc)
219 | parsingOperation = [NSBlockOperation blockOperationWithBlock:^{
220 | XMLRPCResponse *response = [[[XMLRPCResponse alloc] initWithData: myData] autorelease];
221 | XMLRPCRequest *request = [[myRequest retain] autorelease];
222 |
223 | [[NSOperationQueue mainQueue] addOperation: [NSBlockOperation blockOperationWithBlock:^{
224 | [myDelegate request: request didReceiveResponse: response];
225 | }]];
226 | }];
227 | #else
228 | parsingOperation = [NSBlockOperation blockOperationWithBlock:^{
229 | XMLRPCResponse *response = [[XMLRPCResponse alloc] initWithData: myData];
230 | XMLRPCRequest *request = myRequest;
231 |
232 | [[NSOperationQueue mainQueue] addOperation: [NSBlockOperation blockOperationWithBlock:^{
233 | [myDelegate request: request didReceiveResponse: response];
234 |
235 | [myManager closeConnectionForIdentifier: myIdentifier];
236 | }]];
237 | }];
238 | #endif
239 |
240 | [[XMLRPCConnection parsingQueue] addOperation: parsingOperation];
241 | }
242 | else {
243 | [myManager closeConnectionForIdentifier: myIdentifier];
244 | }
245 | }
246 |
247 | #pragma mark -
248 | - (void)timeoutExpired
249 | {
250 | NSDictionary *userInfo = [NSDictionary dictionaryWithObjectsAndKeys:
251 | [myRequest URL], NSURLErrorFailingURLErrorKey,
252 | [[myRequest URL] absoluteString], NSURLErrorFailingURLStringErrorKey,
253 | //TODO not good to use hardcoded value for localized description
254 | @"The request timed out.", NSLocalizedDescriptionKey,
255 | nil];
256 |
257 | NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorTimedOut userInfo:userInfo];
258 |
259 | [self connection:myConnection didFailWithError:error];
260 | }
261 |
262 | - (void)invalidateTimer
263 | {
264 | [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(timeoutExpired) object:nil];
265 | }
266 |
267 | #pragma mark -
268 |
269 | + (NSOperationQueue *)parsingQueue {
270 | if (parsingQueue == nil) {
271 | parsingQueue = [[NSOperationQueue alloc] init];
272 | }
273 |
274 | return parsingQueue;
275 | }
276 |
277 | @end
278 |
--------------------------------------------------------------------------------
/Pods/xmlrpc/XMLRPCConnectionDelegate.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | @class XMLRPCConnection, XMLRPCRequest, XMLRPCResponse;
4 |
5 | @protocol XMLRPCConnectionDelegate
6 |
7 | @required
8 | - (void)request: (XMLRPCRequest *)request didReceiveResponse: (XMLRPCResponse *)response;
9 |
10 | @optional
11 | - (void)request: (XMLRPCRequest *)request didSendBodyData: (float)percent;
12 |
13 | @required
14 | - (void)request: (XMLRPCRequest *)request didFailWithError: (NSError *)error;
15 |
16 | #pragma mark -
17 |
18 | @required
19 | - (BOOL)request: (XMLRPCRequest *)request canAuthenticateAgainstProtectionSpace: (NSURLProtectionSpace *)protectionSpace;
20 |
21 | @required
22 | - (void)request: (XMLRPCRequest *)request didReceiveAuthenticationChallenge: (NSURLAuthenticationChallenge *)challenge;
23 |
24 | @required
25 | - (void)request: (XMLRPCRequest *)request didCancelAuthenticationChallenge: (NSURLAuthenticationChallenge *)challenge;
26 |
27 | @end
28 |
--------------------------------------------------------------------------------
/Pods/xmlrpc/XMLRPCConnectionManager.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import "XMLRPCConnectionDelegate.h"
3 |
4 | @class XMLRPCConnection, XMLRPCRequest;
5 |
6 | @interface XMLRPCConnectionManager : NSObject {
7 | NSMutableDictionary *myConnections;
8 | }
9 |
10 | + (XMLRPCConnectionManager *)sharedManager;
11 |
12 | #pragma mark -
13 |
14 | - (NSString *)spawnConnectionWithXMLRPCRequest: (XMLRPCRequest *)request delegate: (id)delegate;
15 |
16 | #pragma mark -
17 |
18 | - (NSArray *)activeConnectionIdentifiers;
19 |
20 | - (NSUInteger)numberOfActiveConnections;
21 |
22 | #pragma mark -
23 |
24 | - (XMLRPCConnection *)connectionForIdentifier: (NSString *)identifier;
25 |
26 | #pragma mark -
27 |
28 | - (void)closeConnectionForIdentifier: (NSString *)identifier;
29 |
30 | - (void)closeConnections;
31 |
32 | @end
33 |
--------------------------------------------------------------------------------
/Pods/xmlrpc/XMLRPCConnectionManager.m:
--------------------------------------------------------------------------------
1 | #import "XMLRPCConnectionManager.h"
2 | #import "XMLRPCConnection.h"
3 | #import "XMLRPCRequest.h"
4 |
5 | @implementation XMLRPCConnectionManager
6 |
7 | static XMLRPCConnectionManager *sharedInstance = nil;
8 |
9 | - (id)init {
10 | self = [super init];
11 | if (self) {
12 | myConnections = [[NSMutableDictionary alloc] init];
13 | }
14 |
15 | return self;
16 | }
17 |
18 | #pragma mark -
19 |
20 | + (id)allocWithZone: (NSZone *)zone {
21 | @synchronized(self) {
22 | if (!sharedInstance) {
23 | sharedInstance = [super allocWithZone: zone];
24 |
25 | return sharedInstance;
26 | }
27 | }
28 |
29 | return nil;
30 | }
31 |
32 | #pragma mark -
33 |
34 | + (XMLRPCConnectionManager *)sharedManager {
35 | @synchronized(self) {
36 | if (!sharedInstance) {
37 | sharedInstance = [[self alloc] init];
38 | }
39 | }
40 |
41 | return sharedInstance;
42 | }
43 |
44 | #pragma mark -
45 |
46 | - (NSString *)spawnConnectionWithXMLRPCRequest: (XMLRPCRequest *)request delegate: (id)delegate {
47 | XMLRPCConnection *newConnection = [[XMLRPCConnection alloc] initWithXMLRPCRequest: request delegate: delegate manager: self];
48 | #if ! __has_feature(objc_arc)
49 | NSString *identifier = [[[newConnection identifier] retain] autorelease];
50 | #else
51 | NSString *identifier = [newConnection identifier];
52 | #endif
53 |
54 | [myConnections setObject: newConnection forKey: identifier];
55 |
56 | #if ! __has_feature(objc_arc)
57 | [newConnection release];
58 | #endif
59 |
60 | return identifier;
61 | }
62 |
63 | #pragma mark -
64 |
65 | - (NSArray *)activeConnectionIdentifiers {
66 | return [myConnections allKeys];
67 | }
68 |
69 | - (NSUInteger)numberOfActiveConnections {
70 | return [myConnections count];
71 | }
72 |
73 | #pragma mark -
74 |
75 | - (XMLRPCConnection *)connectionForIdentifier: (NSString *)identifier {
76 | return [myConnections objectForKey: identifier];
77 | }
78 |
79 | #pragma mark -
80 |
81 | - (void)closeConnectionForIdentifier: (NSString *)identifier {
82 | XMLRPCConnection *selectedConnection = [self connectionForIdentifier: identifier];
83 |
84 | if (selectedConnection) {
85 | [selectedConnection cancel];
86 |
87 | [myConnections removeObjectForKey: identifier];
88 | }
89 | }
90 |
91 | - (void)closeConnections {
92 | [[myConnections allValues] makeObjectsPerformSelector: @selector(cancel)];
93 |
94 | [myConnections removeAllObjects];
95 | }
96 |
97 | #pragma mark -
98 |
99 |
100 | #pragma mark -
101 |
102 | - (void)dealloc {
103 | [self closeConnections];
104 |
105 | #if ! __has_feature(objc_arc)
106 | [myConnections release];
107 |
108 | [super dealloc];
109 | #endif
110 | }
111 |
112 | @end
113 |
--------------------------------------------------------------------------------
/Pods/xmlrpc/XMLRPCDefaultEncoder.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import "XMLRPCEncoder.h"
3 |
4 | @interface XMLRPCDefaultEncoder : NSObject {
5 | NSString *myMethod;
6 | NSArray *myParameters;
7 | }
8 |
9 | @end
10 |
--------------------------------------------------------------------------------
/Pods/xmlrpc/XMLRPCDefaultEncoder.m:
--------------------------------------------------------------------------------
1 | #import "XMLRPCDefaultEncoder.h"
2 | #import "NSStringAdditions.h"
3 | #import "NSData+Base64.h"
4 |
5 | @interface XMLRPCDefaultEncoder (XMLRPCEncoderPrivate)
6 |
7 | - (NSString *)valueTag: (NSString *)tag value: (NSString *)value;
8 |
9 | #pragma mark -
10 |
11 | - (NSString *)replaceTarget: (NSString *)target withValue: (NSString *)value inString: (NSString *)string;
12 |
13 | #pragma mark -
14 |
15 | - (NSString *)encodeObject: (id)object;
16 |
17 | #pragma mark -
18 |
19 | - (NSString *)encodeArray: (NSArray *)array;
20 |
21 | - (NSString *)encodeDictionary: (NSDictionary *)dictionary;
22 |
23 | #pragma mark -
24 |
25 | - (NSString *)encodeBoolean: (CFBooleanRef)boolean;
26 |
27 | - (NSString *)encodeNumber: (NSNumber *)number;
28 |
29 | - (NSString *)encodeString: (NSString *)string omitTag: (BOOL)omitTag;
30 |
31 | - (NSString *)encodeDate: (NSDate *)date;
32 |
33 | - (NSString *)encodeData: (NSData *)data;
34 |
35 | @end
36 |
37 | #pragma mark -
38 |
39 | @implementation XMLRPCDefaultEncoder
40 |
41 | - (id)init {
42 | if (self = [super init]) {
43 | myMethod = [[NSString alloc] init];
44 | myParameters = [[NSArray alloc] init];
45 | }
46 |
47 | return self;
48 | }
49 |
50 | #pragma mark -
51 |
52 | - (NSString *)encode {
53 | NSMutableString *buffer = [NSMutableString stringWithString: @""];
54 |
55 | [buffer appendFormat: @"%@ ", [self encodeString: myMethod omitTag: YES]];
56 |
57 | [buffer appendString: @""];
58 |
59 | if (myParameters) {
60 | NSEnumerator *enumerator = [myParameters objectEnumerator];
61 | id parameter = nil;
62 |
63 | while ((parameter = [enumerator nextObject])) {
64 | [buffer appendString: @" "];
65 | [buffer appendString: [self encodeObject: parameter]];
66 | [buffer appendString: @""];
67 | }
68 | }
69 |
70 | [buffer appendString: @" "];
71 |
72 | [buffer appendString: @" "];
73 |
74 | return buffer;
75 | }
76 |
77 | #pragma mark -
78 |
79 | - (void)setMethod: (NSString *)method withParameters: (NSArray *)parameters {
80 | #if ! __has_feature(objc_arc)
81 | if (myMethod) {
82 | [myMethod release];
83 | }
84 |
85 | if (!method) {
86 | myMethod = nil;
87 | } else {
88 | myMethod = [method retain];
89 | }
90 |
91 | if (myParameters) {
92 | [myParameters release];
93 | }
94 |
95 | if (!parameters) {
96 | myParameters = nil;
97 | } else {
98 | myParameters = [parameters retain];
99 | }
100 | #else
101 | myMethod = method;
102 | myParameters = parameters;
103 | #endif
104 | }
105 |
106 | #pragma mark -
107 |
108 | - (NSString *)method {
109 | return myMethod;
110 | }
111 |
112 | - (NSArray *)parameters {
113 | return myParameters;
114 | }
115 |
116 | #pragma mark -
117 |
118 | - (void)dealloc {
119 | #if ! __has_feature(objc_arc)
120 | [myMethod release];
121 | [myParameters release];
122 |
123 | [super dealloc];
124 | #endif
125 | }
126 |
127 | @end
128 |
129 | #pragma mark -
130 |
131 | @implementation XMLRPCDefaultEncoder (XMLRPCEncoderPrivate)
132 |
133 | - (NSString *)valueTag: (NSString *)tag value: (NSString *)value {
134 | return [NSString stringWithFormat: @"<%@>%@%@> ", tag, value, tag];
135 | }
136 |
137 | #pragma mark -
138 |
139 | - (NSString *)replaceTarget: (NSString *)target withValue: (NSString *)value inString: (NSString *)string {
140 | return [[string componentsSeparatedByString: target] componentsJoinedByString: value];
141 | }
142 |
143 | #pragma mark -
144 |
145 | - (NSString *)encodeObject: (id)object {
146 | if (!object) {
147 | return nil;
148 | }
149 |
150 | if ([object isKindOfClass: [NSArray class]]) {
151 | return [self encodeArray: object];
152 | } else if ([object isKindOfClass: [NSDictionary class]]) {
153 | return [self encodeDictionary: object];
154 | #if ! __has_feature(objc_arc)
155 | } else if (((CFBooleanRef)object == kCFBooleanTrue) || ((CFBooleanRef)object == kCFBooleanFalse)) {
156 | #else
157 | } else if (((__bridge CFBooleanRef)object == kCFBooleanTrue) || ((__bridge CFBooleanRef)object == kCFBooleanFalse)) {
158 | #endif
159 | return [self encodeBoolean: (CFBooleanRef)object];
160 | } else if ([object isKindOfClass: [NSNumber class]]) {
161 | return [self encodeNumber: object];
162 | } else if ([object isKindOfClass: [NSString class]]) {
163 | return [self encodeString: object omitTag: NO];
164 | } else if ([object isKindOfClass: [NSDate class]]) {
165 | return [self encodeDate: object];
166 | } else if ([object isKindOfClass: [NSData class]]) {
167 | return [self encodeData: object];
168 | } else {
169 | return [self encodeString: object omitTag: NO];
170 | }
171 | }
172 |
173 | #pragma mark -
174 |
175 | - (NSString *)encodeArray: (NSArray *)array {
176 | NSMutableString *buffer = [NSMutableString string];
177 | NSEnumerator *enumerator = [array objectEnumerator];
178 |
179 | [buffer appendString: @""];
180 |
181 | id object = nil;
182 |
183 | while (object = [enumerator nextObject]) {
184 | [buffer appendString: [self encodeObject: object]];
185 | }
186 |
187 | [buffer appendString: @" "];
188 |
189 | return (NSString *)buffer;
190 | }
191 |
192 | - (NSString *)encodeDictionary: (NSDictionary *)dictionary {
193 | NSMutableString * buffer = [NSMutableString string];
194 | NSEnumerator *enumerator = [dictionary keyEnumerator];
195 |
196 | [buffer appendString: @""];
197 |
198 | NSString *key = nil;
199 | NSObject *val;
200 |
201 | while (key = [enumerator nextObject]) {
202 | [buffer appendString: @""];
203 | [buffer appendFormat: @"%@ ", [self encodeString: key omitTag: YES]];
204 |
205 | val = [dictionary objectForKey: key];
206 | if (val != [NSNull null]) {
207 | [buffer appendString: [self encodeObject: val]];
208 | } else {
209 | [buffer appendString:@" "];
210 | }
211 |
212 | [buffer appendString: @" "];
213 | }
214 |
215 | [buffer appendString: @" "];
216 |
217 | return (NSString *)buffer;
218 | }
219 |
220 | #pragma mark -
221 |
222 | - (NSString *)encodeBoolean: (CFBooleanRef)boolean {
223 | if (boolean == kCFBooleanTrue) {
224 | return [self valueTag: @"boolean" value: @"1"];
225 | } else {
226 | return [self valueTag: @"boolean" value: @"0"];
227 | }
228 | }
229 |
230 | - (NSString *)encodeNumber: (NSNumber *)number {
231 | NSString *numberType = [NSString stringWithCString: [number objCType] encoding: NSUTF8StringEncoding];
232 |
233 | if ([numberType isEqualToString: @"d"]) {
234 | return [self valueTag: @"double" value: [number stringValue]];
235 | } else {
236 | return [self valueTag: @"i4" value: [number stringValue]];
237 | }
238 | }
239 |
240 | - (NSString *)encodeString: (NSString *)string omitTag: (BOOL)omitTag {
241 | return omitTag ? [string escapedString] : [self valueTag: @"string" value: [string escapedString]];
242 | }
243 |
244 | - (NSString *)encodeDate: (NSDate *)date {
245 | unsigned components = kCFCalendarUnitYear | kCFCalendarUnitMonth | kCFCalendarUnitDay | kCFCalendarUnitHour | kCFCalendarUnitMinute | kCFCalendarUnitSecond;
246 | NSDateComponents *dateComponents = [[NSCalendar currentCalendar] components: components fromDate: date];
247 | NSString *buffer = [NSString stringWithFormat: @"%.4ld%.2ld%.2ldT%.2ld:%.2ld:%.2ld", (long)[dateComponents year], (long)[dateComponents month], (long)[dateComponents day], (long)[dateComponents hour], (long)[dateComponents minute], (long)[dateComponents second], nil];
248 |
249 | return [self valueTag: @"dateTime.iso8601" value: buffer];
250 | }
251 |
252 | - (NSString *)encodeData: (NSData *)data {
253 | return [self valueTag: @"base64" value: [data base64EncodedString]];
254 | }
255 |
256 | @end
257 |
--------------------------------------------------------------------------------
/Pods/xmlrpc/XMLRPCEncoder.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | @protocol XMLRPCEncoder
4 |
5 | - (NSString *)encode;
6 |
7 | #pragma mark -
8 |
9 | - (void)setMethod: (NSString *)method withParameters: (NSArray *)parameters;
10 |
11 | #pragma mark -
12 |
13 | - (NSString *)method;
14 |
15 | - (NSArray *)parameters;
16 |
17 | @end
18 |
--------------------------------------------------------------------------------
/Pods/xmlrpc/XMLRPCEventBasedParser.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | @class XMLRPCEventBasedParserDelegate;
4 |
5 | @interface XMLRPCEventBasedParser : NSObject {
6 | NSXMLParser *myParser;
7 | XMLRPCEventBasedParserDelegate *myParserDelegate;
8 | BOOL isFault;
9 | }
10 |
11 | - (id)initWithData: (NSData *)data;
12 |
13 | #pragma mark -
14 |
15 | - (id)parse;
16 |
17 | - (void)abortParsing;
18 |
19 | #pragma mark -
20 |
21 | - (NSError *)parserError;
22 |
23 | #pragma mark -
24 |
25 | - (BOOL)isFault;
26 |
27 | @end
28 |
--------------------------------------------------------------------------------
/Pods/xmlrpc/XMLRPCEventBasedParser.m:
--------------------------------------------------------------------------------
1 | #import "XMLRPCEventBasedParser.h"
2 | #import "XMLRPCEventBasedParserDelegate.h"
3 |
4 | @implementation XMLRPCEventBasedParser
5 |
6 | - (id)initWithData: (NSData *)data {
7 | if (!data) {
8 | return nil;
9 | }
10 |
11 | if (self = [self init]) {
12 | myParser = [[NSXMLParser alloc] initWithData: data];
13 | myParserDelegate = nil;
14 | isFault = NO;
15 | }
16 |
17 | return self;
18 | }
19 |
20 | #pragma mark -
21 |
22 | - (id)parse {
23 | [myParser setDelegate: self];
24 |
25 | [myParser parse];
26 |
27 | if ([myParser parserError]) {
28 | return nil;
29 | }
30 |
31 | return [myParserDelegate elementValue];
32 | }
33 |
34 | - (void)abortParsing {
35 | [myParser abortParsing];
36 | }
37 |
38 | #pragma mark -
39 |
40 | - (NSError *)parserError {
41 | return [myParser parserError];
42 | }
43 |
44 | #pragma mark -
45 |
46 | - (BOOL)isFault {
47 | return isFault;
48 | }
49 |
50 | #pragma mark -
51 |
52 | - (void)dealloc {
53 | #if ! __has_feature(objc_arc)
54 | [myParser release];
55 | [myParserDelegate release];
56 |
57 | [super dealloc];
58 | #endif
59 | }
60 |
61 | @end
62 |
63 | #pragma mark -
64 |
65 | @implementation XMLRPCEventBasedParser (NSXMLParserDelegate)
66 |
67 | - (void)parser: (NSXMLParser *)parser didStartElement: (NSString *)element namespaceURI: (NSString *)namespaceURI qualifiedName: (NSString *)qualifiedName attributes: (NSDictionary *)attributes {
68 | if ([element isEqualToString: @"fault"]) {
69 | isFault = YES;
70 | } else if ([element isEqualToString: @"value"]) {
71 | myParserDelegate = [[XMLRPCEventBasedParserDelegate alloc] initWithParent: nil];
72 |
73 | [myParser setDelegate: myParserDelegate];
74 | }
75 | }
76 |
77 | - (void)parser: (NSXMLParser *)parser parseErrorOccurred: (NSError *)parseError {
78 | [self abortParsing];
79 | }
80 |
81 | @end
82 |
--------------------------------------------------------------------------------
/Pods/xmlrpc/XMLRPCEventBasedParserDelegate.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | typedef enum {
4 | XMLRPCElementTypeArray,
5 | XMLRPCElementTypeDictionary,
6 | XMLRPCElementTypeMember,
7 | XMLRPCElementTypeName,
8 | XMLRPCElementTypeInteger,
9 | XMLRPCElementTypeDouble,
10 | XMLRPCElementTypeBoolean,
11 | XMLRPCElementTypeString,
12 | XMLRPCElementTypeDate,
13 | XMLRPCElementTypeData
14 | } XMLRPCElementType;
15 |
16 | #pragma mark -
17 |
18 | @interface XMLRPCEventBasedParserDelegate : NSObject {
19 | #if !__has_feature(objc_arc)
20 | XMLRPCEventBasedParserDelegate *myParent;
21 | #else
22 | // Without ARC this reference is effectively unretained so don't use strong reference here.
23 | XMLRPCEventBasedParserDelegate * __unsafe_unretained myParent;
24 | #endif
25 | NSMutableSet *myChildren;
26 | XMLRPCElementType myElementType;
27 | NSString *myElementKey;
28 | id myElementValue;
29 | }
30 |
31 | - (id)initWithParent: (XMLRPCEventBasedParserDelegate *)parent;
32 |
33 | #pragma mark -
34 |
35 | - (void)setParent: (XMLRPCEventBasedParserDelegate *)parent;
36 |
37 | - (XMLRPCEventBasedParserDelegate *)parent;
38 |
39 | #pragma mark -
40 |
41 | - (void)setElementType: (XMLRPCElementType)elementType;
42 |
43 | - (XMLRPCElementType)elementType;
44 |
45 | #pragma mark -
46 |
47 | - (void)setElementKey: (NSString *)elementKey;
48 |
49 | - (NSString *)elementKey;
50 |
51 | #pragma mark -
52 |
53 | - (void)setElementValue: (id)elementValue;
54 |
55 | - (id)elementValue;
56 |
57 | @end
58 |
--------------------------------------------------------------------------------
/Pods/xmlrpc/XMLRPCEventBasedParserDelegate.m:
--------------------------------------------------------------------------------
1 | #import "XMLRPCEventBasedParserDelegate.h"
2 | #import "NSData+Base64.h"
3 |
4 | @interface XMLRPCEventBasedParserDelegate (XMLRPCEventBasedParserDelegatePrivate)
5 |
6 | - (BOOL)isDictionaryElementType: (XMLRPCElementType)elementType;
7 |
8 | #pragma mark -
9 |
10 | - (void)addElementValueToParent;
11 |
12 | #pragma mark -
13 |
14 | - (NSDate *)parseDateString: (NSString *)dateString withFormat: (NSString *)format;
15 |
16 | #pragma mark -
17 |
18 | - (NSNumber *)parseInteger: (NSString *)value;
19 |
20 | - (NSNumber *)parseDouble: (NSString *)value;
21 |
22 | - (NSNumber *)parseBoolean: (NSString *)value;
23 |
24 | - (NSString *)parseString: (NSString *)value;
25 |
26 | - (NSDate *)parseDate: (NSString *)value;
27 |
28 | - (NSData *)parseData: (NSString *)value;
29 |
30 | @end
31 |
32 | #pragma mark -
33 |
34 | @implementation XMLRPCEventBasedParserDelegate
35 |
36 | - (id)initWithParent: (XMLRPCEventBasedParserDelegate *)parent {
37 | self = [super init];
38 | if (self) {
39 | myParent = parent;
40 | myChildren = [[NSMutableSet alloc] initWithCapacity: 1];
41 | myElementType = XMLRPCElementTypeString;
42 | myElementKey = nil;
43 | myElementValue = [[NSMutableString alloc] init];
44 | }
45 |
46 | return self;
47 | }
48 |
49 | #pragma mark -
50 |
51 | - (void)setParent: (XMLRPCEventBasedParserDelegate *)parent {
52 | #if ! __has_feature(objc_arc)
53 | [parent retain];
54 | [myParent release];
55 | #endif
56 |
57 | myParent = parent;
58 | }
59 |
60 | - (XMLRPCEventBasedParserDelegate *)parent {
61 | return myParent;
62 | }
63 |
64 | #pragma mark -
65 |
66 | - (void)setElementType: (XMLRPCElementType)elementType {
67 | myElementType = elementType;
68 | }
69 |
70 | - (XMLRPCElementType)elementType {
71 | return myElementType;
72 | }
73 |
74 | #pragma mark -
75 |
76 | - (void)setElementKey: (NSString *)elementKey {
77 | #if ! __has_feature(objc_arc)
78 | [elementKey retain];
79 | [myElementKey release];
80 | #endif
81 |
82 | myElementKey = elementKey;
83 | }
84 |
85 | - (NSString *)elementKey {
86 | return myElementKey;
87 | }
88 |
89 | #pragma mark -
90 |
91 | - (void)setElementValue: (id)elementValue {
92 | #if ! __has_feature(objc_arc)
93 | [elementValue retain];
94 | [myElementValue release];
95 | #endif
96 |
97 | myElementValue = elementValue;
98 | }
99 |
100 | - (id)elementValue {
101 | return myElementValue;
102 | }
103 |
104 | #pragma mark -
105 |
106 | - (void)dealloc {
107 | #if ! __has_feature(objc_arc)
108 | [myChildren release];
109 | [myElementKey release];
110 | [myElementValue release];
111 |
112 | [super dealloc];
113 | #endif
114 | }
115 |
116 | @end
117 |
118 | #pragma mark -
119 |
120 | @implementation XMLRPCEventBasedParserDelegate (NSXMLParserDelegate)
121 |
122 | - (void)parser: (NSXMLParser *)parser didStartElement: (NSString *)element namespaceURI: (NSString *)namespaceURI qualifiedName: (NSString *)qualifiedName attributes: (NSDictionary *)attributes {
123 | if ([element isEqualToString: @"value"] || [element isEqualToString: @"member"] || [element isEqualToString: @"name"]) {
124 | XMLRPCEventBasedParserDelegate *parserDelegate = [[XMLRPCEventBasedParserDelegate alloc] initWithParent: self];
125 |
126 | if ([element isEqualToString: @"member"]) {
127 | [parserDelegate setElementType: XMLRPCElementTypeMember];
128 | } else if ([element isEqualToString: @"name"]) {
129 | [parserDelegate setElementType: XMLRPCElementTypeName];
130 | }
131 |
132 | [myChildren addObject: parserDelegate];
133 |
134 | [parser setDelegate: parserDelegate];
135 | #if ! __has_feature(objc_arc)
136 | [parserDelegate release];
137 | #endif
138 | return;
139 | }
140 |
141 | if ([element isEqualToString: @"array"]) {
142 | NSMutableArray *array = [[NSMutableArray alloc] init];
143 |
144 | [self setElementValue: array];
145 | #if ! __has_feature(objc_arc)
146 | [array release];
147 | #endif
148 | [self setElementType: XMLRPCElementTypeArray];
149 | } else if ([element isEqualToString: @"struct"]) {
150 | NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
151 |
152 | [self setElementValue: dictionary];
153 | #if ! __has_feature(objc_arc)
154 | [dictionary release];
155 | #endif
156 | [self setElementType: XMLRPCElementTypeDictionary];
157 | } else if ([element isEqualToString: @"int"] || [element isEqualToString: @"i4"]) {
158 | [self setElementType: XMLRPCElementTypeInteger];
159 | } else if ([element isEqualToString: @"double"]) {
160 | [self setElementType: XMLRPCElementTypeDouble];
161 | } else if ([element isEqualToString: @"boolean"]) {
162 | [self setElementType: XMLRPCElementTypeBoolean];
163 | } else if ([element isEqualToString: @"string"]) {
164 | [self setElementType: XMLRPCElementTypeString];
165 | } else if ([element isEqualToString: @"dateTime.iso8601"]) {
166 | [self setElementType: XMLRPCElementTypeDate];
167 | } else if ([element isEqualToString: @"base64"]) {
168 | [self setElementType: XMLRPCElementTypeData];
169 | }
170 | }
171 |
172 | - (void)parser: (NSXMLParser *)parser didEndElement: (NSString *)element namespaceURI: (NSString *)namespaceURI qualifiedName: (NSString *)qualifiedName {
173 | if ([element isEqualToString: @"value"] || [element isEqualToString: @"member"] || [element isEqualToString: @"name"]) {
174 | NSString *elementValue = nil;
175 |
176 | if ((myElementType != XMLRPCElementTypeArray) && ![self isDictionaryElementType: myElementType]) {
177 | elementValue = [self parseString: myElementValue];
178 | #if ! __has_feature(objc_arc)
179 | [myElementValue release];
180 | #endif
181 | myElementValue = nil;
182 | }
183 |
184 | switch (myElementType) {
185 | case XMLRPCElementTypeInteger:
186 | myElementValue = [self parseInteger: elementValue];
187 | #if ! __has_feature(objc_arc)
188 | [myElementValue retain];
189 | #endif
190 | break;
191 | case XMLRPCElementTypeDouble:
192 | myElementValue = [self parseDouble: elementValue];
193 | #if ! __has_feature(objc_arc)
194 | [myElementValue retain];
195 | #endif
196 | break;
197 | case XMLRPCElementTypeBoolean:
198 | myElementValue = [self parseBoolean: elementValue];
199 | #if ! __has_feature(objc_arc)
200 | [myElementValue retain];
201 | #endif
202 | break;
203 | case XMLRPCElementTypeString:
204 | case XMLRPCElementTypeName:
205 | myElementValue = elementValue;
206 | #if ! __has_feature(objc_arc)
207 | [myElementValue retain];
208 | #endif
209 | break;
210 | case XMLRPCElementTypeDate:
211 | myElementValue = [self parseDate: elementValue];
212 | #if ! __has_feature(objc_arc)
213 | [myElementValue retain];
214 | #endif
215 | break;
216 | case XMLRPCElementTypeData:
217 | myElementValue = [self parseData: elementValue];
218 | #if ! __has_feature(objc_arc)
219 | [myElementValue retain];
220 | #endif
221 | break;
222 | default:
223 | break;
224 | }
225 |
226 | if (myParent && myElementValue) {
227 | [self addElementValueToParent];
228 | }
229 |
230 | [parser setDelegate: myParent];
231 |
232 | if (myParent) {
233 | XMLRPCEventBasedParserDelegate *parent = myParent;
234 |
235 | // Set it to nil explicitly since it's not __weak but __unsafe_unretained.
236 | // We're doing it here because if we'll do it after removal from myChildren
237 | // self can already be deallocated, and accessing field of deallocated object
238 | // causes memory corruption.
239 | myParent = nil;
240 |
241 | [parent->myChildren removeObject: self];
242 | }
243 | }
244 | }
245 |
246 | - (void)parser: (NSXMLParser *)parser foundCharacters: (NSString *)string {
247 | if ((myElementType == XMLRPCElementTypeArray) || [self isDictionaryElementType: myElementType]) {
248 | return;
249 | }
250 |
251 | if (!myElementValue) {
252 | myElementValue = [[NSMutableString alloc] initWithString: string];
253 | } else {
254 | [myElementValue appendString: string];
255 | }
256 | }
257 |
258 | - (void)parser: (NSXMLParser *)parser parseErrorOccurred: (NSError *)parseError {
259 | [parser abortParsing];
260 | }
261 |
262 | @end
263 |
264 | #pragma mark -
265 |
266 | @implementation XMLRPCEventBasedParserDelegate (XMLRPCEventBasedParserDelegatePrivate)
267 |
268 | - (BOOL)isDictionaryElementType: (XMLRPCElementType)elementType {
269 | if ((myElementType == XMLRPCElementTypeDictionary) || (myElementType == XMLRPCElementTypeMember)) {
270 | return YES;
271 | }
272 |
273 | return NO;
274 | }
275 |
276 | #pragma mark -
277 |
278 | - (void)addElementValueToParent {
279 | id parentElementValue = [myParent elementValue];
280 |
281 | switch ([myParent elementType]) {
282 | case XMLRPCElementTypeArray:
283 | [parentElementValue addObject: myElementValue];
284 |
285 | break;
286 | case XMLRPCElementTypeDictionary:
287 | if ([myElementValue isEqual:[NSNull null]]) {
288 | [parentElementValue removeObjectForKey:myElementKey];
289 | } else {
290 | [parentElementValue setObject: myElementValue forKey: myElementKey];
291 | }
292 |
293 | break;
294 | case XMLRPCElementTypeMember:
295 | if (myElementType == XMLRPCElementTypeName) {
296 | [myParent setElementKey: myElementValue];
297 | } else {
298 | [myParent setElementValue: myElementValue];
299 | }
300 |
301 | break;
302 | default:
303 | break;
304 | }
305 | }
306 |
307 | #pragma mark -
308 |
309 | - (NSDate *)parseDateString: (NSString *)dateString withFormat: (NSString *)format {
310 | NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
311 | NSDate *result = nil;
312 |
313 | [dateFormatter setDateFormat: format];
314 |
315 | result = [dateFormatter dateFromString: dateString];
316 | #if ! __has_feature(objc_arc)
317 | [dateFormatter release];
318 | #endif
319 | return result;
320 | }
321 |
322 | #pragma mark -
323 |
324 | - (NSNumber *)parseInteger: (NSString *)value {
325 | return [NSNumber numberWithInteger: [value integerValue]];
326 | }
327 |
328 | - (NSNumber *)parseDouble: (NSString *)value {
329 | return [NSNumber numberWithDouble: [value doubleValue]];
330 | }
331 |
332 | - (NSNumber *)parseBoolean: (NSString *)value {
333 | if ([value isEqualToString: @"1"]) {
334 | return [NSNumber numberWithBool: YES];
335 | }
336 |
337 | return [NSNumber numberWithBool: NO];
338 | }
339 |
340 | - (NSString *)parseString: (NSString *)value {
341 | return [value stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]];
342 | }
343 |
344 | - (NSDate *)parseDate: (NSString *)value {
345 | NSDate *result = nil;
346 |
347 | result = [self parseDateString: value withFormat: @"yyyyMMdd'T'HH:mm:ss"];
348 |
349 | if (!result) {
350 | result = [self parseDateString: value withFormat: @"yyyy'-'MM'-'dd'T'HH:mm:ss"];
351 | }
352 |
353 | if (!result) {
354 | result = [self parseDateString: value withFormat: @"yyyy'-'MM'-'dd'T'HH:mm:ssZ"];
355 | }
356 |
357 | if (!result) {
358 | result = (NSDate *)[NSNull null];
359 | }
360 |
361 | return result;
362 | }
363 |
364 | - (NSData *)parseData: (NSString *)value {
365 | return [NSData dataFromBase64String: value];
366 | }
367 |
368 | @end
369 |
--------------------------------------------------------------------------------
/Pods/xmlrpc/XMLRPCRequest.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | #import "XMLRPCEncoder.h"
4 |
5 | @interface XMLRPCRequest : NSObject {
6 | NSMutableURLRequest *myRequest;
7 | id myXMLEncoder;
8 | NSTimeInterval myTimeout;
9 |
10 | id extra;
11 | }
12 |
13 | - (id)initWithURL: (NSURL *)URL;
14 |
15 | #pragma mark -
16 |
17 | - (void)setURL: (NSURL *)URL;
18 |
19 | - (NSURL *)URL;
20 |
21 | #pragma mark -
22 |
23 | - (void)setUserAgent: (NSString *)userAgent;
24 |
25 | - (NSString *)userAgent;
26 |
27 | #pragma mark -
28 |
29 | - (void)setEncoder: (id) encoder;
30 |
31 | - (void)setMethod: (NSString *)method;
32 |
33 | - (void)setMethod: (NSString *)method withParameter: (id)parameter;
34 |
35 | - (void)setMethod: (NSString *)method withParameters: (NSArray *)parameters;
36 |
37 | - (void)setTimeoutInterval: (NSTimeInterval)timeout;
38 |
39 | #pragma mark -
40 |
41 | - (NSString *)method;
42 |
43 | - (NSArray *)parameters;
44 |
45 | - (NSTimeInterval)timeout;
46 |
47 | #pragma mark -
48 |
49 | - (NSString *)body;
50 |
51 | #pragma mark -
52 |
53 | - (NSURLRequest *)request;
54 |
55 | #pragma mark -
56 |
57 | - (void)setValue: (NSString *)value forHTTPHeaderField: (NSString *)header;
58 |
59 | #pragma mark -
60 |
61 | - (id) extra;
62 | - (void) setExtra:(id) extraObject;
63 |
64 | @end
65 |
--------------------------------------------------------------------------------
/Pods/xmlrpc/XMLRPCRequest.m:
--------------------------------------------------------------------------------
1 | #import "XMLRPCRequest.h"
2 | #import "XMLRPCEncoder.h"
3 | #import "XMLRPCDefaultEncoder.h"
4 |
5 | static const NSTimeInterval DEFAULT_TIMEOUT = 240;
6 |
7 | @implementation XMLRPCRequest
8 |
9 | - (id)initWithURL: (NSURL *)URL withEncoder: (id)encoder {
10 | self = [super init];
11 | if (self) {
12 | if (URL) {
13 | myRequest = [[NSMutableURLRequest alloc] initWithURL: URL];
14 | } else {
15 | myRequest = [[NSMutableURLRequest alloc] init];
16 | }
17 |
18 | myXMLEncoder = encoder;
19 | #if ! __has_feature(objc_arc)
20 | [myXMLEncoder retain];
21 | #endif
22 |
23 | myTimeout = DEFAULT_TIMEOUT;
24 | }
25 |
26 | return self;
27 | }
28 |
29 | - (id)initWithURL: (NSURL *)URL {
30 | #if ! __has_feature(objc_arc)
31 | return [self initWithURL:URL withEncoder:[[[XMLRPCDefaultEncoder alloc] init] autorelease]];
32 | #else
33 | return [self initWithURL:URL withEncoder:[[XMLRPCDefaultEncoder alloc] init]];
34 | #endif
35 | }
36 |
37 | #pragma mark -
38 |
39 | - (void)setURL: (NSURL *)URL {
40 | [myRequest setURL: URL];
41 | }
42 |
43 | - (NSURL *)URL {
44 | return [myRequest URL];
45 | }
46 |
47 | #pragma mark -
48 |
49 | - (void)setUserAgent: (NSString *)userAgent {
50 | if (![self userAgent]) {
51 | [myRequest addValue: userAgent forHTTPHeaderField: @"User-Agent"];
52 | } else {
53 | [myRequest setValue: userAgent forHTTPHeaderField: @"User-Agent"];
54 | }
55 | }
56 |
57 | - (NSString *)userAgent {
58 | return [myRequest valueForHTTPHeaderField: @"User-Agent"];
59 | }
60 |
61 | #pragma mark -
62 |
63 | - (void)setEncoder:(id)encoder {
64 | NSString *method = [myXMLEncoder method];
65 | NSArray *parameters = [myXMLEncoder parameters];
66 | #if ! __has_feature(objc_arc)
67 | [myXMLEncoder release];
68 |
69 | myXMLEncoder = [encoder retain];
70 | #else
71 | myXMLEncoder = encoder;
72 | #endif
73 |
74 | [myXMLEncoder setMethod: method withParameters: parameters];
75 | }
76 |
77 | - (void)setMethod: (NSString *)method {
78 | [myXMLEncoder setMethod: method withParameters: nil];
79 | }
80 |
81 | - (void)setMethod: (NSString *)method withParameter: (id)parameter {
82 | NSArray *parameters = nil;
83 |
84 | if (parameter) {
85 | parameters = [NSArray arrayWithObject: parameter];
86 | }
87 |
88 | [myXMLEncoder setMethod: method withParameters: parameters];
89 | }
90 |
91 | - (void)setMethod: (NSString *)method withParameters: (NSArray *)parameters {
92 | [myXMLEncoder setMethod: method withParameters: parameters];
93 | }
94 |
95 | - (void)setTimeoutInterval: (NSTimeInterval)timeout
96 | {
97 | myTimeout = timeout;
98 | }
99 |
100 | #pragma mark -
101 |
102 | - (NSString *)method {
103 | return [myXMLEncoder method];
104 | }
105 |
106 | - (NSArray *)parameters {
107 | return [myXMLEncoder parameters];
108 | }
109 |
110 | - (NSTimeInterval)timeout
111 | {
112 | return myTimeout;
113 | }
114 |
115 | #pragma mark -
116 |
117 | - (NSString *)body {
118 | return [myXMLEncoder encode];
119 | }
120 |
121 | #pragma mark -
122 |
123 | - (NSURLRequest *)request {
124 | NSData *content = [[self body] dataUsingEncoding: NSUTF8StringEncoding];
125 | NSNumber *contentLength = [NSNumber numberWithUnsignedInteger:[content length]];
126 |
127 | if (!myRequest) {
128 | return nil;
129 | }
130 |
131 | [myRequest setHTTPMethod: @"POST"];
132 |
133 | if (![myRequest valueForHTTPHeaderField: @"Content-Type"]) {
134 | [myRequest addValue: @"text/xml" forHTTPHeaderField: @"Content-Type"];
135 | } else {
136 | [myRequest setValue: @"text/xml" forHTTPHeaderField: @"Content-Type"];
137 | }
138 |
139 | if (![myRequest valueForHTTPHeaderField: @"Content-Length"]) {
140 | [myRequest addValue: [contentLength stringValue] forHTTPHeaderField: @"Content-Length"];
141 | } else {
142 | [myRequest setValue: [contentLength stringValue] forHTTPHeaderField: @"Content-Length"];
143 | }
144 |
145 | if (![myRequest valueForHTTPHeaderField: @"Accept"]) {
146 | [myRequest addValue: @"text/xml" forHTTPHeaderField: @"Accept"];
147 | } else {
148 | [myRequest setValue: @"text/xml" forHTTPHeaderField: @"Accept"];
149 | }
150 |
151 | if (![self userAgent]) {
152 | NSString *userAgent = [[NSUserDefaults standardUserDefaults] objectForKey:@"UserAgent"];
153 |
154 | if (userAgent) {
155 | [self setUserAgent: userAgent];
156 | }
157 | }
158 |
159 | [myRequest setHTTPBody: content];
160 |
161 | return (NSURLRequest *)myRequest;
162 | }
163 |
164 | #pragma mark -
165 |
166 | - (void)setValue: (NSString *)value forHTTPHeaderField: (NSString *)header {
167 | [myRequest setValue: value forHTTPHeaderField: header];
168 | }
169 | #pragma mark -
170 |
171 | - (id) extra {
172 | return extra;
173 | }
174 |
175 | - (void) setExtra:(id) extraObject {
176 | #if ! __has_feature(objc_arc)
177 | [extra release];
178 | extra = [extraObject retain];
179 | #else
180 | extra = extraObject;
181 | #endif
182 | }
183 |
184 | #pragma mark -
185 |
186 | - (void)dealloc {
187 | #if ! __has_feature(objc_arc)
188 | [myRequest release];
189 | [myXMLEncoder release];
190 |
191 | [super dealloc];
192 | #endif
193 | }
194 |
195 | @end
196 |
--------------------------------------------------------------------------------
/Pods/xmlrpc/XMLRPCResponse.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | @class XMLRPCDecoder;
4 |
5 | @interface XMLRPCResponse : NSObject {
6 | NSString *myBody;
7 | id myObject;
8 | BOOL isFault;
9 | }
10 |
11 | - (id)initWithData: (NSData *)data;
12 |
13 | #pragma mark -
14 |
15 | - (BOOL)isFault;
16 |
17 | - (NSNumber *)faultCode;
18 |
19 | - (NSString *)faultString;
20 |
21 | #pragma mark -
22 |
23 | - (id)object;
24 |
25 | #pragma mark -
26 |
27 | - (NSString *)body;
28 |
29 | #pragma mark -
30 |
31 | - (NSString *)description;
32 |
33 | @end
34 |
--------------------------------------------------------------------------------
/Pods/xmlrpc/XMLRPCResponse.m:
--------------------------------------------------------------------------------
1 | #import "XMLRPCResponse.h"
2 | #import "XMLRPCEventBasedParser.h"
3 |
4 | @implementation XMLRPCResponse
5 |
6 | - (id)initWithData: (NSData *)data {
7 | if (!data) {
8 | return nil;
9 | }
10 |
11 | self = [super init];
12 | if (self) {
13 | XMLRPCEventBasedParser *parser = [[XMLRPCEventBasedParser alloc] initWithData: data];
14 |
15 | if (!parser) {
16 | #if ! __has_feature(objc_arc)
17 | [self release];
18 | #endif
19 | return nil;
20 | }
21 |
22 | myBody = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
23 | myObject = [parser parse];
24 | #if ! __has_feature(objc_arc)
25 | [myObject retain];
26 | #endif
27 |
28 | isFault = [parser isFault];
29 |
30 | #if ! __has_feature(objc_arc)
31 | [parser release];
32 | #endif
33 | }
34 |
35 | return self;
36 | }
37 |
38 | #pragma mark -
39 |
40 | - (BOOL)isFault {
41 | return isFault;
42 | }
43 |
44 | - (NSNumber *)faultCode {
45 | if (isFault) {
46 | return [myObject objectForKey: @"faultCode"];
47 | }
48 |
49 | return nil;
50 | }
51 |
52 | - (NSString *)faultString {
53 | if (isFault) {
54 | return [myObject objectForKey: @"faultString"];
55 | }
56 |
57 | return nil;
58 | }
59 |
60 | #pragma mark -
61 |
62 | - (id)object {
63 | return myObject;
64 | }
65 |
66 | #pragma mark -
67 |
68 | - (NSString *)body {
69 | return myBody;
70 | }
71 |
72 | #pragma mark -
73 |
74 | - (NSString *)description {
75 | NSMutableString *result = [NSMutableString stringWithCapacity:128];
76 |
77 | [result appendFormat:@"[body=%@", myBody];
78 |
79 | if (isFault) {
80 | [result appendFormat:@", fault[%@]='%@'", [self faultCode], [self faultString]];
81 | } else {
82 | [result appendFormat:@", object=%@", myObject];
83 | }
84 |
85 | [result appendString:@"]"];
86 |
87 | return result;
88 | }
89 |
90 | #pragma mark -
91 |
92 | - (void)dealloc {
93 | #if ! __has_feature(objc_arc)
94 | [myBody release];
95 | [myObject release];
96 |
97 | [super dealloc];
98 | #endif
99 | }
100 |
101 | @end
102 |
--------------------------------------------------------------------------------
/PopoverController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PopoverController.swift
3 | // subs
4 | //
5 | // Created by Lucija Frković on 27/07/15.
6 | // Copyright © 2015 Lucija Frković. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 |
11 | class PopoverController: NSViewController {
12 |
13 | @IBOutlet weak var languageSelection: NSPopUpButton!
14 |
15 | override func viewDidLoad() {
16 | super.viewDidLoad()
17 | // Do view setup here.
18 | languageSelection.addItemsWithTitles((Language.getLanguages().allKeys as! [String]).sort())
19 |
20 | let userSubtitleLanguage = NSUserDefaults.standardUserDefaults().valueForKey(Constants.Keys.subtitleLanguage) as! String
21 |
22 | let subtitleDropdownTitle = Language.getLanguages().allKeysForObject(userSubtitleLanguage)[0] as! String
23 |
24 |
25 | languageSelection.selectItemWithTitle(subtitleDropdownTitle)
26 |
27 | }
28 |
29 | let languages = Language.getLanguages()
30 |
31 | @IBAction func changeLanguage(sender: NSPopUpButton) {
32 |
33 | let selectedItem = sender.titleOfSelectedItem!
34 |
35 | NSUserDefaults.standardUserDefaults().setValue(languages[selectedItem], forKey: Constants.Keys.subtitleLanguage)
36 |
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/PopoverController.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Subtitlr
2 |
3 | Subtitlr is an open source OS X app used to find and download subtitles easily. Video files are dropped into the app which then finds their hashcodes using OpenSubtitles.org algorithm and maches them against their database. Matched subtitles are downloaded in the same directory where the video files are located.
4 |
5 | ## Installation
6 |
7 |
8 | ### Prerequisites
9 | 1. XCode (can be downloaded from the app store)
10 | 2. [CocoaPods](https://cocoapods.org)
11 |
12 | ### Installation Instructions
13 | Clone the repository into a folder of your choice, and run `pod install` inside that folder. This will download the necessary dependencies and create a **Subtitlr.xcworkspace** file.
14 |
15 | Open the **Subtitlr.xcworkspace** file in XCode, go to "Product->Build" in the top bar, once this has built right-click on the "Products" folder in the left hand sidebar, and click "Open in Finder". **Subtitlr.app** will be in there, you can then drag this into your Applications folder.
16 |
17 | Alternatively, you can download Subtitlr.app in a ZIP file [here] (https://www.dropbox.com/s/et60e6lcvi3h2qc/Subtitlr.zip?dl=0).
18 |
--------------------------------------------------------------------------------
/Subtitle.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Subtitle.swift
3 | // subs
4 | //
5 | // Created by Lucija Frković on 18/09/15.
6 | // Copyright (c) 2015 Lucija Frković. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 |
12 | class Subtitle: NSObject {
13 | var path: String
14 | var ext: String
15 | var videoPath: String
16 |
17 | init(path: String, ext: String){
18 | self.videoPath = path
19 | self.path = (path as NSString).stringByDeletingPathExtension + "." + ext
20 | self.ext = ext
21 | }
22 | }
23 |
24 | extension Subtitle: NSFilePresenter {
25 |
26 | /*
27 | Output subtitle file
28 | */
29 | var presentedItemURL: NSURL? {
30 | let filePath = (path as NSString).stringByDeletingPathExtension + "." + ext
31 | return NSURL(fileURLWithPath: filePath)
32 | }
33 |
34 | /*
35 | "Source" file - video file which will get "modified and saved" as subtitle file
36 | */
37 | var primaryPresentedItemURL: NSURL? {
38 | return NSURL(fileURLWithPath: videoPath)
39 | }
40 |
41 | var presentedItemOperationQueue: NSOperationQueue {
42 | return NSOperationQueue.mainQueue()
43 | }
44 | }
--------------------------------------------------------------------------------
/Subtitlr 2.0/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // subs
4 | //
5 | // Created by Lucija Frković on 21/07/15.
6 | // Copyright © 2015 Lucija Frković. All rights reserved.
7 | //
8 |
9 | import Cocoa
10 |
11 | @NSApplicationMain
12 | class AppDelegate: NSObject, NSApplicationDelegate {
13 |
14 | var mainWindowController: MainWindowController?
15 | var popoverController: PopoverController?
16 |
17 | func applicationDidFinishLaunching(aNotification: NSNotification) {
18 |
19 | let mainWindowController = MainWindowController()
20 | let popoverController = PopoverController()
21 |
22 | //put the window of the window controller on screen
23 | mainWindowController.showWindow(self)
24 | self.mainWindowController = mainWindowController
25 | self.popoverController = popoverController
26 |
27 | //check if user has selected a language, if not, set to English
28 | if NSUserDefaults.standardUserDefaults().objectForKey(Constants.Keys.subtitleLanguage) == nil {
29 | NSUserDefaults.standardUserDefaults().setObject(Constants.defaultSubtitleLanguage, forKey: Constants.Keys.subtitleLanguage)
30 | }
31 | }
32 |
33 | func applicationShouldTerminateAfterLastWindowClosed(sender: NSApplication) -> Bool {
34 | return true
35 | }
36 |
37 | func applicationWillTerminate(notification: NSNotification) {
38 |
39 | //save user settings before quitting
40 | NSUserDefaults.standardUserDefaults().synchronize()
41 | }
42 |
43 | }
44 |
45 |
--------------------------------------------------------------------------------
/Subtitlr 2.0/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "16x16",
5 | "idiom" : "mac",
6 | "filename" : "logo_16.png",
7 | "scale" : "1x"
8 | },
9 | {
10 | "size" : "16x16",
11 | "idiom" : "mac",
12 | "filename" : "logo_32.png",
13 | "scale" : "2x"
14 | },
15 | {
16 | "size" : "32x32",
17 | "idiom" : "mac",
18 | "filename" : "logo_32-1.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "32x32",
23 | "idiom" : "mac",
24 | "filename" : "logo_64.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "128x128",
29 | "idiom" : "mac",
30 | "filename" : "logo_128.png",
31 | "scale" : "1x"
32 | },
33 | {
34 | "size" : "128x128",
35 | "idiom" : "mac",
36 | "filename" : "logo_256-1.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "256x256",
41 | "idiom" : "mac",
42 | "filename" : "logo_256.png",
43 | "scale" : "1x"
44 | },
45 | {
46 | "size" : "256x256",
47 | "idiom" : "mac",
48 | "filename" : "logo_512-1.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "512x512",
53 | "idiom" : "mac",
54 | "filename" : "logo_512.png",
55 | "scale" : "1x"
56 | },
57 | {
58 | "size" : "512x512",
59 | "idiom" : "mac",
60 | "filename" : "logo.png",
61 | "scale" : "2x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
--------------------------------------------------------------------------------
/Subtitlr 2.0/Assets.xcassets/AppIcon.appiconset/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lucijafrkovic/Subtitlr/0c0327bcdad6a317734952a0d410c43c045a69db/Subtitlr 2.0/Assets.xcassets/AppIcon.appiconset/logo.png
--------------------------------------------------------------------------------
/Subtitlr 2.0/Assets.xcassets/AppIcon.appiconset/logo_128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lucijafrkovic/Subtitlr/0c0327bcdad6a317734952a0d410c43c045a69db/Subtitlr 2.0/Assets.xcassets/AppIcon.appiconset/logo_128.png
--------------------------------------------------------------------------------
/Subtitlr 2.0/Assets.xcassets/AppIcon.appiconset/logo_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lucijafrkovic/Subtitlr/0c0327bcdad6a317734952a0d410c43c045a69db/Subtitlr 2.0/Assets.xcassets/AppIcon.appiconset/logo_16.png
--------------------------------------------------------------------------------
/Subtitlr 2.0/Assets.xcassets/AppIcon.appiconset/logo_256-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lucijafrkovic/Subtitlr/0c0327bcdad6a317734952a0d410c43c045a69db/Subtitlr 2.0/Assets.xcassets/AppIcon.appiconset/logo_256-1.png
--------------------------------------------------------------------------------
/Subtitlr 2.0/Assets.xcassets/AppIcon.appiconset/logo_256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lucijafrkovic/Subtitlr/0c0327bcdad6a317734952a0d410c43c045a69db/Subtitlr 2.0/Assets.xcassets/AppIcon.appiconset/logo_256.png
--------------------------------------------------------------------------------
/Subtitlr 2.0/Assets.xcassets/AppIcon.appiconset/logo_32-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lucijafrkovic/Subtitlr/0c0327bcdad6a317734952a0d410c43c045a69db/Subtitlr 2.0/Assets.xcassets/AppIcon.appiconset/logo_32-1.png
--------------------------------------------------------------------------------
/Subtitlr 2.0/Assets.xcassets/AppIcon.appiconset/logo_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lucijafrkovic/Subtitlr/0c0327bcdad6a317734952a0d410c43c045a69db/Subtitlr 2.0/Assets.xcassets/AppIcon.appiconset/logo_32.png
--------------------------------------------------------------------------------
/Subtitlr 2.0/Assets.xcassets/AppIcon.appiconset/logo_512-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lucijafrkovic/Subtitlr/0c0327bcdad6a317734952a0d410c43c045a69db/Subtitlr 2.0/Assets.xcassets/AppIcon.appiconset/logo_512-1.png
--------------------------------------------------------------------------------
/Subtitlr 2.0/Assets.xcassets/AppIcon.appiconset/logo_512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lucijafrkovic/Subtitlr/0c0327bcdad6a317734952a0d410c43c045a69db/Subtitlr 2.0/Assets.xcassets/AppIcon.appiconset/logo_512.png
--------------------------------------------------------------------------------
/Subtitlr 2.0/Assets.xcassets/AppIcon.appiconset/logo_64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lucijafrkovic/Subtitlr/0c0327bcdad6a317734952a0d410c43c045a69db/Subtitlr 2.0/Assets.xcassets/AppIcon.appiconset/logo_64.png
--------------------------------------------------------------------------------
/Subtitlr 2.0/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDocumentTypes
8 |
9 |
10 | CFBundleTypeExtensions
11 |
12 | 3g2
13 | 3gp
14 | 3gp2
15 | 3gpp
16 | 60d
17 | ajp
18 | asf
19 | asx
20 | avchd
21 | avi
22 | bik
23 | bix
24 | box
25 | cam
26 | dat
27 | divx
28 | dmf
29 | dv
30 | dvr-ms
31 | evo
32 | flc
33 | fli
34 | flic
35 | flv
36 | flx
37 | gvi
38 | gvp
39 | h264
40 | m1v
41 | m2p
42 | m2ts
43 | m2v
44 | m4e
45 | m4v
46 | mjp
47 | mjpeg
48 | mjpg
49 | mkv
50 | moov
51 | mov
52 | movhd
53 | movie
54 | movx
55 | mp4
56 | mpe
57 | mpeg
58 | mpg
59 | mpv
60 | mpv2
61 | mxf
62 | nsv
63 | nut
64 | ogg
65 | ogm
66 | omf
67 | ps
68 | qt
69 | ram
70 | rm
71 | rmvb
72 | swf
73 | ts
74 | vfw
75 | vid
76 | video
77 | viv
78 | vivo
79 | vob
80 | vro
81 | wm
82 | wmv
83 | wmx
84 | wrap
85 | wvx
86 | wx
87 | x264
88 | xvid
89 |
90 | CFBundleTypeName
91 | Video file
92 | CFBundleTypeRole
93 | Viewer
94 |
95 |
96 | CFBundleTypeExtensions
97 |
98 | sub
99 | srt
100 | txt
101 | smi
102 | ssa
103 | ass
104 | mpl
105 |
106 | CFBundleTypeName
107 | Subtitle File
108 | CFBundleTypeRole
109 | Editor
110 | NSIsRelatedItemType
111 |
112 |
113 |
114 | CFBundleExecutable
115 | $(EXECUTABLE_NAME)
116 | CFBundleIconFile
117 |
118 | CFBundleIdentifier
119 | $(PRODUCT_BUNDLE_IDENTIFIER)
120 | CFBundleInfoDictionaryVersion
121 | 6.0
122 | CFBundleName
123 | $(PRODUCT_NAME)
124 | CFBundlePackageType
125 | APPL
126 | CFBundleShortVersionString
127 | 1.0
128 | CFBundleSignature
129 | ????
130 | CFBundleVersion
131 | 9
132 | LSApplicationCategoryType
133 | public.app-category.video
134 | LSMinimumSystemVersion
135 | $(MACOSX_DEPLOYMENT_TARGET)
136 | NSHumanReadableCopyright
137 | Copyright © 2015 Lucija Frković. All rights reserved.
138 | NSMainNibFile
139 | MainMenu
140 | NSPrincipalClass
141 | NSApplication
142 |
143 |
144 |
--------------------------------------------------------------------------------
/Subtitlr 2.0/MainMenu.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/Subtitlr 2.0Tests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Subtitlr 2.0Tests/OpenSubsAccessTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OpenSubsAccessTests.swift
3 | // Subtitlr
4 | //
5 | // Created by Lucija Frković on 27/09/15.
6 | // Copyright © 2015 Lucija Frković. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import Subtitlr
11 |
12 | class OpenSubsAccessTests: XCTestCase {
13 |
14 | var subsAccess = OpenSubsAccess()
15 |
16 | override func setUp() {
17 | super.setUp()
18 | subsAccess.logIn()
19 | }
20 |
21 | override func tearDown() {
22 | // Put teardown code here. This method is called after the invocation of each test method in the class.
23 | super.tearDown()
24 | }
25 |
26 | func testLogIn(){
27 | subsAccess.logIn()
28 | XCTAssertNotNil(subsAccess.token)
29 |
30 | }
31 |
32 | func testTalkToOpenSubs(){
33 | /* test log in */
34 | let result = subsAccess.talkToOpenSubs("LogIn", params: ["", "", "eng", Constants.OSUserAgent])
35 | XCTAssertNotNil(result!.valueForKey("token"))
36 |
37 | let serverInfo = subsAccess.talkToOpenSubs("ServerInfo", params: [])
38 | print(serverInfo)
39 | }
40 |
41 | func testSearchSubs(){
42 | let file = Video(path: "/Users/spilja/Downloads/breakdance.avi")
43 | let result = subsAccess.getSubtitle(file.hash, size: Double(file.size))
44 | XCTAssertEqual(1951887680, result!.id)
45 | XCTAssertEqual("srt", result!.format)
46 | }
47 |
48 | //TODO: add entitlements to tests??
49 | // func testGetSubFile(){
50 | // var file = Video(path: "/Users/spilja/Downloads/breakdance.avi", subFound: false)
51 | // subsAccess.downloadSub(1951887680, format: "srt", file: &file)
52 | // }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/Subtitlr 2.0Tests/SubtitlrTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Subtitlr_2_0Tests.swift
3 | // Subtitlr 2.0Tests
4 | //
5 | // Created by Lucija Frković on 11/10/15.
6 | // Copyright © 2015 Lucija Frković. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import Subtitlr
11 |
12 | class SubtitlrTests: XCTestCase {
13 |
14 | override func setUp() {
15 | super.setUp()
16 | // Put setup code here. This method is called before the invocation of each test method in the class.
17 | }
18 |
19 | override func tearDown() {
20 | // Put teardown code here. This method is called after the invocation of each test method in the class.
21 | super.tearDown()
22 | }
23 |
24 | func testHashMethod(){
25 | let file = Video(path: "/Users/spilja/Downloads/breakdance.avi")
26 | XCTAssertEqual(file.hash, "8e245d9679d31e12")
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/Subtitlr 2.0UITests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Subtitlr 2.0UITests/UITests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Subtitlr_2_0UITests.swift
3 | // Subtitlr 2.0UITests
4 | //
5 | // Created by Lucija Frković on 11/10/15.
6 | // Copyright © 2015 Lucija Frković. All rights reserved.
7 | //
8 |
9 | import XCTest
10 |
11 | class Subtitlr_2_0UITests: XCTestCase {
12 |
13 | override func setUp() {
14 | super.setUp()
15 |
16 | // Put setup code here. This method is called before the invocation of each test method in the class.
17 |
18 | // In UI tests it is usually best to stop immediately when a failure occurs.
19 | continueAfterFailure = false
20 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
21 | XCUIApplication().launch()
22 |
23 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
24 | }
25 |
26 | override func tearDown() {
27 | // Put teardown code here. This method is called after the invocation of each test method in the class.
28 | super.tearDown()
29 | }
30 |
31 | func testExample() {
32 | // Use recording to get started writing UI tests.
33 | // Use XCTAssert and related functions to verify your tests produce the correct results.
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/Subtitlr.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 | com.apple.security.files.user-selected.read-write
8 |
9 | com.apple.security.network.client
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/Subtitlr.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 7B003A1099DF698D527C753E /* libPods-Subtitlr.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 69EFDB4D604EAFD284C0AEC5 /* libPods-Subtitlr.a */; };
11 | C60B0A491BCD41EB00DD4286 /* PopoverController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C60B0A481BCD41EA00DD4286 /* PopoverController.swift */; settings = {ASSET_TAGS = (); }; };
12 | C60B0A4B1BCD41FD00DD4286 /* PopoverController.xib in Resources */ = {isa = PBXBuildFile; fileRef = C60B0A4A1BCD41FD00DD4286 /* PopoverController.xib */; settings = {ASSET_TAGS = (); }; };
13 | C60B0A4E1BCE35FB00DD4286 /* dropzone_img.png in Resources */ = {isa = PBXBuildFile; fileRef = C60B0A4C1BCE35FB00DD4286 /* dropzone_img.png */; settings = {ASSET_TAGS = (); }; };
14 | C60B0A4F1BCE35FB00DD4286 /* dropzone_img@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = C60B0A4D1BCE35FB00DD4286 /* dropzone_img@2x.png */; settings = {ASSET_TAGS = (); }; };
15 | C67C2ECD1BCA8AE100AD6F36 /* SubtitlrTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C67C2ECC1BCA8AE100AD6F36 /* SubtitlrTests.swift */; };
16 | C67C2ED81BCA8AE100AD6F36 /* UITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C67C2ED71BCA8AE100AD6F36 /* UITests.swift */; };
17 | C6CF29651BCA8D5800BB9B89 /* OpenSubsAccess.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6CF29641BCA8D5800BB9B89 /* OpenSubsAccess.swift */; settings = {ASSET_TAGS = (); }; };
18 | C6CF29761BCA8E1700BB9B89 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C6CF29751BCA8E1700BB9B89 /* Assets.xcassets */; settings = {ASSET_TAGS = (); }; };
19 | C6CF298D1BCA8EAD00BB9B89 /* Languages.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6CF29871BCA8EAD00BB9B89 /* Languages.swift */; settings = {ASSET_TAGS = (); }; };
20 | C6CF298E1BCA8EAD00BB9B89 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6CF29881BCA8EAD00BB9B89 /* Constants.swift */; settings = {ASSET_TAGS = (); }; };
21 | C6CF298F1BCA8EAD00BB9B89 /* Subtitlr.entitlements in Resources */ = {isa = PBXBuildFile; fileRef = C6CF29891BCA8EAD00BB9B89 /* Subtitlr.entitlements */; settings = {ASSET_TAGS = (); }; };
22 | C6CF29901BCA8EAD00BB9B89 /* opensubs-logo.png in Resources */ = {isa = PBXBuildFile; fileRef = C6CF298A1BCA8EAD00BB9B89 /* opensubs-logo.png */; settings = {ASSET_TAGS = (); }; };
23 | C6CF29911BCA8EAD00BB9B89 /* Credits.html in Resources */ = {isa = PBXBuildFile; fileRef = C6CF298B1BCA8EAD00BB9B89 /* Credits.html */; settings = {ASSET_TAGS = (); }; };
24 | C6CF29921BCA8EAD00BB9B89 /* opensubs-logo.gif in Resources */ = {isa = PBXBuildFile; fileRef = C6CF298C1BCA8EAD00BB9B89 /* opensubs-logo.gif */; settings = {ASSET_TAGS = (); }; };
25 | C6CF29941BCA8F9000BB9B89 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6CF29931BCA8F9000BB9B89 /* AppDelegate.swift */; settings = {ASSET_TAGS = (); }; };
26 | C6E0FC641BCA954700EC5F81 /* FileHashMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6E0FC611BCA954700EC5F81 /* FileHashMethod.swift */; settings = {ASSET_TAGS = (); }; };
27 | C6E0FC651BCA954700EC5F81 /* Subtitle.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6E0FC621BCA954700EC5F81 /* Subtitle.swift */; settings = {ASSET_TAGS = (); }; };
28 | C6E0FC661BCA954700EC5F81 /* Video.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6E0FC631BCA954700EC5F81 /* Video.swift */; settings = {ASSET_TAGS = (); }; };
29 | C6E0FC691BCAA52B00EC5F81 /* OpenSubsAccessTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6E0FC671BCAA4E200EC5F81 /* OpenSubsAccessTests.swift */; settings = {ASSET_TAGS = (); }; };
30 | C6E0FC6B1BCAD5A600EC5F81 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = C6E0FC6A1BCAD5A600EC5F81 /* MainMenu.xib */; settings = {ASSET_TAGS = (); }; };
31 | C6E0FC721BCAD7DC00EC5F81 /* MainWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6E0FC701BCAD7DC00EC5F81 /* MainWindowController.swift */; settings = {ASSET_TAGS = (); }; };
32 | C6E0FC731BCAD7DC00EC5F81 /* MainWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = C6E0FC711BCAD7DC00EC5F81 /* MainWindowController.xib */; settings = {ASSET_TAGS = (); }; };
33 | /* End PBXBuildFile section */
34 |
35 | /* Begin PBXContainerItemProxy section */
36 | C67C2EC91BCA8AE100AD6F36 /* PBXContainerItemProxy */ = {
37 | isa = PBXContainerItemProxy;
38 | containerPortal = C67C2EAF1BCA8AE100AD6F36 /* Project object */;
39 | proxyType = 1;
40 | remoteGlobalIDString = C67C2EB61BCA8AE100AD6F36;
41 | remoteInfo = "Subtitlr 2.0";
42 | };
43 | C67C2ED41BCA8AE100AD6F36 /* PBXContainerItemProxy */ = {
44 | isa = PBXContainerItemProxy;
45 | containerPortal = C67C2EAF1BCA8AE100AD6F36 /* Project object */;
46 | proxyType = 1;
47 | remoteGlobalIDString = C67C2EB61BCA8AE100AD6F36;
48 | remoteInfo = "Subtitlr 2.0";
49 | };
50 | /* End PBXContainerItemProxy section */
51 |
52 | /* Begin PBXFileReference section */
53 | 69EFDB4D604EAFD284C0AEC5 /* libPods-Subtitlr.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Subtitlr.a"; sourceTree = BUILT_PRODUCTS_DIR; };
54 | 939DFACE05D5CB3208F84560 /* Pods-Subtitlr.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Subtitlr.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Subtitlr/Pods-Subtitlr.debug.xcconfig"; sourceTree = ""; };
55 | C60B0A481BCD41EA00DD4286 /* PopoverController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PopoverController.swift; sourceTree = ""; };
56 | C60B0A4A1BCD41FD00DD4286 /* PopoverController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PopoverController.xib; sourceTree = ""; };
57 | C60B0A4C1BCE35FB00DD4286 /* dropzone_img.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = dropzone_img.png; sourceTree = ""; };
58 | C60B0A4D1BCE35FB00DD4286 /* dropzone_img@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "dropzone_img@2x.png"; sourceTree = ""; };
59 | C622A25797A6FF275036C660 /* Pods-Subtitlr.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Subtitlr.release.xcconfig"; path = "Pods/Target Support Files/Pods-Subtitlr/Pods-Subtitlr.release.xcconfig"; sourceTree = ""; };
60 | C67C2EB71BCA8AE100AD6F36 /* Subtitlr.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Subtitlr.app; sourceTree = BUILT_PRODUCTS_DIR; };
61 | C67C2EC31BCA8AE100AD6F36 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
62 | C67C2EC81BCA8AE100AD6F36 /* Subtitlr.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Subtitlr.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
63 | C67C2ECC1BCA8AE100AD6F36 /* SubtitlrTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubtitlrTests.swift; sourceTree = ""; };
64 | C67C2ECE1BCA8AE100AD6F36 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
65 | C67C2ED31BCA8AE100AD6F36 /* Subtitlr.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Subtitlr.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
66 | C67C2ED71BCA8AE100AD6F36 /* UITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITests.swift; sourceTree = ""; };
67 | C67C2ED91BCA8AE100AD6F36 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
68 | C6CF29641BCA8D5800BB9B89 /* OpenSubsAccess.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpenSubsAccess.swift; sourceTree = ""; };
69 | C6CF29751BCA8E1700BB9B89 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
70 | C6CF29861BCA8EAD00BB9B89 /* Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Bridging-Header.h"; sourceTree = ""; };
71 | C6CF29871BCA8EAD00BB9B89 /* Languages.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Languages.swift; sourceTree = ""; };
72 | C6CF29881BCA8EAD00BB9B89 /* Constants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; };
73 | C6CF29891BCA8EAD00BB9B89 /* Subtitlr.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = Subtitlr.entitlements; sourceTree = ""; };
74 | C6CF298A1BCA8EAD00BB9B89 /* opensubs-logo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "opensubs-logo.png"; sourceTree = ""; };
75 | C6CF298B1BCA8EAD00BB9B89 /* Credits.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = Credits.html; sourceTree = ""; };
76 | C6CF298C1BCA8EAD00BB9B89 /* opensubs-logo.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = "opensubs-logo.gif"; sourceTree = ""; };
77 | C6CF29931BCA8F9000BB9B89 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
78 | C6E0FC611BCA954700EC5F81 /* FileHashMethod.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileHashMethod.swift; sourceTree = ""; };
79 | C6E0FC621BCA954700EC5F81 /* Subtitle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Subtitle.swift; sourceTree = ""; };
80 | C6E0FC631BCA954700EC5F81 /* Video.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Video.swift; sourceTree = ""; };
81 | C6E0FC671BCAA4E200EC5F81 /* OpenSubsAccessTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpenSubsAccessTests.swift; sourceTree = ""; };
82 | C6E0FC6A1BCAD5A600EC5F81 /* MainMenu.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainMenu.xib; sourceTree = ""; };
83 | C6E0FC701BCAD7DC00EC5F81 /* MainWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainWindowController.swift; sourceTree = ""; };
84 | C6E0FC711BCAD7DC00EC5F81 /* MainWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainWindowController.xib; sourceTree = ""; };
85 | /* End PBXFileReference section */
86 |
87 | /* Begin PBXFrameworksBuildPhase section */
88 | C67C2EB41BCA8AE100AD6F36 /* Frameworks */ = {
89 | isa = PBXFrameworksBuildPhase;
90 | buildActionMask = 2147483647;
91 | files = (
92 | 7B003A1099DF698D527C753E /* libPods-Subtitlr.a in Frameworks */,
93 | );
94 | runOnlyForDeploymentPostprocessing = 0;
95 | };
96 | C67C2EC51BCA8AE100AD6F36 /* Frameworks */ = {
97 | isa = PBXFrameworksBuildPhase;
98 | buildActionMask = 2147483647;
99 | files = (
100 | );
101 | runOnlyForDeploymentPostprocessing = 0;
102 | };
103 | C67C2ED01BCA8AE100AD6F36 /* Frameworks */ = {
104 | isa = PBXFrameworksBuildPhase;
105 | buildActionMask = 2147483647;
106 | files = (
107 | );
108 | runOnlyForDeploymentPostprocessing = 0;
109 | };
110 | /* End PBXFrameworksBuildPhase section */
111 |
112 | /* Begin PBXGroup section */
113 | 5F0C39BF85412E4C5310E406 /* Frameworks */ = {
114 | isa = PBXGroup;
115 | children = (
116 | 69EFDB4D604EAFD284C0AEC5 /* libPods-Subtitlr.a */,
117 | );
118 | name = Frameworks;
119 | sourceTree = "";
120 | };
121 | C67C2EAE1BCA8AE100AD6F36 = {
122 | isa = PBXGroup;
123 | children = (
124 | C6E0FC6F1BCAD77000EC5F81 /* Views */,
125 | C6E0FC6C1BCAD69100EC5F81 /* Controllers */,
126 | C6E0FC601BCA953E00EC5F81 /* Model */,
127 | C6CF29851BCA8E9F00BB9B89 /* Supporting Files */,
128 | C6CF29661BCA8D5E00BB9B89 /* API communication */,
129 | C6CF295F1BCA8D0C00BB9B89 /* UI files */,
130 | C67C2EB91BCA8AE100AD6F36 /* Subtitlr 2.0 */,
131 | C67C2ECB1BCA8AE100AD6F36 /* Tests */,
132 | C67C2ED61BCA8AE100AD6F36 /* UITests */,
133 | C67C2EB81BCA8AE100AD6F36 /* Products */,
134 | E4827C282BBCFD4CF3615B0B /* Pods */,
135 | 5F0C39BF85412E4C5310E406 /* Frameworks */,
136 | );
137 | sourceTree = "";
138 | };
139 | C67C2EB81BCA8AE100AD6F36 /* Products */ = {
140 | isa = PBXGroup;
141 | children = (
142 | C67C2EB71BCA8AE100AD6F36 /* Subtitlr.app */,
143 | C67C2EC81BCA8AE100AD6F36 /* Subtitlr.xctest */,
144 | C67C2ED31BCA8AE100AD6F36 /* Subtitlr.xctest */,
145 | );
146 | name = Products;
147 | sourceTree = "";
148 | };
149 | C67C2EB91BCA8AE100AD6F36 /* Subtitlr 2.0 */ = {
150 | isa = PBXGroup;
151 | children = (
152 | C6E0FC6A1BCAD5A600EC5F81 /* MainMenu.xib */,
153 | C6CF29931BCA8F9000BB9B89 /* AppDelegate.swift */,
154 | C6CF29751BCA8E1700BB9B89 /* Assets.xcassets */,
155 | C67C2EC31BCA8AE100AD6F36 /* Info.plist */,
156 | );
157 | path = "Subtitlr 2.0";
158 | sourceTree = "";
159 | };
160 | C67C2ECB1BCA8AE100AD6F36 /* Tests */ = {
161 | isa = PBXGroup;
162 | children = (
163 | C6E0FC671BCAA4E200EC5F81 /* OpenSubsAccessTests.swift */,
164 | C67C2ECC1BCA8AE100AD6F36 /* SubtitlrTests.swift */,
165 | C67C2ECE1BCA8AE100AD6F36 /* Info.plist */,
166 | );
167 | name = Tests;
168 | path = "Subtitlr 2.0Tests";
169 | sourceTree = "";
170 | };
171 | C67C2ED61BCA8AE100AD6F36 /* UITests */ = {
172 | isa = PBXGroup;
173 | children = (
174 | C67C2ED71BCA8AE100AD6F36 /* UITests.swift */,
175 | C67C2ED91BCA8AE100AD6F36 /* Info.plist */,
176 | );
177 | name = UITests;
178 | path = "Subtitlr 2.0UITests";
179 | sourceTree = "";
180 | };
181 | C6CF295F1BCA8D0C00BB9B89 /* UI files */ = {
182 | isa = PBXGroup;
183 | children = (
184 | C60B0A4C1BCE35FB00DD4286 /* dropzone_img.png */,
185 | C60B0A4D1BCE35FB00DD4286 /* dropzone_img@2x.png */,
186 | );
187 | name = "UI files";
188 | sourceTree = "";
189 | };
190 | C6CF29661BCA8D5E00BB9B89 /* API communication */ = {
191 | isa = PBXGroup;
192 | children = (
193 | C6CF29641BCA8D5800BB9B89 /* OpenSubsAccess.swift */,
194 | );
195 | name = "API communication";
196 | sourceTree = "";
197 | };
198 | C6CF29851BCA8E9F00BB9B89 /* Supporting Files */ = {
199 | isa = PBXGroup;
200 | children = (
201 | C6CF29861BCA8EAD00BB9B89 /* Bridging-Header.h */,
202 | C6CF29871BCA8EAD00BB9B89 /* Languages.swift */,
203 | C6CF29881BCA8EAD00BB9B89 /* Constants.swift */,
204 | C6CF29891BCA8EAD00BB9B89 /* Subtitlr.entitlements */,
205 | C6CF298A1BCA8EAD00BB9B89 /* opensubs-logo.png */,
206 | C6CF298B1BCA8EAD00BB9B89 /* Credits.html */,
207 | C6CF298C1BCA8EAD00BB9B89 /* opensubs-logo.gif */,
208 | );
209 | name = "Supporting Files";
210 | sourceTree = "";
211 | };
212 | C6E0FC601BCA953E00EC5F81 /* Model */ = {
213 | isa = PBXGroup;
214 | children = (
215 | C6E0FC611BCA954700EC5F81 /* FileHashMethod.swift */,
216 | C6E0FC621BCA954700EC5F81 /* Subtitle.swift */,
217 | C6E0FC631BCA954700EC5F81 /* Video.swift */,
218 | );
219 | name = Model;
220 | sourceTree = "";
221 | };
222 | C6E0FC6C1BCAD69100EC5F81 /* Controllers */ = {
223 | isa = PBXGroup;
224 | children = (
225 | C60B0A481BCD41EA00DD4286 /* PopoverController.swift */,
226 | C6E0FC701BCAD7DC00EC5F81 /* MainWindowController.swift */,
227 | );
228 | name = Controllers;
229 | sourceTree = "";
230 | };
231 | C6E0FC6F1BCAD77000EC5F81 /* Views */ = {
232 | isa = PBXGroup;
233 | children = (
234 | C60B0A4A1BCD41FD00DD4286 /* PopoverController.xib */,
235 | C6E0FC711BCAD7DC00EC5F81 /* MainWindowController.xib */,
236 | );
237 | name = Views;
238 | sourceTree = "";
239 | };
240 | E4827C282BBCFD4CF3615B0B /* Pods */ = {
241 | isa = PBXGroup;
242 | children = (
243 | 939DFACE05D5CB3208F84560 /* Pods-Subtitlr.debug.xcconfig */,
244 | C622A25797A6FF275036C660 /* Pods-Subtitlr.release.xcconfig */,
245 | );
246 | name = Pods;
247 | sourceTree = "";
248 | };
249 | /* End PBXGroup section */
250 |
251 | /* Begin PBXNativeTarget section */
252 | C67C2EB61BCA8AE100AD6F36 /* Subtitlr */ = {
253 | isa = PBXNativeTarget;
254 | buildConfigurationList = C67C2EDC1BCA8AE100AD6F36 /* Build configuration list for PBXNativeTarget "Subtitlr" */;
255 | buildPhases = (
256 | DB497872C2E728CC77E482CC /* Check Pods Manifest.lock */,
257 | C67C2EB31BCA8AE100AD6F36 /* Sources */,
258 | C67C2EB41BCA8AE100AD6F36 /* Frameworks */,
259 | C67C2EB51BCA8AE100AD6F36 /* Resources */,
260 | 6B36B21AA6C21B3843E04796 /* Copy Pods Resources */,
261 | );
262 | buildRules = (
263 | );
264 | dependencies = (
265 | );
266 | name = Subtitlr;
267 | productName = "Subtitlr 2.0";
268 | productReference = C67C2EB71BCA8AE100AD6F36 /* Subtitlr.app */;
269 | productType = "com.apple.product-type.application";
270 | };
271 | C67C2EC71BCA8AE100AD6F36 /* SubtitlrTests */ = {
272 | isa = PBXNativeTarget;
273 | buildConfigurationList = C67C2EDF1BCA8AE100AD6F36 /* Build configuration list for PBXNativeTarget "SubtitlrTests" */;
274 | buildPhases = (
275 | C67C2EC41BCA8AE100AD6F36 /* Sources */,
276 | C67C2EC51BCA8AE100AD6F36 /* Frameworks */,
277 | C67C2EC61BCA8AE100AD6F36 /* Resources */,
278 | );
279 | buildRules = (
280 | );
281 | dependencies = (
282 | C67C2ECA1BCA8AE100AD6F36 /* PBXTargetDependency */,
283 | );
284 | name = SubtitlrTests;
285 | productName = "Subtitlr 2.0Tests";
286 | productReference = C67C2EC81BCA8AE100AD6F36 /* Subtitlr.xctest */;
287 | productType = "com.apple.product-type.bundle.unit-test";
288 | };
289 | C67C2ED21BCA8AE100AD6F36 /* SubtitlrUITests */ = {
290 | isa = PBXNativeTarget;
291 | buildConfigurationList = C67C2EE21BCA8AE100AD6F36 /* Build configuration list for PBXNativeTarget "SubtitlrUITests" */;
292 | buildPhases = (
293 | C67C2ECF1BCA8AE100AD6F36 /* Sources */,
294 | C67C2ED01BCA8AE100AD6F36 /* Frameworks */,
295 | C67C2ED11BCA8AE100AD6F36 /* Resources */,
296 | );
297 | buildRules = (
298 | );
299 | dependencies = (
300 | C67C2ED51BCA8AE100AD6F36 /* PBXTargetDependency */,
301 | );
302 | name = SubtitlrUITests;
303 | productName = "Subtitlr 2.0UITests";
304 | productReference = C67C2ED31BCA8AE100AD6F36 /* Subtitlr.xctest */;
305 | productType = "com.apple.product-type.bundle.ui-testing";
306 | };
307 | /* End PBXNativeTarget section */
308 |
309 | /* Begin PBXProject section */
310 | C67C2EAF1BCA8AE100AD6F36 /* Project object */ = {
311 | isa = PBXProject;
312 | attributes = {
313 | LastUpgradeCheck = 0700;
314 | ORGANIZATIONNAME = "Lucija Frković";
315 | TargetAttributes = {
316 | C67C2EB61BCA8AE100AD6F36 = {
317 | CreatedOnToolsVersion = 7.0.1;
318 | DevelopmentTeam = X4N5X87CSP;
319 | };
320 | C67C2EC71BCA8AE100AD6F36 = {
321 | CreatedOnToolsVersion = 7.0.1;
322 | TestTargetID = C67C2EB61BCA8AE100AD6F36;
323 | };
324 | C67C2ED21BCA8AE100AD6F36 = {
325 | CreatedOnToolsVersion = 7.0.1;
326 | TestTargetID = C67C2EB61BCA8AE100AD6F36;
327 | };
328 | };
329 | };
330 | buildConfigurationList = C67C2EB21BCA8AE100AD6F36 /* Build configuration list for PBXProject "Subtitlr" */;
331 | compatibilityVersion = "Xcode 3.2";
332 | developmentRegion = English;
333 | hasScannedForEncodings = 0;
334 | knownRegions = (
335 | en,
336 | Base,
337 | );
338 | mainGroup = C67C2EAE1BCA8AE100AD6F36;
339 | productRefGroup = C67C2EB81BCA8AE100AD6F36 /* Products */;
340 | projectDirPath = "";
341 | projectRoot = "";
342 | targets = (
343 | C67C2EB61BCA8AE100AD6F36 /* Subtitlr */,
344 | C67C2EC71BCA8AE100AD6F36 /* SubtitlrTests */,
345 | C67C2ED21BCA8AE100AD6F36 /* SubtitlrUITests */,
346 | );
347 | };
348 | /* End PBXProject section */
349 |
350 | /* Begin PBXResourcesBuildPhase section */
351 | C67C2EB51BCA8AE100AD6F36 /* Resources */ = {
352 | isa = PBXResourcesBuildPhase;
353 | buildActionMask = 2147483647;
354 | files = (
355 | C6CF298F1BCA8EAD00BB9B89 /* Subtitlr.entitlements in Resources */,
356 | C60B0A4F1BCE35FB00DD4286 /* dropzone_img@2x.png in Resources */,
357 | C60B0A4B1BCD41FD00DD4286 /* PopoverController.xib in Resources */,
358 | C6E0FC731BCAD7DC00EC5F81 /* MainWindowController.xib in Resources */,
359 | C60B0A4E1BCE35FB00DD4286 /* dropzone_img.png in Resources */,
360 | C6CF29921BCA8EAD00BB9B89 /* opensubs-logo.gif in Resources */,
361 | C6CF29911BCA8EAD00BB9B89 /* Credits.html in Resources */,
362 | C6CF29761BCA8E1700BB9B89 /* Assets.xcassets in Resources */,
363 | C6CF29901BCA8EAD00BB9B89 /* opensubs-logo.png in Resources */,
364 | C6E0FC6B1BCAD5A600EC5F81 /* MainMenu.xib in Resources */,
365 | );
366 | runOnlyForDeploymentPostprocessing = 0;
367 | };
368 | C67C2EC61BCA8AE100AD6F36 /* Resources */ = {
369 | isa = PBXResourcesBuildPhase;
370 | buildActionMask = 2147483647;
371 | files = (
372 | );
373 | runOnlyForDeploymentPostprocessing = 0;
374 | };
375 | C67C2ED11BCA8AE100AD6F36 /* Resources */ = {
376 | isa = PBXResourcesBuildPhase;
377 | buildActionMask = 2147483647;
378 | files = (
379 | );
380 | runOnlyForDeploymentPostprocessing = 0;
381 | };
382 | /* End PBXResourcesBuildPhase section */
383 |
384 | /* Begin PBXShellScriptBuildPhase section */
385 | 6B36B21AA6C21B3843E04796 /* Copy Pods Resources */ = {
386 | isa = PBXShellScriptBuildPhase;
387 | buildActionMask = 2147483647;
388 | files = (
389 | );
390 | inputPaths = (
391 | );
392 | name = "Copy Pods Resources";
393 | outputPaths = (
394 | );
395 | runOnlyForDeploymentPostprocessing = 0;
396 | shellPath = /bin/sh;
397 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Subtitlr/Pods-Subtitlr-resources.sh\"\n";
398 | showEnvVarsInLog = 0;
399 | };
400 | DB497872C2E728CC77E482CC /* Check Pods Manifest.lock */ = {
401 | isa = PBXShellScriptBuildPhase;
402 | buildActionMask = 2147483647;
403 | files = (
404 | );
405 | inputPaths = (
406 | );
407 | name = "Check Pods Manifest.lock";
408 | outputPaths = (
409 | );
410 | runOnlyForDeploymentPostprocessing = 0;
411 | shellPath = /bin/sh;
412 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
413 | showEnvVarsInLog = 0;
414 | };
415 | /* End PBXShellScriptBuildPhase section */
416 |
417 | /* Begin PBXSourcesBuildPhase section */
418 | C67C2EB31BCA8AE100AD6F36 /* Sources */ = {
419 | isa = PBXSourcesBuildPhase;
420 | buildActionMask = 2147483647;
421 | files = (
422 | C6CF298E1BCA8EAD00BB9B89 /* Constants.swift in Sources */,
423 | C6CF29651BCA8D5800BB9B89 /* OpenSubsAccess.swift in Sources */,
424 | C6E0FC641BCA954700EC5F81 /* FileHashMethod.swift in Sources */,
425 | C6CF298D1BCA8EAD00BB9B89 /* Languages.swift in Sources */,
426 | C6CF29941BCA8F9000BB9B89 /* AppDelegate.swift in Sources */,
427 | C6E0FC661BCA954700EC5F81 /* Video.swift in Sources */,
428 | C6E0FC721BCAD7DC00EC5F81 /* MainWindowController.swift in Sources */,
429 | C60B0A491BCD41EB00DD4286 /* PopoverController.swift in Sources */,
430 | C6E0FC651BCA954700EC5F81 /* Subtitle.swift in Sources */,
431 | );
432 | runOnlyForDeploymentPostprocessing = 0;
433 | };
434 | C67C2EC41BCA8AE100AD6F36 /* Sources */ = {
435 | isa = PBXSourcesBuildPhase;
436 | buildActionMask = 2147483647;
437 | files = (
438 | C6E0FC691BCAA52B00EC5F81 /* OpenSubsAccessTests.swift in Sources */,
439 | C67C2ECD1BCA8AE100AD6F36 /* SubtitlrTests.swift in Sources */,
440 | );
441 | runOnlyForDeploymentPostprocessing = 0;
442 | };
443 | C67C2ECF1BCA8AE100AD6F36 /* Sources */ = {
444 | isa = PBXSourcesBuildPhase;
445 | buildActionMask = 2147483647;
446 | files = (
447 | C67C2ED81BCA8AE100AD6F36 /* UITests.swift in Sources */,
448 | );
449 | runOnlyForDeploymentPostprocessing = 0;
450 | };
451 | /* End PBXSourcesBuildPhase section */
452 |
453 | /* Begin PBXTargetDependency section */
454 | C67C2ECA1BCA8AE100AD6F36 /* PBXTargetDependency */ = {
455 | isa = PBXTargetDependency;
456 | target = C67C2EB61BCA8AE100AD6F36 /* Subtitlr */;
457 | targetProxy = C67C2EC91BCA8AE100AD6F36 /* PBXContainerItemProxy */;
458 | };
459 | C67C2ED51BCA8AE100AD6F36 /* PBXTargetDependency */ = {
460 | isa = PBXTargetDependency;
461 | target = C67C2EB61BCA8AE100AD6F36 /* Subtitlr */;
462 | targetProxy = C67C2ED41BCA8AE100AD6F36 /* PBXContainerItemProxy */;
463 | };
464 | /* End PBXTargetDependency section */
465 |
466 | /* Begin XCBuildConfiguration section */
467 | C67C2EDA1BCA8AE100AD6F36 /* Debug */ = {
468 | isa = XCBuildConfiguration;
469 | buildSettings = {
470 | ALWAYS_SEARCH_USER_PATHS = NO;
471 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
472 | CLANG_CXX_LIBRARY = "libc++";
473 | CLANG_ENABLE_MODULES = YES;
474 | CLANG_ENABLE_OBJC_ARC = YES;
475 | CLANG_WARN_BOOL_CONVERSION = YES;
476 | CLANG_WARN_CONSTANT_CONVERSION = YES;
477 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
478 | CLANG_WARN_EMPTY_BODY = YES;
479 | CLANG_WARN_ENUM_CONVERSION = YES;
480 | CLANG_WARN_INT_CONVERSION = YES;
481 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
482 | CLANG_WARN_UNREACHABLE_CODE = YES;
483 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
484 | CODE_SIGN_IDENTITY = "-";
485 | COPY_PHASE_STRIP = NO;
486 | DEBUG_INFORMATION_FORMAT = dwarf;
487 | ENABLE_STRICT_OBJC_MSGSEND = YES;
488 | ENABLE_TESTABILITY = YES;
489 | GCC_C_LANGUAGE_STANDARD = gnu99;
490 | GCC_DYNAMIC_NO_PIC = NO;
491 | GCC_NO_COMMON_BLOCKS = YES;
492 | GCC_OPTIMIZATION_LEVEL = 0;
493 | GCC_PREPROCESSOR_DEFINITIONS = (
494 | "DEBUG=1",
495 | "$(inherited)",
496 | );
497 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
498 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
499 | GCC_WARN_UNDECLARED_SELECTOR = YES;
500 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
501 | GCC_WARN_UNUSED_FUNCTION = YES;
502 | GCC_WARN_UNUSED_VARIABLE = YES;
503 | MACOSX_DEPLOYMENT_TARGET = 10.11;
504 | MTL_ENABLE_DEBUG_INFO = YES;
505 | ONLY_ACTIVE_ARCH = YES;
506 | SDKROOT = macosx;
507 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
508 | };
509 | name = Debug;
510 | };
511 | C67C2EDB1BCA8AE100AD6F36 /* Release */ = {
512 | isa = XCBuildConfiguration;
513 | buildSettings = {
514 | ALWAYS_SEARCH_USER_PATHS = NO;
515 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
516 | CLANG_CXX_LIBRARY = "libc++";
517 | CLANG_ENABLE_MODULES = YES;
518 | CLANG_ENABLE_OBJC_ARC = YES;
519 | CLANG_WARN_BOOL_CONVERSION = YES;
520 | CLANG_WARN_CONSTANT_CONVERSION = YES;
521 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
522 | CLANG_WARN_EMPTY_BODY = YES;
523 | CLANG_WARN_ENUM_CONVERSION = YES;
524 | CLANG_WARN_INT_CONVERSION = YES;
525 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
526 | CLANG_WARN_UNREACHABLE_CODE = YES;
527 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
528 | CODE_SIGN_IDENTITY = "-";
529 | COPY_PHASE_STRIP = NO;
530 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
531 | ENABLE_NS_ASSERTIONS = NO;
532 | ENABLE_STRICT_OBJC_MSGSEND = YES;
533 | GCC_C_LANGUAGE_STANDARD = gnu99;
534 | GCC_NO_COMMON_BLOCKS = YES;
535 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
536 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
537 | GCC_WARN_UNDECLARED_SELECTOR = YES;
538 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
539 | GCC_WARN_UNUSED_FUNCTION = YES;
540 | GCC_WARN_UNUSED_VARIABLE = YES;
541 | MACOSX_DEPLOYMENT_TARGET = 10.11;
542 | MTL_ENABLE_DEBUG_INFO = NO;
543 | SDKROOT = macosx;
544 | };
545 | name = Release;
546 | };
547 | C67C2EDD1BCA8AE100AD6F36 /* Debug */ = {
548 | isa = XCBuildConfiguration;
549 | baseConfigurationReference = 939DFACE05D5CB3208F84560 /* Pods-Subtitlr.debug.xcconfig */;
550 | buildSettings = {
551 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
552 | CODE_SIGN_ENTITLEMENTS = Subtitlr.entitlements;
553 | CODE_SIGN_IDENTITY = "Mac Developer";
554 | COMBINE_HIDPI_IMAGES = YES;
555 | INFOPLIST_FILE = "Subtitlr 2.0/Info.plist";
556 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
557 | PRODUCT_BUNDLE_IDENTIFIER = com.eagerMoose.Subtitlr;
558 | PRODUCT_NAME = Subtitlr;
559 | SWIFT_OBJC_BRIDGING_HEADER = "Bridging-Header.h";
560 | };
561 | name = Debug;
562 | };
563 | C67C2EDE1BCA8AE100AD6F36 /* Release */ = {
564 | isa = XCBuildConfiguration;
565 | baseConfigurationReference = C622A25797A6FF275036C660 /* Pods-Subtitlr.release.xcconfig */;
566 | buildSettings = {
567 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
568 | CODE_SIGN_ENTITLEMENTS = Subtitlr.entitlements;
569 | CODE_SIGN_IDENTITY = "Mac Developer";
570 | COMBINE_HIDPI_IMAGES = YES;
571 | INFOPLIST_FILE = "Subtitlr 2.0/Info.plist";
572 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
573 | PRODUCT_BUNDLE_IDENTIFIER = com.eagerMoose.Subtitlr;
574 | PRODUCT_NAME = Subtitlr;
575 | SWIFT_OBJC_BRIDGING_HEADER = "Bridging-Header.h";
576 | };
577 | name = Release;
578 | };
579 | C67C2EE01BCA8AE100AD6F36 /* Debug */ = {
580 | isa = XCBuildConfiguration;
581 | buildSettings = {
582 | BUNDLE_LOADER = "$(TEST_HOST)";
583 | CODE_SIGN_ENTITLEMENTS = Subtitlr.entitlements;
584 | COMBINE_HIDPI_IMAGES = YES;
585 | INFOPLIST_FILE = "Subtitlr 2.0Tests/Info.plist";
586 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
587 | PODS_ROOT = "${SRCROOT}/Pods";
588 | PRODUCT_BUNDLE_IDENTIFIER = "com.eagerMoose.Subtitlr-2-0Tests";
589 | PRODUCT_NAME = Subtitlr;
590 | SWIFT_OBJC_BRIDGING_HEADER = "Bridging-Header.h";
591 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Subtitlr.app/Contents/MacOS/Subtitlr";
592 | USER_HEADER_SEARCH_PATHS = "$(inherited) \"${PODS_ROOT}/Headers/Public\" \"${PODS_ROOT}/Headers/Public/GZIP\" \"${PODS_ROOT}/Headers/Public/NSData+Base64\" \"${PODS_ROOT}/Headers/Public/xmlrpc\"";
593 | };
594 | name = Debug;
595 | };
596 | C67C2EE11BCA8AE100AD6F36 /* Release */ = {
597 | isa = XCBuildConfiguration;
598 | buildSettings = {
599 | BUNDLE_LOADER = "$(TEST_HOST)";
600 | CODE_SIGN_ENTITLEMENTS = Subtitlr.entitlements;
601 | COMBINE_HIDPI_IMAGES = YES;
602 | INFOPLIST_FILE = "Subtitlr 2.0Tests/Info.plist";
603 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
604 | PODS_ROOT = "${SRCROOT}/Pods";
605 | PRODUCT_BUNDLE_IDENTIFIER = "com.eagerMoose.Subtitlr-2-0Tests";
606 | PRODUCT_NAME = Subtitlr;
607 | SWIFT_OBJC_BRIDGING_HEADER = "Bridging-Header.h";
608 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Subtitlr.app/Contents/MacOS/Subtitlr";
609 | USER_HEADER_SEARCH_PATHS = "$(inherited) \"${PODS_ROOT}/Headers/Public\" \"${PODS_ROOT}/Headers/Public/GZIP\" \"${PODS_ROOT}/Headers/Public/NSData+Base64\" \"${PODS_ROOT}/Headers/Public/xmlrpc\"";
610 | };
611 | name = Release;
612 | };
613 | C67C2EE31BCA8AE100AD6F36 /* Debug */ = {
614 | isa = XCBuildConfiguration;
615 | buildSettings = {
616 | COMBINE_HIDPI_IMAGES = YES;
617 | INFOPLIST_FILE = "Subtitlr 2.0UITests/Info.plist";
618 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
619 | PRODUCT_BUNDLE_IDENTIFIER = "com.eagerMoose.Subtitlr-2-0UITests";
620 | PRODUCT_NAME = Subtitlr;
621 | TEST_TARGET_NAME = "Subtitlr 2.0";
622 | USES_XCTRUNNER = YES;
623 | };
624 | name = Debug;
625 | };
626 | C67C2EE41BCA8AE100AD6F36 /* Release */ = {
627 | isa = XCBuildConfiguration;
628 | buildSettings = {
629 | COMBINE_HIDPI_IMAGES = YES;
630 | INFOPLIST_FILE = "Subtitlr 2.0UITests/Info.plist";
631 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
632 | PRODUCT_BUNDLE_IDENTIFIER = "com.eagerMoose.Subtitlr-2-0UITests";
633 | PRODUCT_NAME = Subtitlr;
634 | TEST_TARGET_NAME = "Subtitlr 2.0";
635 | USES_XCTRUNNER = YES;
636 | };
637 | name = Release;
638 | };
639 | /* End XCBuildConfiguration section */
640 |
641 | /* Begin XCConfigurationList section */
642 | C67C2EB21BCA8AE100AD6F36 /* Build configuration list for PBXProject "Subtitlr" */ = {
643 | isa = XCConfigurationList;
644 | buildConfigurations = (
645 | C67C2EDA1BCA8AE100AD6F36 /* Debug */,
646 | C67C2EDB1BCA8AE100AD6F36 /* Release */,
647 | );
648 | defaultConfigurationIsVisible = 0;
649 | defaultConfigurationName = Release;
650 | };
651 | C67C2EDC1BCA8AE100AD6F36 /* Build configuration list for PBXNativeTarget "Subtitlr" */ = {
652 | isa = XCConfigurationList;
653 | buildConfigurations = (
654 | C67C2EDD1BCA8AE100AD6F36 /* Debug */,
655 | C67C2EDE1BCA8AE100AD6F36 /* Release */,
656 | );
657 | defaultConfigurationIsVisible = 0;
658 | defaultConfigurationName = Release;
659 | };
660 | C67C2EDF1BCA8AE100AD6F36 /* Build configuration list for PBXNativeTarget "SubtitlrTests" */ = {
661 | isa = XCConfigurationList;
662 | buildConfigurations = (
663 | C67C2EE01BCA8AE100AD6F36 /* Debug */,
664 | C67C2EE11BCA8AE100AD6F36 /* Release */,
665 | );
666 | defaultConfigurationIsVisible = 0;
667 | defaultConfigurationName = Release;
668 | };
669 | C67C2EE21BCA8AE100AD6F36 /* Build configuration list for PBXNativeTarget "SubtitlrUITests" */ = {
670 | isa = XCConfigurationList;
671 | buildConfigurations = (
672 | C67C2EE31BCA8AE100AD6F36 /* Debug */,
673 | C67C2EE41BCA8AE100AD6F36 /* Release */,
674 | );
675 | defaultConfigurationIsVisible = 0;
676 | defaultConfigurationName = Release;
677 | };
678 | /* End XCConfigurationList section */
679 | };
680 | rootObject = C67C2EAF1BCA8AE100AD6F36 /* Project object */;
681 | }
682 |
--------------------------------------------------------------------------------
/Subtitlr.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Subtitlr.xcodeproj/xcuserdata/spilja.xcuserdatad/xcschemes/Subtitlr 2.0.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
43 |
49 |
50 |
51 |
52 |
53 |
59 |
60 |
61 |
62 |
63 |
64 |
74 |
76 |
82 |
83 |
84 |
85 |
86 |
87 |
93 |
95 |
101 |
102 |
103 |
104 |
106 |
107 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/Subtitlr.xcodeproj/xcuserdata/spilja.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | Subtitlr 2.0.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | C67C2EB61BCA8AE100AD6F36
16 |
17 | primary
18 |
19 |
20 | C67C2EC71BCA8AE100AD6F36
21 |
22 | primary
23 |
24 |
25 | C67C2ED21BCA8AE100AD6F36
26 |
27 | primary
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/Video.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Videos.swift
3 | // subs
4 | //
5 | // Created by Lucija Frković on 21/07/15.
6 | // Copyright © 2015 Lucija Frković. All rights reserved.
7 | //
8 |
9 | import Foundation
10 |
11 |
12 |
13 | class Video {
14 | init(path: String){
15 | self.path = path
16 | self.subStatus = SubtitleStauts.NotSearched
17 | }
18 |
19 | var path: String
20 |
21 | enum SubtitleStauts {
22 | case NotSearched
23 | case Found
24 | case NotFound
25 | }
26 |
27 | var subStatus: SubtitleStauts?
28 |
29 | var subtitle: Subtitle?
30 |
31 | var hash: String {
32 | get {
33 | return FileHash().stringForHash(FileHash().hashForPath(path).fileHash) as String
34 | }
35 | }
36 |
37 | var size: UInt64 {
38 | get {
39 | return FileHash().hashForPath(path).fileSize
40 | }
41 | }
42 |
43 |
44 | var fileName: String {
45 | get {
46 | return (path as NSString).lastPathComponent
47 | }
48 | }
49 |
50 | func downloadSubtitle(){
51 | let osApi = OpenSubsAccess()
52 | osApi.logIn()
53 |
54 | if let result = osApi.getSubtitle(self.hash, size: Double(self.size)){
55 | let subFile = osApi.downloadSub(result.id, format: result.format)
56 |
57 | subtitle = Subtitle(path: path, ext: result.format)
58 | NSFileCoordinator.addFilePresenter(subtitle!)
59 |
60 | if let fData = subtitle, let url = fData.presentedItemURL {
61 | var errorMain: NSError?
62 | let coord = NSFileCoordinator(filePresenter: fData)
63 | coord.coordinateWritingItemAtURL(url, options: NSFileCoordinatorWritingOptions(), error: &errorMain, byAccessor: { writeUrl in
64 | subFile!.writeToFile(self.subtitle!.path, atomically: true)
65 |
66 | if NSFileManager.defaultManager().fileExistsAtPath(self.subtitle!.path) {
67 | self.subStatus = SubtitleStauts.Found
68 | }
69 | return
70 | })
71 | }
72 | }
73 | else {
74 | subStatus = SubtitleStauts.NotFound
75 | }
76 |
77 | }
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/dropzone_img.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lucijafrkovic/Subtitlr/0c0327bcdad6a317734952a0d410c43c045a69db/dropzone_img.png
--------------------------------------------------------------------------------
/dropzone_img@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lucijafrkovic/Subtitlr/0c0327bcdad6a317734952a0d410c43c045a69db/dropzone_img@2x.png
--------------------------------------------------------------------------------
/opensubs-logo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lucijafrkovic/Subtitlr/0c0327bcdad6a317734952a0d410c43c045a69db/opensubs-logo.gif
--------------------------------------------------------------------------------
/opensubs-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lucijafrkovic/Subtitlr/0c0327bcdad6a317734952a0d410c43c045a69db/opensubs-logo.png
--------------------------------------------------------------------------------