Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

adding an enml to html transformer

This allows viewing of notes in a UIWebView
  • Loading branch information...
commit 9c616ddd2cd7c9ea8ff034cc23e7356859f3fcde 1 parent 2c9229f
mustafa authored
Showing with 2,470 additions and 5 deletions.
  1. +82 −0 evernote-sdk-ios.xcodeproj/project.pbxproj
  2. +50 −0 evernote-sdk-ios/3rdParty/KSHTMLWriter/KSForwardingWriter.h
  3. +70 −0 evernote-sdk-ios/3rdParty/KSHTMLWriter/KSForwardingWriter.m
  4. +158 −0 evernote-sdk-ios/3rdParty/KSHTMLWriter/KSHTMLWriter.h
  5. +501 −0 evernote-sdk-ios/3rdParty/KSHTMLWriter/KSHTMLWriter.m
  6. +53 −0 evernote-sdk-ios/3rdParty/KSHTMLWriter/KSWriter.h
  7. +53 −0 evernote-sdk-ios/3rdParty/KSHTMLWriter/KSWriter.m
  8. +27 −0 evernote-sdk-ios/3rdParty/KSHTMLWriter/KSXMLAttributes.h
  9. +102 −0 evernote-sdk-ios/3rdParty/KSHTMLWriter/KSXMLAttributes.m
  10. +184 −0 evernote-sdk-ios/3rdParty/KSHTMLWriter/KSXMLWriter.h
  11. +691 −0 evernote-sdk-ios/3rdParty/KSHTMLWriter/KSXMLWriter.m
  12. +22 −0 evernote-sdk-ios/3rdParty/KSHTMLWriter/LICENSE.txt
  13. +23 −0 evernote-sdk-ios/3rdParty/KSHTMLWriter/NSString+XMLAdditions.h
  14. +66 −0 evernote-sdk-ios/3rdParty/KSHTMLWriter/NSString+XMLAdditions.m
  15. +16 −0 evernote-sdk-ios/ENConstants.h
  16. +17 −0 evernote-sdk-ios/ENConstants.m
  17. +19 −1 evernote-sdk-ios/Utilities/ENMLUtility.h
  18. +150 −3 evernote-sdk-ios/Utilities/ENMLUtility.m
  19. +1 −0  evernote-sdk-ios/Utilities/NSData+EvernoteSDK.h
  20. +22 −1 evernote-sdk-ios/Utilities/NSData+EvernoteSDK.m
  21. +12 −0 evernote-sdk-ios/Utilities/NSDataBase64Additions.h
  22. +151 −0 evernote-sdk-ios/Utilities/NSDataBase64Additions.m
View
82 evernote-sdk-ios.xcodeproj/project.pbxproj
@@ -154,6 +154,28 @@
A9AD4C5B16BA0572005609A6 /* EvernoteBridge.h in Headers */ = {isa = PBXBuildFile; fileRef = A9AD4C4016BA0572005609A6 /* EvernoteBridge.h */; };
A9B1E82016C056B700D54760 /* MoreViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A9B1E81F16C056B700D54760 /* MoreViewController.m */; };
A9B1E82716C1E73900D54760 /* StoreKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A9B1E82616C1E73900D54760 /* StoreKit.framework */; };
+ A9B1E86616C2242200D54760 /* KSForwardingWriter.h in Headers */ = {isa = PBXBuildFile; fileRef = A9B1E85B16C2242200D54760 /* KSForwardingWriter.h */; };
+ A9B1E86716C2242200D54760 /* KSForwardingWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = A9B1E85C16C2242200D54760 /* KSForwardingWriter.m */; };
+ A9B1E86816C2242200D54760 /* KSForwardingWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = A9B1E85C16C2242200D54760 /* KSForwardingWriter.m */; };
+ A9B1E86916C2242200D54760 /* KSHTMLWriter.h in Headers */ = {isa = PBXBuildFile; fileRef = A9B1E85D16C2242200D54760 /* KSHTMLWriter.h */; };
+ A9B1E86A16C2242200D54760 /* KSHTMLWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = A9B1E85E16C2242200D54760 /* KSHTMLWriter.m */; };
+ A9B1E86B16C2242200D54760 /* KSHTMLWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = A9B1E85E16C2242200D54760 /* KSHTMLWriter.m */; };
+ A9B1E86C16C2242200D54760 /* KSWriter.h in Headers */ = {isa = PBXBuildFile; fileRef = A9B1E85F16C2242200D54760 /* KSWriter.h */; };
+ A9B1E86D16C2242200D54760 /* KSWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = A9B1E86016C2242200D54760 /* KSWriter.m */; };
+ A9B1E86E16C2242200D54760 /* KSWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = A9B1E86016C2242200D54760 /* KSWriter.m */; };
+ A9B1E86F16C2242200D54760 /* KSXMLAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = A9B1E86116C2242200D54760 /* KSXMLAttributes.h */; };
+ A9B1E87016C2242200D54760 /* KSXMLAttributes.m in Sources */ = {isa = PBXBuildFile; fileRef = A9B1E86216C2242200D54760 /* KSXMLAttributes.m */; };
+ A9B1E87116C2242200D54760 /* KSXMLAttributes.m in Sources */ = {isa = PBXBuildFile; fileRef = A9B1E86216C2242200D54760 /* KSXMLAttributes.m */; };
+ A9B1E87216C2242200D54760 /* KSXMLWriter.h in Headers */ = {isa = PBXBuildFile; fileRef = A9B1E86316C2242200D54760 /* KSXMLWriter.h */; };
+ A9B1E87316C2242200D54760 /* KSXMLWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = A9B1E86416C2242200D54760 /* KSXMLWriter.m */; };
+ A9B1E87416C2242200D54760 /* KSXMLWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = A9B1E86416C2242200D54760 /* KSXMLWriter.m */; };
+ A9B1E87516C2242200D54760 /* LICENSE.txt in Resources */ = {isa = PBXBuildFile; fileRef = A9B1E86516C2242200D54760 /* LICENSE.txt */; };
+ A9B1E87A16C2259F00D54760 /* NSString+XMLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = A9B1E87816C2259F00D54760 /* NSString+XMLAdditions.h */; };
+ A9B1E87B16C2259F00D54760 /* NSString+XMLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = A9B1E87916C2259F00D54760 /* NSString+XMLAdditions.m */; };
+ A9B1E87C16C2259F00D54760 /* NSString+XMLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = A9B1E87916C2259F00D54760 /* NSString+XMLAdditions.m */; };
+ A9B1E88B16C2F99A00D54760 /* NSDataBase64Additions.h in Headers */ = {isa = PBXBuildFile; fileRef = A9B1E88916C2F99A00D54760 /* NSDataBase64Additions.h */; };
+ A9B1E88C16C2F99A00D54760 /* NSDataBase64Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = A9B1E88A16C2F99A00D54760 /* NSDataBase64Additions.m */; };
+ A9B1E88D16C2F99A00D54760 /* NSDataBase64Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = A9B1E88A16C2F99A00D54760 /* NSDataBase64Additions.m */; };
A9C552F816B5915200A97E48 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = A9C552F716B5915200A97E48 /* Default-568h@2x.png */; };
A9C554FC16712F17006E0020 /* NSDate+EDAMAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = A9C554FA16712F17006E0020 /* NSDate+EDAMAdditions.h */; };
A9C554FD16712F17006E0020 /* NSDate+EDAMAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = A9C554FB16712F17006E0020 /* NSDate+EDAMAdditions.m */; };
@@ -300,6 +322,21 @@
A9B1E81E16C056B700D54760 /* MoreViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MoreViewController.h; sourceTree = "<group>"; };
A9B1E81F16C056B700D54760 /* MoreViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MoreViewController.m; sourceTree = "<group>"; };
A9B1E82616C1E73900D54760 /* StoreKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = StoreKit.framework; path = System/Library/Frameworks/StoreKit.framework; sourceTree = SDKROOT; };
+ A9B1E85B16C2242200D54760 /* KSForwardingWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSForwardingWriter.h; sourceTree = "<group>"; };
+ A9B1E85C16C2242200D54760 /* KSForwardingWriter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSForwardingWriter.m; sourceTree = "<group>"; };
+ A9B1E85D16C2242200D54760 /* KSHTMLWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSHTMLWriter.h; sourceTree = "<group>"; };
+ A9B1E85E16C2242200D54760 /* KSHTMLWriter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSHTMLWriter.m; sourceTree = "<group>"; };
+ A9B1E85F16C2242200D54760 /* KSWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSWriter.h; sourceTree = "<group>"; };
+ A9B1E86016C2242200D54760 /* KSWriter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSWriter.m; sourceTree = "<group>"; };
+ A9B1E86116C2242200D54760 /* KSXMLAttributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSXMLAttributes.h; sourceTree = "<group>"; };
+ A9B1E86216C2242200D54760 /* KSXMLAttributes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSXMLAttributes.m; sourceTree = "<group>"; };
+ A9B1E86316C2242200D54760 /* KSXMLWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSXMLWriter.h; sourceTree = "<group>"; };
+ A9B1E86416C2242200D54760 /* KSXMLWriter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSXMLWriter.m; sourceTree = "<group>"; };
+ A9B1E86516C2242200D54760 /* LICENSE.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE.txt; sourceTree = "<group>"; };
+ A9B1E87816C2259F00D54760 /* NSString+XMLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+XMLAdditions.h"; sourceTree = "<group>"; };
+ A9B1E87916C2259F00D54760 /* NSString+XMLAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+XMLAdditions.m"; sourceTree = "<group>"; };
+ A9B1E88916C2F99A00D54760 /* NSDataBase64Additions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSDataBase64Additions.h; sourceTree = "<group>"; };
+ A9B1E88A16C2F99A00D54760 /* NSDataBase64Additions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSDataBase64Additions.m; sourceTree = "<group>"; };
A9C552F716B5915200A97E48 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default-568h@2x.png"; path = "../../../Default-568h@2x.png"; sourceTree = "<group>"; };
A9C554FA16712F17006E0020 /* NSDate+EDAMAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDate+EDAMAdditions.h"; sourceTree = "<group>"; };
A9C554FB16712F17006E0020 /* NSDate+EDAMAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDate+EDAMAdditions.m"; sourceTree = "<group>"; };
@@ -353,6 +390,7 @@
0B943F241525015500DB20A3 /* 3rdParty */ = {
isa = PBXGroup;
children = (
+ A9B1E85A16C2242200D54760 /* KSHTMLWriter */,
A96FE4EB16A0A3DB00F1AD8C /* AFNetworking */,
0B943F251525015500DB20A3 /* cocoa-oauth */,
0B943F2B1525015500DB20A3 /* NSString+URLEncoding */,
@@ -700,9 +738,31 @@
path = Bridge;
sourceTree = "<group>";
};
+ A9B1E85A16C2242200D54760 /* KSHTMLWriter */ = {
+ isa = PBXGroup;
+ children = (
+ A9B1E87816C2259F00D54760 /* NSString+XMLAdditions.h */,
+ A9B1E87916C2259F00D54760 /* NSString+XMLAdditions.m */,
+ A9B1E85B16C2242200D54760 /* KSForwardingWriter.h */,
+ A9B1E85C16C2242200D54760 /* KSForwardingWriter.m */,
+ A9B1E85D16C2242200D54760 /* KSHTMLWriter.h */,
+ A9B1E85E16C2242200D54760 /* KSHTMLWriter.m */,
+ A9B1E85F16C2242200D54760 /* KSWriter.h */,
+ A9B1E86016C2242200D54760 /* KSWriter.m */,
+ A9B1E86116C2242200D54760 /* KSXMLAttributes.h */,
+ A9B1E86216C2242200D54760 /* KSXMLAttributes.m */,
+ A9B1E86316C2242200D54760 /* KSXMLWriter.h */,
+ A9B1E86416C2242200D54760 /* KSXMLWriter.m */,
+ A9B1E86516C2242200D54760 /* LICENSE.txt */,
+ );
+ path = KSHTMLWriter;
+ sourceTree = "<group>";
+ };
A9C554F416712E8D006E0020 /* Utilities */ = {
isa = PBXGroup;
children = (
+ A9B1E88916C2F99A00D54760 /* NSDataBase64Additions.h */,
+ A9B1E88A16C2F99A00D54760 /* NSDataBase64Additions.m */,
A9C554FA16712F17006E0020 /* NSDate+EDAMAdditions.h */,
A9C554FB16712F17006E0020 /* NSDate+EDAMAdditions.m */,
A92602BD1672B6DD00F01E63 /* NSData+EvernoteSDK.h */,
@@ -772,6 +832,13 @@
A9AD4C5516BA0572005609A6 /* ENResourceAttachment.h in Headers */,
A9AD4C5816BA0572005609A6 /* ENSearchRequest.h in Headers */,
A9AD4C5B16BA0572005609A6 /* EvernoteBridge.h in Headers */,
+ A9B1E86616C2242200D54760 /* KSForwardingWriter.h in Headers */,
+ A9B1E86916C2242200D54760 /* KSHTMLWriter.h in Headers */,
+ A9B1E86C16C2242200D54760 /* KSWriter.h in Headers */,
+ A9B1E86F16C2242200D54760 /* KSXMLAttributes.h in Headers */,
+ A9B1E87216C2242200D54760 /* KSXMLWriter.h in Headers */,
+ A9B1E87A16C2259F00D54760 /* NSString+XMLAdditions.h in Headers */,
+ A9B1E88B16C2F99A00D54760 /* NSDataBase64Additions.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -871,6 +938,7 @@
A96E28E1165594480031EC63 /* Localizable.strings in Resources */,
A92602BC1672B4FE00F01E63 /* evernote_logo_4c-sm.png in Resources */,
A9C552F816B5915200A97E48 /* Default-568h@2x.png in Resources */,
+ A9B1E87516C2242200D54760 /* LICENSE.txt in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -962,6 +1030,13 @@
A9AD4C5316BA0572005609A6 /* ENNoteViewRequest.m in Sources */,
A9AD4C5616BA0572005609A6 /* ENResourceAttachment.m in Sources */,
A9AD4C5916BA0572005609A6 /* ENSearchRequest.m in Sources */,
+ A9B1E86716C2242200D54760 /* KSForwardingWriter.m in Sources */,
+ A9B1E86A16C2242200D54760 /* KSHTMLWriter.m in Sources */,
+ A9B1E86D16C2242200D54760 /* KSWriter.m in Sources */,
+ A9B1E87016C2242200D54760 /* KSXMLAttributes.m in Sources */,
+ A9B1E87316C2242200D54760 /* KSXMLWriter.m in Sources */,
+ A9B1E87B16C2259F00D54760 /* NSString+XMLAdditions.m in Sources */,
+ A9B1E88C16C2F99A00D54760 /* NSDataBase64Additions.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1015,6 +1090,13 @@
A9AD4C5716BA0572005609A6 /* ENResourceAttachment.m in Sources */,
A9AD4C5A16BA0572005609A6 /* ENSearchRequest.m in Sources */,
A9B1E82016C056B700D54760 /* MoreViewController.m in Sources */,
+ A9B1E86816C2242200D54760 /* KSForwardingWriter.m in Sources */,
+ A9B1E86B16C2242200D54760 /* KSHTMLWriter.m in Sources */,
+ A9B1E86E16C2242200D54760 /* KSWriter.m in Sources */,
+ A9B1E87116C2242200D54760 /* KSXMLAttributes.m in Sources */,
+ A9B1E87416C2242200D54760 /* KSXMLWriter.m in Sources */,
+ A9B1E87C16C2259F00D54760 /* NSString+XMLAdditions.m in Sources */,
+ A9B1E88D16C2F99A00D54760 /* NSDataBase64Additions.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
View
50 evernote-sdk-ios/3rdParty/KSHTMLWriter/KSForwardingWriter.h
@@ -0,0 +1,50 @@
+//
+// KSForwardingWriter.h
+//
+// Copyright (c) 2010, Mike Abdullah and Karelia Software
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL MIKE ABDULLAH OR KARELIA SOFTWARE BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Abstract base class for any writers that operate by sending strings along to an output writer.
+//
+
+
+#import <Foundation/Foundation.h>
+#import "KSWriter.h"
+
+
+@interface KSForwardingWriter : NSObject <KSWriter>
+{
+@private
+ id <KSWriter> _writer;
+}
+
+#pragma mark Creating a Writer
+- (id)initWithOutputWriter:(id <KSWriter>)stream; // designated initializer
+- (id)init; // calls -initWithOutputWriter with nil. Handy for iteration & deriving info, but not a lot else
+
+
+#pragma mark Primitive
+
+- (void)writeString:(NSString *)string; // calls -writeString: on our string stream. Override to customize raw writing
+
+
+@end
View
70 evernote-sdk-ios/3rdParty/KSHTMLWriter/KSForwardingWriter.m
@@ -0,0 +1,70 @@
+//
+// KSForwardingWriter.m
+//
+// Copyright (c) 2010, Mike Abdullah and Karelia Software
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL MIKE ABDULLAH OR KARELIA SOFTWARE BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+
+
+#import "KSForwardingWriter.h"
+
+
+@implementation KSForwardingWriter
+
+#pragma mark Init & Dealloc
+
+- (id)initWithOutputWriter:(id <KSWriter>)output; // designated initializer
+{
+ self = [super init];
+ if (self != nil) {
+ _writer = output;
+ }
+ return self;
+}
+
+- (id)init;
+{
+ return [self initWithOutputWriter:nil];
+}
+
+- (void)dealloc
+{
+ [self close];
+ NSAssert(!_writer, @"-close failed to dispose of output writer");
+
+}
+
+#pragma mark Writer Status
+
+- (void)close;
+{
+ _writer = nil;
+}
+
+#pragma mark Primitive
+
+- (void)writeString:(NSString *)string;
+{
+ [_writer writeString:string];
+}
+
+@end
View
158 evernote-sdk-ios/3rdParty/KSHTMLWriter/KSHTMLWriter.h
@@ -0,0 +1,158 @@
+//
+// KSHTMLWriter.h
+//
+// Copyright (c) 2010, Mike Abdullah and Karelia Software
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL MIKE ABDULLAH OR KARELIA SOFTWARE BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+
+
+#import "KSXMLWriter.h"
+
+
+extern NSString *KSHTMLWriterDocTypeHTML_4_01_Strict;
+extern NSString *KSHTMLWriterDocTypeHTML_4_01_Transitional;
+extern NSString *KSHTMLWriterDocTypeHTML_4_01_Frameset;
+extern NSString *KSHTMLWriterDocTypeXHTML_1_0_Strict;
+extern NSString *KSHTMLWriterDocTypeXHTML_1_0_Transitional;
+extern NSString *KSHTMLWriterDocTypeXHTML_1_0_Frameset;
+extern NSString *KSHTMLWriterDocTypeXHTML_1_1;
+extern NSString *KSHTMLWriterDocTypeHTML_5;
+
+
+@interface KSHTMLWriter : KSXMLWriter
+{
+@private
+ NSString *_docType;
+ BOOL _isXHTML;
+ NSMutableSet *_IDs;
+
+ NSMutableArray *_classNames;
+}
+
+#pragma mark Creating an HTML Writer
+// For if you desperately need to set a doctype before calling -startDocument:isXHTML: (perhaps because you're not going to call it!)
+- (id)initWithOutputWriter:(id <KSWriter>)output docType:(NSString *)docType encoding:(NSStringEncoding)encoding;
+
+
+#pragma mark DTD
+
+// Default is HTML5
+@property(nonatomic, copy, readonly) NSString *docType;
+
+// Whether empty elements should be written as <FOO> or <FOO />
+// Default is YES. There's no setter method; instead, specify with -startDocumentWithDocType:encoding: or when initializing.
+- (BOOL)isXHTML;
++ (BOOL)isDocTypeXHTML:(NSString *)docType;
+
+
+#pragma mark CSS Class Name
+// Class names are accumulated and written automatically as an attribute of the next element started
+// You can also push a class name using -pushAttribute:value: if attribute is 'class'
+- (void)pushClassName:(NSString *)className;
+
+
+#pragma mark HTML Fragments
+- (void)writeHTMLString:(NSString *)html;
+- (void)writeHTMLFormat:(NSString *)format , ...;
+
+
+#pragma mark General
+
+// <tagName id="idName" class="className">
+// Pretty standard convenience methods
+
+- (void)startElement:(NSString *)tagName className:(NSString *)className;
+
+- (void)startElement:(NSString *)tagName
+ idName:(NSString *)idName
+ className:(NSString *)className;
+
+- (BOOL)isIDValid:(NSString *)anID; // NO if the ID has already been used
+
+
+#pragma mark Line Break
+// <br /> OR <br>
+// depends on isXHTML
+- (void)writeLineBreak;
+
+
+#pragma mark Links
+// <a href="...." target="..." rel="nofollow">
+- (void)startAnchorElementWithHref:(NSString *)href title:(NSString *)titleString target:(NSString *)targetString rel:(NSString *)relString;
+
+
+#pragma mark Images
+// <img src="..." alt="..." width="..." height="..." />
+- (void)writeImageWithSrc:(NSString *)src
+ alt:(NSString *)alt
+ width:(id)width
+ height:(id)height;
+
+
+#pragma mark Link
+
+// <link>
+// Goes in <head> to link to scripts, CSS, etc.
+- (void)writeLinkWithHref:(NSString *)href
+ type:(NSString *)type // if nil, default is "text/css"
+ rel:(NSString *)rel
+ title:(NSString *)title
+ media:(NSString *)media;
+
+// Note: If a title is set, it is considered an *alternate* stylesheet. http://www.alistapart.com/articles/alternate/
+- (void)writeLinkToStylesheet:(NSString *)href
+ title:(NSString *)title
+ media:(NSString *)media;
+
+
+#pragma mark Scripts
+
+- (void)writeJavascriptWithSrc:(NSString *)src encoding:(NSStringEncoding)encoding;
+- (void)writeJavascriptWithSrc:(NSString *)src charset:(NSString *)charset;
+- (void)writeJavascript:(NSString *)script useCDATA:(BOOL)useCDATA;
+- (void)startJavascriptElementWithSrc:(NSString *)src; // src may be nil
+
+// Like -startCDATA and -endCDATA, but wrapped in a javascript comment so don't risk tripping up a browser's interpreter
+- (void)startJavascriptCDATA;
+- (void)endJavascriptCDATA;
+
+#pragma mark Param
+
+- (void)writeParamElementWithName:(NSString *)name value:(NSString *)value;
+
+#pragma mark Style
+- (void)writeStyleElementWithCSSString:(NSString *)css;
+- (void)startStyleElementWithType:(NSString *)type;
+
+
+#pragma mark Elements Stack
+- (BOOL)topElementIsList;
+
+
+#pragma mark Element Primitives
+// /> OR >
+// Which is used depends on -isXHTML
+- (void)closeEmptyElementTag;
+
+
+@end
+
View
501 evernote-sdk-ios/3rdParty/KSHTMLWriter/KSHTMLWriter.m
@@ -0,0 +1,501 @@
+//
+// KSHTMLWriter.m
+//
+// Copyright (c) 2010, Mike Abdullah and Karelia Software
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL MIKE ABDULLAH OR KARELIA SOFTWARE BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+
+
+#import "KSHTMLWriter.h"
+
+#import "KSXMLAttributes.h"
+
+
+NSString *KSHTMLWriterDocTypeHTML_4_01_Strict = @"HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\"";
+NSString *KSHTMLWriterDocTypeHTML_4_01_Transitional = @"HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\"";
+NSString *KSHTMLWriterDocTypeHTML_4_01_Frameset = @"HTML PUBLIC \"-//W3C//DTD HTML 4.01 Frameset//EN\" \"http://www.w3.org/TR/html4/frameset.dtd\"";
+NSString *KSHTMLWriterDocTypeXHTML_1_0_Strict = @"html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\"";
+NSString *KSHTMLWriterDocTypeXHTML_1_0_Transitional = @"html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"";
+NSString *KSHTMLWriterDocTypeXHTML_1_0_Frameset = @"html PUBLIC \"-//W3C//DTD XHTML 1.0 Frameset//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd\"";
+NSString *KSHTMLWriterDocTypeXHTML_1_1 = @"html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\"";
+NSString *KSHTMLWriterDocTypeHTML_5 = @"html";
+
+
+@interface KSHTMLWriter ()
+@property(nonatomic, copy, readwrite) NSString *docType;
+@end
+
+
+@implementation KSHTMLWriter
+
+#pragma mark Creating an HTML Writer
+
+- (id)initWithOutputWriter:(id <KSWriter>)output;
+{
+ self = [super initWithOutputWriter:output];
+ if (self != nil) {
+ [self setDocType:KSHTMLWriterDocTypeHTML_5];
+ _IDs = [[NSMutableSet alloc] init];
+ _classNames = [[NSMutableArray alloc] init];
+ }
+ return self;
+}
+
+- (id)initWithOutputWriter:(id <KSWriter>)output docType:(NSString *)docType encoding:(NSStringEncoding)encoding;
+{
+ if (self = [self initWithOutputWriter:output encoding:encoding])
+ {
+ [self setDocType:docType];
+ }
+
+ return self;
+}
+
+
+#pragma mark DTD
+
+- (void)startDocumentWithDocType:(NSString *)docType encoding:(NSStringEncoding)encoding;
+{
+ [self setDocType:docType];
+ [super startDocumentWithDocType:docType encoding:encoding];
+}
+
+@synthesize docType = _docType;
+- (void)setDocType:(NSString *)docType;
+{
+ docType = [docType copy];
+ _docType = docType;
+
+ _isXHTML = [[self class] isDocTypeXHTML:docType];
+}
+
+- (BOOL)isXHTML; { return _isXHTML; }
+
++ (BOOL)isDocTypeXHTML:(NSString *)docType;
+{
+ BOOL result = !([docType isEqualToString:KSHTMLWriterDocTypeHTML_4_01_Strict] ||
+ [docType isEqualToString:KSHTMLWriterDocTypeHTML_4_01_Transitional] ||
+ [docType isEqualToString:KSHTMLWriterDocTypeHTML_4_01_Frameset]);
+ return result;
+}
+
+#pragma mark CSS Class Name
+
+- (NSString *)currentElementClassName;
+{
+ NSString *result = nil;
+ if ([_classNames count])
+ {
+ result = [_classNames componentsJoinedByString:@" "];
+ }
+ return result;
+}
+
+- (void)pushClassName:(NSString *)className;
+{
+#ifdef DEBUG
+ if ([_classNames containsObject:className])
+ {
+ NSLog(@"Adding class \"%@\" to an element twice", className);
+ }
+#endif
+
+ [_classNames addObject:className];
+}
+
+- (void)pushAttribute:(NSString *)attribute value:(id)value;
+{
+ if ([attribute isEqualToString:@"class"])
+ {
+ return [self pushClassName:value];
+ }
+
+ // Keep track of IDs in use
+ if ([attribute isEqualToString:@"id"]) [_IDs addObject:value];
+ [super pushAttribute:attribute value:value];
+}
+
+- (KSXMLAttributes *)currentAttributes;
+{
+ KSXMLAttributes *result = [super currentAttributes];
+
+ // Add in buffered class info
+ NSString *class = [self currentElementClassName];
+ if (class) [result addAttribute:@"class" value:class];
+
+ return result;
+}
+
+- (BOOL)hasCurrentAttributes;
+{
+ return ([super hasCurrentAttributes] || [_classNames count]);
+}
+
+#pragma mark HTML Fragments
+
+- (void)writeHTMLString:(NSString *)html;
+{
+ [self writeString:html];
+}
+
+- (void)writeHTMLFormat:(NSString *)format , ...
+{
+ va_list argList;
+ va_start(argList, format);
+ NSString *aString = [[NSString alloc] initWithFormat:format arguments:argList];
+ va_end(argList);
+
+ [self writeHTMLString:aString];
+}
+
+#pragma mark General
+
+- (void)startElement:(NSString *)tagName className:(NSString *)className;
+{
+ [self startElement:tagName idName:nil className:className];
+}
+
+- (void)startElement:(NSString *)tagName idName:(NSString *)idName className:(NSString *)className;
+{
+ if (idName) [self pushAttribute:@"id" value:idName];
+ if (className) [self pushAttribute:@"class" value:className];
+
+ [self startElement:tagName];
+}
+
+- (BOOL)isIDValid:(NSString *)anID; // NO if the ID has already been used
+{
+ BOOL result = ![_IDs containsObject:anID];
+ return result;
+}
+
+#pragma mark Line Break
+
+- (void)writeLineBreak;
+{
+ [self startElement:@"br"];
+ [self endElement];
+}
+
+#pragma mark Higher-level Tag Writing
+
+- (void)startAnchorElementWithHref:(NSString *)href title:(NSString *)titleString target:(NSString *)targetString rel:(NSString *)relString;
+{
+ if (href) [self pushAttribute:@"href" value:href];
+ if (targetString) [self pushAttribute:@"target" value:targetString];
+ if (titleString) [self pushAttribute:@"title" value:titleString];
+ if (relString) [self pushAttribute:@"rel" value:relString];
+
+ [self startElement:@"a"];
+}
+
+- (void)writeImageWithSrc:(NSString *)src
+ alt:(NSString *)alt
+ width:(id)width
+ height:(id)height;
+{
+ [self pushAttribute:@"src" value:src];
+ [self pushAttribute:@"alt" value:alt];
+ if (width) [self pushAttribute:@"width" value:width];
+ if (height) [self pushAttribute:@"height" value:height];
+
+ [self startElement:@"img"];
+ [self endElement];
+}
+
+#pragma mark Link
+
+- (void)writeLinkWithHref:(NSString *)href
+ type:(NSString *)type
+ rel:(NSString *)rel
+ title:(NSString *)title
+ media:(NSString *)media;
+{
+ if (rel) [self pushAttribute:@"rel" value:rel];
+ if (!type) type = @"text/css"; [self pushAttribute:@"type" value:type];
+ [self pushAttribute:@"href" value:href];
+ if (title) [self pushAttribute:@"title" value:title];
+ if (media) [self pushAttribute:@"media" value:media];
+
+ [self startElement:@"link"];
+ [self endElement];
+}
+
+- (void)writeLinkToStylesheet:(NSString *)href
+ title:(NSString *)title
+ media:(NSString *)media;
+{
+ [self writeLinkWithHref:href type:nil rel:@"stylesheet" title:title media:media];
+}
+
+#pragma mark Scripts
+
+- (void)writeJavascriptWithSrc:(NSString *)src encoding:(NSStringEncoding)encoding;
+{
+ // According to the HTML spec, charset only needs to be specified if the script is a different encoding to the document
+ NSString *charset = nil;
+ if (encoding != [self encoding])
+ {
+ charset = (__bridge NSString *)CFStringConvertEncodingToIANACharSetName(CFStringConvertNSStringEncodingToEncoding(encoding));
+ }
+
+ [self writeJavascriptWithSrc:src charset:charset];
+}
+
+- (void)writeJavascriptWithSrc:(NSString *)src charset:(NSString *)charset; // src may be nil
+{
+ if (charset) [self pushAttribute:@"charset" value:charset];
+ [self startJavascriptElementWithSrc:src];
+ [self endElement];
+}
+
+- (void)writeJavascript:(NSString *)script useCDATA:(BOOL)useCDATA;
+{
+ [self startJavascriptElementWithSrc:nil];
+
+ if (useCDATA) [self startJavascriptCDATA];
+ [self writeString:script];
+ if (useCDATA) [self endJavascriptCDATA];
+
+ [self endElement];
+}
+
+- (void)startJavascriptElementWithSrc:(NSString *)src; // src may be nil
+{
+ // HTML5 doesn't need the script type specified, but older doc types do for standards-compliance
+ if (![[self docType] isEqualToString:KSHTMLWriterDocTypeHTML_5])
+ {
+ [self pushAttribute:@"type" value:@"text/javascript"];
+ }
+
+ // Script
+ if (src)
+ {
+ [self pushAttribute:@"src" value:src];
+ }
+
+ [self startElement:@"script"];
+
+ // Embedded scripts should start on their own line for clarity
+ if (!src)
+ {
+ [self writeString:@"\n"];
+ [self stopWritingInline];
+ }
+}
+
+- (void)startJavascriptCDATA;
+{
+ [self writeString:@"\n/* "];
+ [self startCDATA];
+ [self writeString:@" */"];
+}
+
+- (void)endJavascriptCDATA;
+{
+ [self writeString:@"\n/* "];
+ [self endCDATA];
+ [self writeString:@" */\n"];
+}
+
+#pragma mark Param
+
+- (void)writeParamElementWithName:(NSString *)name value:(NSString *)value;
+{
+ if (name) [self pushAttribute:@"name" value:name];
+ if (value) [self pushAttribute:@"value" value:value];
+ [self startElement:@"param"];
+ [self endElement];
+}
+
+#pragma mark Style
+
+- (void)writeStyleElementWithCSSString:(NSString *)css;
+{
+ [self startStyleElementWithType:@"text/css"];
+ [self writeString:css]; // browsers don't expect styles to be XML escaped
+ [self endElement];
+}
+
+- (void)startStyleElementWithType:(NSString *)type;
+{
+ if (type) [self pushAttribute:@"type" value:type];
+ [self startElement:@"style"];
+}
+
+#pragma mark Elements Stack
+
+- (BOOL)topElementIsList;
+{
+ NSString *tagName = [self topElement];
+ BOOL result = ([tagName isEqualToString:@"ul"] ||
+ [tagName isEqualToString:@"ol"]);
+ return result;
+}
+
+#pragma mark (X)HTML
+
+- (BOOL)elementCanBeEmpty:(NSString *)tagName;
+{
+ if ([tagName isEqualToString:@"br"] ||
+ [tagName isEqualToString:@"img"] ||
+ [tagName isEqualToString:@"hr"] ||
+ [tagName isEqualToString:@"meta"] ||
+ [tagName isEqualToString:@"link"] ||
+ [tagName isEqualToString:@"input"] ||
+ [tagName isEqualToString:@"base"] ||
+ [tagName isEqualToString:@"basefont"] ||
+ [tagName isEqualToString:@"param"] ||
+ [tagName isEqualToString:@"area"] ||
+ [tagName isEqualToString:@"source"]) return YES;
+
+ return NO;
+}
+
+- (BOOL)canWriteElementInline:(NSString *)tagName;
+{
+ switch ([tagName length])
+ {
+ case 1:
+ if ([tagName isEqualToString:@"a"] ||
+ [tagName isEqualToString:@"b"] ||
+ [tagName isEqualToString:@"i"] ||
+ [tagName isEqualToString:@"u"] ||
+ [tagName isEqualToString:@"q"]) return YES;
+ break;
+
+ case 2:
+ if ([tagName isEqualToString:@"br"] ||
+ [tagName isEqualToString:@"em"] ||
+ [tagName isEqualToString:@"tt"]) return YES;
+ break;
+
+ case 3:
+ if ([tagName isEqualToString:@"img"] ||
+ [tagName isEqualToString:@"sup"] ||
+ [tagName isEqualToString:@"sub"] ||
+ [tagName isEqualToString:@"big"] ||
+ [tagName isEqualToString:@"del"] ||
+ [tagName isEqualToString:@"ins"] ||
+ [tagName isEqualToString:@"dfn"] ||
+ [tagName isEqualToString:@"map"] ||
+ [tagName isEqualToString:@"var"] ||
+ [tagName isEqualToString:@"bdo"] ||
+ [tagName isEqualToString:@"kbd"]) return YES;
+ break;
+
+ case 4:
+ if ([tagName isEqualToString:@"span"] ||
+ [tagName isEqualToString:@"font"] ||
+ [tagName isEqualToString:@"abbr"] ||
+ [tagName isEqualToString:@"cite"] ||
+ [tagName isEqualToString:@"code"] ||
+ [tagName isEqualToString:@"samp"]) return YES;
+ break;
+
+ case 5:
+ if ([tagName isEqualToString:@"small"] ||
+ [tagName isEqualToString:@"input"] ||
+ [tagName isEqualToString:@"label"]) return YES;
+ break;
+
+ case 6:
+ if ([tagName isEqualToString:@"strong"] ||
+ [tagName isEqualToString:@"select"] ||
+ [tagName isEqualToString:@"button"] ||
+ [tagName isEqualToString:@"object"] ||
+ [tagName isEqualToString:@"applet"] ||
+ [tagName isEqualToString:@"script"]) return YES;
+ break;
+
+ case 7:
+ if ([tagName isEqualToString:@"acronym"]) return YES;
+ break;
+
+ case 8:
+ if ([tagName isEqualToString:@"textarea"]) return YES;
+ break;
+ }
+
+ return [super canWriteElementInline:tagName];
+}
+
+- (BOOL)validateElement:(NSString *)element;
+{
+ if (![super validateElement:element]) return NO;
+
+ // Lists can only contain list items
+ if ([self topElementIsList])
+ {
+ return [element isEqualToString:@"li"];
+ }
+ else
+ {
+ return YES;
+ }
+}
+
+- (NSString *)validateAttribute:(NSString *)name value:(NSString *)value ofElement:(NSString *)element;
+{
+ NSString *result = [super validateAttribute:name value:value ofElement:element];
+ if (!result) return nil;
+
+ // value is only allowed as a list item attribute when in an ordered list
+ if ([element isEqualToString:@"li"] && [name isEqualToString:@"value"])
+ {
+ if (![[self topElement] isEqualToString:@"ol"]) result = nil;
+ }
+
+ return result;
+}
+
+#pragma mark Element Primitives
+
+- (void)startElement:(NSString *)elementName writeInline:(BOOL)writeInline; // for more control
+{
+ NSAssert1([elementName isEqualToString:[elementName lowercaseString]], @"Attempt to start non-lowercase element: %@", elementName);
+
+
+ // Add in any pre-written classes
+ NSString *class = [self currentElementClassName];
+ if (class)
+ {
+ [_classNames removeAllObjects];
+ [super pushAttribute:@"class" value:class];
+ }
+
+ [super startElement:elementName writeInline:writeInline];
+}
+
+- (void)closeEmptyElementTag; // /> OR > depending on -isXHTML
+{
+ if ([self isXHTML])
+ {
+ [super closeEmptyElementTag];
+ }
+ else
+ {
+ [self writeString:@">"];
+ }
+}
+
+@end
View
53 evernote-sdk-ios/3rdParty/KSHTMLWriter/KSWriter.h
@@ -0,0 +1,53 @@
+//
+// KSWriter.h
+//
+// Copyright (c) 2010, Mike Abdullah and Karelia Software
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL MIKE ABDULLAH OR KARELIA SOFTWARE BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+
+
+#import <Foundation/Foundation.h>
+
+
+@protocol KSWriter <NSObject>
+- (void)writeString:(NSString *)string;
+- (void)close; // most writers will ignore, but others may use it to trigger an action
+@end
+
+
+@protocol KSBufferingWriter <KSWriter>
+- (void)startBuffering; // can be called multiple times, implementor chooses how to handle that
+- (void)flush; // writes all buffered content
+- (void)writeString:(NSString *)string bypassBuffer:(BOOL)bypassBuffer;
+@end
+
+
+@protocol KSMultiBufferingWriter <KSBufferingWriter>
+- (void)startBuffering; // each call is expected to start a new distinct buffer, while maintaining the old
+- (void)flushFirstBuffer; // thus you can stagger beginning and ending buffers
+- (NSUInteger)numberOfBuffers;
+- (void)writeString:(NSString *)string toBufferAtIndex:(NSUInteger)index; // 0 bypasses all buffers
+@end
+
+
+@interface NSMutableString (KSWriter) <KSWriter>
+@end
View
53 evernote-sdk-ios/3rdParty/KSHTMLWriter/KSWriter.m
@@ -0,0 +1,53 @@
+//
+// KSWriter.m
+//
+// Copyright (c) 2010, Mike Abdullah and Karelia Software
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL MIKE ABDULLAH OR KARELIA SOFTWARE BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+
+
+#import "KSWriter.h"
+
+
+@implementation NSMutableString (KSWriter)
+
+- (void)writeString:(NSString *)string
+{
+ /* This was some experimental code to see if it would speed up writing:
+ const UniChar *characters = CFStringGetCharactersPtr((CFStringRef)string);
+ if (characters)
+ {
+ CFStringAppendCharacters((CFMutableStringRef)self,
+ characters,
+ CFStringGetLength((CFStringRef)string));
+ }
+ else
+ {
+ CFStringAppend((CFMutableStringRef)self, (CFStringRef)string);
+ }*/
+
+ [self appendString:string];
+}
+
+- (void)close; { } // do nothing as it makes no sense to close a mutable string
+
+@end
View
27 evernote-sdk-ios/3rdParty/KSHTMLWriter/KSXMLAttributes.h
@@ -0,0 +1,27 @@
+//
+// KSXMLAttributes.h
+// Sandvox
+//
+// Created by Mike on 19/11/2010.
+// Copyright 2010 Karelia Software. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+
+@interface KSXMLAttributes : NSObject <NSCopying>
+{
+@private
+ NSMutableArray *_attributes;
+}
+
+- (id)initWithXMLAttributes:(KSXMLAttributes *)info;
+
+@property(nonatomic, copy) NSDictionary *attributesAsDictionary;
+- (BOOL)hasAttributes;
+- (void)addAttribute:(NSString *)attribute value:(id)value;
+
+- (void)close; // removes all attributes
+
+
+@end
View
102 evernote-sdk-ios/3rdParty/KSHTMLWriter/KSXMLAttributes.m
@@ -0,0 +1,102 @@
+//
+// KSXMLAttributes.m
+// Sandvox
+//
+// Created by Mike on 19/11/2010.
+// Copyright 2010 Karelia Software. All rights reserved.
+//
+
+#import "KSXMLAttributes.h"
+
+#import "KSXMLWriter.h"
+
+
+@implementation KSXMLAttributes
+
+#pragma mark Lifecycle
+
+- (id)init;
+{
+ self = [super init];
+ if (self != nil) {
+ _attributes = [[NSMutableArray alloc] initWithCapacity:2];
+ }
+ return self;
+}
+
+- (id)initWithXMLAttributes:(KSXMLAttributes *)info;
+{
+ self = [super init]; // call super, so _attributes is still nil
+
+ _attributes = [info->_attributes mutableCopy];
+
+ return self;
+}
+
+
+- (NSDictionary *)attributesAsDictionary;
+{
+ NSMutableDictionary *result = [NSMutableDictionary dictionary];
+
+ for (int i = 0; i < [_attributes count]; i+=2)
+ {
+ NSString *attribute = [_attributes objectAtIndex:i];
+ NSString *value = [_attributes objectAtIndex:i+1];
+ [result setObject:value forKey:attribute];
+ }
+
+ return result;
+}
+
+- (void)setAttributesAsDictionary:(NSDictionary *)dictionary;
+{
+ for (NSString *anAttribute in dictionary)
+ {
+ [self addAttribute:anAttribute value:[dictionary objectForKey:anAttribute]];
+ }
+}
+
+- (BOOL)hasAttributes;
+{
+ return [_attributes count];
+}
+
+- (void)addAttribute:(NSString *)attribute value:(id)value;
+{
+ NSParameterAssert(value);
+
+ // TODO: Ignore if the attribute is already present
+
+ [_attributes addObject:attribute];
+ [_attributes addObject:value];
+}
+
+- (void)close; // sets name to nil and removes all attributes
+{
+ [_attributes removeAllObjects];
+}
+
+#pragma mark NSCopying
+
+- (id)copyWithZone:(NSZone *)zone;
+{
+ return [[[KSXMLAttributes class] alloc] initWithXMLAttributes:self];
+}
+
+#pragma mark Description
+
+- (NSString *)description;
+{
+ NSMutableString *result = [NSMutableString stringWithString:[super description]];
+
+ KSXMLWriter *writer = [[KSXMLWriter alloc] initWithOutputWriter:result];
+ [writer writeString:@" "];
+
+ [writer startElement:@"" attributes:[self attributesAsDictionary]];
+ [writer endElement];
+
+
+ return result;
+}
+
+@end
View
184 evernote-sdk-ios/3rdParty/KSHTMLWriter/KSXMLWriter.h
@@ -0,0 +1,184 @@
+//
+// KSXMLWriter.h
+//
+// Copyright (c) 2010, Mike Abdullah and Karelia Software
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL MIKE ABDULLAH OR KARELIA SOFTWARE BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+
+
+#import "KSForwardingWriter.h"
+
+#import "KSXMLAttributes.h"
+
+
+@class KSXMLElementContentsProxy;
+
+
+@interface KSXMLWriter : KSForwardingWriter
+{
+@private
+ KSXMLAttributes *_attributes;
+ NSMutableArray *_openElements;
+ BOOL _elementIsEmpty;
+ NSUInteger _inlineWritingLevel; // the number of open elements at which inline writing began
+
+ KSXMLElementContentsProxy *_contentsProxy;
+
+ NSInteger _indentation;
+
+ NSStringEncoding _encoding;
+}
+
+#pragma mark Creating an XML Writer
+
+// If output responds to -encoding, that is used as the default encoding. Designated initializer
+- (id)initWithOutputWriter:(id <KSWriter>)output;
+
+// Use this if you need to set encoding up-front, rather than by starting document
+- (id)initWithOutputWriter:(id <KSWriter>)output encoding:(NSStringEncoding)encoding;
+
+
+#pragma mark Writer Status
+- (void)close; // calls -flush, then releases most ivars such as _writer
+- (void)flush; // if there's anything waiting to be lazily written, forces it to write now. For subclasses to implement
+
+
+#pragma mark Document
+// e.g. docType of @"html" for HTML 5. KSHTMLWriter declares many such constants
+- (void)startDocumentWithDocType:(NSString *)docType encoding:(NSStringEncoding)encoding;
+
+
+#pragma mark Characters
+
+// Escapes the string and calls -writeString:. NOT intended for writing text-like strings e.g. element attributed
+- (void)writeCharacters:(NSString *)string;
+
+// Convenience to perform escaping without instantiating a writer
++ (NSString *)stringFromCharacters:(NSString *)string;
+
+
+#pragma mark Elements
+
+// Convenience for writing <tag>text</tag>
+- (void)writeElement:(NSString *)elementName text:(NSString *)text;
+
+// These simple methods make up the bulk of element writing. You can start as many elements at a time as you like in order to nest them. Calling -endElement will automatically know the right close tag to write etc.
+- (void)startElement:(NSString *)elementName;
+- (void)startElement:(NSString *)elementName writeInline:(BOOL)writeInline; // for more control
+- (void)startElement:(NSString *)elementName attributes:(NSDictionary *)attributes;
+- (void)endElement;
+
+- (void)willStartElement:(NSString *)element;
+
+
+#pragma mark Being Too Clever For Your Own Good
+// Since we don't have blocks support yet, this is a slight approximation. You could do something like this:
+//
+// [[writer writeElement:@"foo" contentsInvocationTarget:self]
+// writeFooContents];
+//
+// Where if the -writeFooContents method writes another element and some text, you get this markup:
+//
+// <foo>
+// <bar>baz</baz>
+// </foo>
+//
+// This is about the same amount of code as calling -startElement: and -endElement: seperately. But, it can help make your code more readable, and will also sanity check to make sure the contents invocation balanced its calls to -startElement: and -endElement:
+- (id)writeElement:(NSString *)elementName contentsInvocationTarget:(id)target;
+
+
+#pragma mark Current Element
+/* You can also gain finer-grained control over element attributes. KSXMLWriter maintains a list of attributes that will be applied when you *next* call one of the -startElement: methods. This has several advantages:
+ * - Attributes are written in exactly the order you specify
+ * - More efficient than building up a temporary dictionary object
+ * - Can sneak extra attributes in when using a convenience method (e.g. for HTML)
+ */
+- (void)pushAttribute:(NSString *)attribute value:(id)value;
+- (KSXMLAttributes *)currentAttributes; // modifying this object will not affect writing
+- (BOOL)hasCurrentAttributes; // faster than querying -currentAttributes
+
+
+#pragma mark Attributes
+// Like +stringFromCharacters: but for attributes, where quotes need to be escaped
++ (NSString *)stringFromAttributeValue:(NSString *)value;
+
+
+#pragma mark Whitespace
+// Writes a newline character and the tabs to match -indentationLevel. Normally newlines are automatically written for you; call this if you need an extra one.
+- (void)startNewline;
+
+
+#pragma mark Comments
+- (void)writeComment:(NSString *)comment; // escapes the string, and wraps in a comment tag
+- (void)openComment;
+- (void)closeComment;
+
+
+#pragma mark CDATA
+- (void)startCDATA;
+- (void)endCDATA;
+
+
+#pragma mark Indentation
+// Setting the indentation level does not write to the context in any way. It is up to methods that actually do some writing to respect the indent level. e.g. starting a new line should indent that line to match.
+@property(nonatomic) NSInteger indentationLevel;
+- (void)increaseIndentationLevel;
+- (void)decreaseIndentationLevel;
+
+
+#pragma mark Validation
+// Default implementation returns YES. Subclasses can override to advise that the writing of an element would result in invalid markup
+- (BOOL)validateElement:(NSString *)element;
+- (NSString *)validateAttribute:(NSString *)name value:(NSString *)value ofElement:(NSString *)element;
+
+
+
+#pragma mark Elements Stack
+// XMLWriter maintains a stack of the open elements so it knows how to end them. You probably don't ever care about this, but it can be handy in more advanced use cases
+
+@property(weak, nonatomic, readonly) NSArray *openElements; // the methods below are faster than this
+
+- (NSUInteger)openElementsCount;
+- (BOOL)hasOpenElement:(NSString *)tagName;
+
+- (NSString *)topElement;
+- (void)pushElement:(NSString *)element;
+- (void)popElement;
+
+
+#pragma mark Element Primitives
+- (void)closeEmptyElementTag;
+
+
+#pragma mark Inline Writing
+- (BOOL)isWritingInline;
+- (void)startWritingInline;
+- (void)stopWritingInline;
+- (BOOL)canWriteElementInline:(NSString *)tagName;
+
+
+#pragma mark String Encoding
+@property(nonatomic, readonly) NSStringEncoding encoding; // default is UTF-8
+- (void)writeString:(NSString *)string; // anything outside .encoding gets escaped
+
+
+@end
View
691 evernote-sdk-ios/3rdParty/KSHTMLWriter/KSXMLWriter.m
@@ -0,0 +1,691 @@
+//
+// KSXMLWriter.m
+//
+// Copyright (c) 2010, Mike Abdullah and Karelia Software
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL MIKE ABDULLAH OR KARELIA SOFTWARE BE LIABLE FOR ANY
+// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+
+
+#import "KSXMLWriter.h"
+#import "NSString+XMLAdditions.h"
+
+
+@interface KSXMLElementContentsProxy : NSProxy
+{
+@private
+ id _target; // weak ref
+ KSXMLWriter *_XMLWriter; // weak ref
+ NSUInteger _elementsCount;
+}
+- (void)ks_prepareWithTarget:(id)target XMLWriter:(KSXMLWriter *)writer;
+@end
+
+
+#pragma mark -
+
+
+@interface KSXMLWriter ()
+
+- (void)writeStringByEscapingXMLEntities:(NSString *)string escapeQuot:(BOOL)escapeQuotes;
+
+#pragma mark Element Primitives
+
+// attribute="value"
+- (void)writeAttribute:(NSString *)attribute
+ value:(id)value;
+
+// Starts tracking -writeString: calls to see if element is empty
+- (void)didStartElement;
+
+// >
+// Then increases indentation level
+- (void)closeStartTag;
+
+// />
+- (void)closeEmptyElementTag;
+
+- (void)writeEndTag:(NSString *)tagName; // primitive version that ignores open elements stack
+
+- (BOOL)elementCanBeEmpty:(NSString *)tagName; // YES for everything in pure XML
+
+@property(nonatomic, readwrite) NSStringEncoding encoding; // default is UTF-8
+
+@end
+
+
+@interface KSXMLAttributes (KSXMLWriter)
+- (void)writeAttributes:(KSXMLWriter *)writer;
+@end
+
+
+#pragma mark -
+
+
+@implementation KSXMLWriter
+
+#pragma mark Init & Dealloc
+
+- (id)initWithOutputWriter:(id <KSWriter>)output; // designated initializer
+{
+ self = [super initWithOutputWriter:output];
+ if (self != nil) {
+ _attributes = [[KSXMLAttributes alloc] init];
+ _openElements = [[NSMutableArray alloc] init];
+
+ // Inherit encoding where possible
+ _encoding = ([output respondsToSelector:@selector(encoding)] ?
+ [(KSXMLWriter *)output encoding] :
+ NSUTF8StringEncoding);
+
+ _contentsProxy = [KSXMLElementContentsProxy alloc]; // it's a proxy without an -init method
+ }
+ return self;
+}
+
+- (id)initWithOutputWriter:(id <KSWriter>)output encoding:(NSStringEncoding)encoding;
+{
+ if (self = [self initWithOutputWriter:output])
+ {
+ [self setEncoding:encoding];
+ }
+
+ return self;
+}
+
+
+#pragma mark Writer Status
+
+- (void)close;
+{
+ [self flush];
+ [super close];
+}
+
+- (void)flush; { }
+
+#pragma mark Document
+
+- (void)startDocumentWithDocType:(NSString *)docType encoding:(NSStringEncoding)encoding;
+{
+ [self writeString:@"<!DOCTYPE "];
+ [self writeString:docType];
+ [self writeString:@">"];
+ [self startNewline];
+
+ [self setEncoding:encoding];
+}
+
+#pragma mark Characters
+
+- (void)writeCharacters:(NSString *)string;
+{
+ // Quotes are acceptable characters outside of attribute values
+ [self writeStringByEscapingXMLEntities:string escapeQuot:NO];
+}
+
++ (NSString *)stringFromCharacters:(NSString *)string;
+{
+ NSMutableString *result = [NSMutableString string];
+
+ KSXMLWriter *writer = [[self alloc] initWithOutputWriter:result];
+ [writer writeCharacters:string];
+
+ return result;
+}
+
+#pragma mark Elements
+
+- (id)writeElement:(NSString *)elementName contentsInvocationTarget:(id)target;
+{
+ [self startElement:elementName];
+
+ [_contentsProxy ks_prepareWithTarget:target XMLWriter:self];
+ return _contentsProxy;
+}
+
+- (void)writeElement:(NSString *)elementName text:(NSString *)text;
+{
+ [self startElement:elementName attributes:nil];
+ [self writeCharacters:text];
+ [self endElement];
+}
+
+- (void)startElement:(NSString *)elementName;
+{
+ [self startElement:elementName writeInline:[self canWriteElementInline:elementName]];
+}
+
+- (void)startElement:(NSString *)elementName writeInline:(BOOL)writeInline;
+{
+ // Can only write suitable tags inline if containing element also allows it
+ if (!writeInline)
+ {
+ [self startNewline];
+ [self stopWritingInline];
+ }
+
+ // Warn of impending start
+ [self willStartElement:elementName];
+
+ [self writeString:@"<"];
+ [self writeString:elementName];
+
+ // Must do this AFTER writing the string so subclasses can take early action in a -writeString: override
+ [self pushElement:elementName];
+ [self startWritingInline];
+
+
+ // Write attributes
+ [_attributes writeAttributes:self];
+ [_attributes close];
+
+
+ [self didStartElement];
+ [self increaseIndentationLevel];
+}
+
+- (void)startElement:(NSString *)elementName attributes:(NSDictionary *)attributes;
+{
+ for (NSString *aName in attributes)
+ {
+ NSString *aValue = [attributes objectForKey:aName];
+ [self pushAttribute:aName value:aValue];
+ }
+
+ [self startElement:elementName];
+}
+
+- (void)willStartElement:(NSString *)element; { /* for subclassers */ }
+
+- (void)endElement;
+{
+ // Handle whitespace
+ [self decreaseIndentationLevel];
+ if (![self isWritingInline]) [self startNewline]; // was this element written entirely inline?
+
+
+ // Write the tag itself.
+ if (_elementIsEmpty)
+ {
+ [self popElement]; // turn off _elementIsEmpty first or regular start tag will be written!
+ [self closeEmptyElementTag];
+ }
+ else
+ {
+ [self writeEndTag:[self topElement]];
+ [self popElement];
+ }
+}
+
+- (void)pushElement:(NSString *)element;
+{
+ // Private method so that Sandvox can work for now
+ [_openElements addObject:element];
+}
+
+- (void)popElement;
+{
+ _elementIsEmpty = NO;
+
+ [_openElements removeLastObject];
+
+ // Time to cancel inline writing?
+ if (![self isWritingInline]) [self stopWritingInline];
+}
+
+#pragma mark Current Element
+
+- (void)pushAttribute:(NSString *)attribute value:(id)value; // call before -startElement:
+{
+ [_attributes addAttribute:attribute value:value];
+}
+
+- (KSXMLAttributes *)currentAttributes;
+{
+ KSXMLAttributes *result = [_attributes copy];
+ return result;
+}
+
+- (BOOL)hasCurrentAttributes;
+{
+ return [_attributes hasAttributes];
+}
+
+#pragma mark Attributes
+
+- (void)writeAttributeValue:(NSString *)value;
+{
+ // Make sure that we're not double-escaping XML entities
+ NSString *unescapedString = [value stringByUnescapingCrititcalXMLEntities];
+ [self writeStringByEscapingXMLEntities:unescapedString escapeQuot:YES]; // make sure to escape the quote mark
+}
+
++ (NSString *)stringFromAttributeValue:(NSString *)value;
+{
+ NSMutableString *result = [NSMutableString string];
+
+ KSXMLWriter *writer = [[self alloc] initWithOutputWriter:result];
+ [writer writeAttributeValue:value];
+
+ return result;
+}
+
+- (void)writeAttribute:(NSString *)attribute
+ value:(id)value;
+{
+ NSString *valueString = [value description];
+
+ [self writeString:@" "];
+ [self writeString:attribute];
+ if (value != [NSNull null]) {
+ [self writeString:@"=\""];
+ [self writeAttributeValue:valueString];
+ [self writeString:@"\""];
+ }
+}
+
+#pragma mark Whitespace
+
+- (void)startNewline; // writes a newline character and the tabs to match -indentationLevel
+{
+ [self writeString:@"\n"];
+
+ for (int i = 0; i < [self indentationLevel]; i++)
+ {
+ [self writeString:@"\t"];
+ }
+}
+
+#pragma mark Comments
+
+- (void)writeComment:(NSString *)comment; // escapes the string, and wraps in a comment tag
+{
+ [self openComment];
+ [self writeStringByEscapingXMLEntities:comment escapeQuot:YES];
+ [self closeComment];
+}
+
+- (void)openComment;
+{
+ [self writeString:@"<!--"];
+}
+
+- (void)closeComment;
+{
+ [self writeString:@"-->"];
+}
+
+#pragma mark CDATA
+
+- (void)startCDATA;
+{
+ [self writeString:@"<![CDATA["];
+}
+
+- (void)endCDATA;
+{
+ [self writeString:@"]]>"];
+}
+
+#pragma mark Indentation
+
+@synthesize indentationLevel = _indentation;
+
+- (void)increaseIndentationLevel;
+{
+ [self setIndentationLevel:[self indentationLevel] + 1];
+}
+
+- (void)decreaseIndentationLevel;
+{
+ [self setIndentationLevel:[self indentationLevel] - 1];
+}
+
+#pragma mark Validation
+
+- (BOOL)validateElement:(NSString *)element;
+{
+ NSParameterAssert(element);
+ return YES;
+}
+
+- (NSString *)validateAttribute:(NSString *)name value:(NSString *)value ofElement:(NSString *)element;
+{
+ NSParameterAssert(name);
+ NSParameterAssert(element);
+ return value;
+}
+
+#pragma mark Elements Stack
+
+- (BOOL)canWriteElementInline:(NSString *)tagName;
+{
+ // In standard XML, no elements can be inline, unless it's the start of the doc
+ return (_inlineWritingLevel == 0);
+}
+
+- (NSArray *)openElements; { return [_openElements copy]; }
+
+- (NSUInteger)openElementsCount;
+{
+ return [_openElements count];
+}
+
+- (BOOL)hasOpenElement:(NSString *)tagName;
+{
+ // Seek an open element, matching case insensitively
+ for (NSString *anElement in _openElements)
+ {
+ if ([anElement isEqualToString:tagName])
+ {
+ return YES;
+ }
+ }
+
+ return NO;
+}
+
+- (NSString *)topElement;
+{
+ return [_openElements lastObject];
+}
+
+#pragma mark Element Primitives
+
+- (void)didStartElement;
+{
+ // For elements which can't be empty, might as well go ahead and close the start tag now
+ _elementIsEmpty = [self elementCanBeEmpty:[self topElement]];
+ if (!_elementIsEmpty) [self closeStartTag];
+}
+
+- (void)closeStartTag;
+{
+ [self writeString:@">"];
+}
+
+- (void)closeEmptyElementTag; { [self writeString:@" />"]; }
+
+- (void)writeEndTag:(NSString *)tagName; // primitive version that ignores open elements stack
+{
+ [self writeString:@"</"];
+ [self writeString:tagName];
+ [self writeString:@">"];
+}
+
+- (BOOL)elementCanBeEmpty:(NSString *)tagName; { return YES; }
+
+#pragma mark Inline Writing
+
+/*! How it works:
+ *
+ * _inlineWritingLevel records the number of objects in the Elements Stack at the point inline writing began (-startWritingInline).
+ * A value of NSNotFound indicates that we are not writing inline (-stopWritingInline). This MUST be done whenever about to write non-inline content (-openTag: does so automatically).
+ * Finally, if _inlineWritingLevel is 0, this is a special value to indicate we're at the start of the document/section, so the next element to be written is inline, but then normal service shall resume.
+ */
+
+- (BOOL)isWritingInline;
+{
+ return ([self openElementsCount] >= _inlineWritingLevel);
+}
+
+- (void)startWritingInline;
+{
+ // Is it time to switch over to inline writing? (we may already be writing inline, so can ignore request)
+ if (_inlineWritingLevel >= NSNotFound || _inlineWritingLevel == 0)
+ {
+ _inlineWritingLevel = [self openElementsCount];
+ }
+}
+
+- (void)stopWritingInline; { _inlineWritingLevel = NSNotFound; }
+
+static NSCharacterSet *sCharactersToEntityEscapeWithQuot;
+static NSCharacterSet *sCharactersToEntityEscapeWithoutQuot;
+
++ (void)initialize
+{
+ // Cache the characters to be escaped. Doing it in +initialize should be threadsafe
+ if (!sCharactersToEntityEscapeWithQuot)
+ {
+ // Don't want to escape apostrophes for HTML, but do for Javascript
+ sCharactersToEntityEscapeWithQuot = [NSCharacterSet characterSetWithCharactersInString:@"&<>\""];
+ }
+ if (!sCharactersToEntityEscapeWithoutQuot)
+ {
+ sCharactersToEntityEscapeWithoutQuot = [NSCharacterSet characterSetWithCharactersInString:@"&<>"];
+ }
+}
+
+/*! Escape & < > " ... does NOT escape anything else. Need to deal with character set in subsequent pass.
+ Escaping " so that strings work within HTML tags
+ */
+
+// Explicitly escape, or don't escape, double-quots as &quot;
+// Within a tag like <foo attribute="%@"> then we have to escape it.
+// In just about all other contexts it's OK to NOT escape it, but many contexts we don't know if it's OK or not.
+// So I think we want to gradually shift over to being explicit when we know when it's OK or not.
+- (void)writeStringByEscapingXMLEntities:(NSString *)string escapeQuot:(BOOL)escapeQuotes;
+{
+ NSCharacterSet *charactersToEntityEscape = (escapeQuotes ?
+ sCharactersToEntityEscapeWithQuot :
+ sCharactersToEntityEscapeWithoutQuot);
+
+ // Look for characters to escape. If there are none can bail out quick without having had to allocate anything. #78710
+ NSRange searchRange = NSMakeRange(0, [string length]);
+ NSRange range = [string rangeOfCharacterFromSet:charactersToEntityEscape options:0 range:searchRange];
+ if (range.location == NSNotFound) return [self writeString:string];
+
+
+ while (searchRange.length)
+ {
+ // Write characters not needing to be escaped. Don't bother if there aren't any
+ NSRange unescapedRange = searchRange;
+ if (range.location != NSNotFound)
+ {
+ unescapedRange.length = range.location - searchRange.location;
+ }
+ if (unescapedRange.length)
+ {
+ [self writeString:[string substringWithRange:unescapedRange]];
+ }
+
+
+ // Process characters that need escaping
+ if (range.location != NSNotFound)
+ {
+ NSAssert(range.length == 1, @"trying to escaping non-single character string"); // that's all we should deal with for HTML escaping
+
+ unichar ch = [string characterAtIndex:range.location];
+ switch (ch)
+ {
+ case '&': [self writeString:@"&amp;"]; break;
+ case '<': [self writeString:@"&lt;"]; break;
+ case '>': [self writeString:@"&gt;"]; break;
+ case '"': [self writeString:@"&quot;"]; break;
+ default: [self writeString:[NSString stringWithFormat:@"&#%d;",ch]];
+ }
+ }
+ else
+ {
+ break; // no escapable characters were found so we must be done
+ }
+
+
+ // Continue the search
+ searchRange.location = range.location + range.length;
+ searchRange.length = [string length] - searchRange.location;
+ range = [string rangeOfCharacterFromSet:charactersToEntityEscape options:0 range:searchRange];
+ }
+}
+
+#pragma mark String Encoding
+
+@synthesize encoding = _encoding;
+- (void)setEncoding:(NSStringEncoding)encoding;
+{
+ if ( ! ( encoding == NSASCIIStringEncoding
+ || encoding == NSUTF8StringEncoding
+ || encoding == NSISOLatin1StringEncoding
+ || encoding == NSUnicodeStringEncoding ) )
+ {
+ CFStringRef encodingName = CFStringGetNameOfEncoding(CFStringConvertNSStringEncodingToEncoding(encoding));
+
+ [NSException raise:NSInvalidArgumentException
+ format:@"Unsupported character encoding %@ (%u)", encodingName, (unsigned)encoding];
+ }
+
+
+ _encoding = encoding;
+}
+
+- (void)writeString:(NSString *)string;
+{
+ NSParameterAssert(nil != string);
+ // Is this string some element content? If so, the element is no longer empty so must close the tag and mark as such
+ if (_elementIsEmpty && [string length])
+ {
+ _elementIsEmpty = NO; // comes first to avoid infinte recursion
+ [self closeStartTag];
+ }
+
+
+ CFRange range = CFRangeMake(0, CFStringGetLength((__bridge CFStringRef)string));
+
+ while (range.length)
+ {
+ CFIndex written = CFStringGetBytes((__bridge CFStringRef)string,
+ range,
+ CFStringConvertNSStringEncodingToEncoding([self encoding]),
+ 0, // don't convert invalid characters
+ NO,
+ NULL, // not interested in actually getting the bytes
+ 0,
+ NULL);
+
+ if (written < range.length) // there was an invalid character
+ {
+ // Write what is valid
+ if (written)
+ {
+ NSRange validRange = NSMakeRange(range.location, written);
+ [super writeString:[string substringWithRange:validRange]];
+ }
+
+ // Convert the invalid char
+ unichar ch = [string characterAtIndex:(range.location + written)];
+ switch (ch)
+ {
+ // If we encounter a special character with a symbolic entity, use that
+ case 160: [super writeString:@"&nbsp;"]; break;
+ case 169: [super writeString:@"&copy;"]; break;
+ case 174: [super writeString:@"&reg;"]; break;
+ case 8211: [super writeString:@"&ndash;"]; break;
+ case 8212: [super writeString:@"&mdash;"]; break;
+ case 8364: [super writeString:@"&euro;"]; break;
+
+ // Otherwise, use the decimal unicode value.
+ default: [super writeString:[NSString stringWithFormat:@"&#%d;",ch]]; break;
+ }
+
+ // Convert the rest
+ NSUInteger increment = written + 1;
+ range.location += increment; range.length -= increment;
+ }
+ else if (range.location == 0)
+ {
+ // Efficient route for if entire string can be written
+ [super writeString:string];
+ break;
+ }
+ else
+ {
+ // Use CFStringCreateWithSubstring() rather than -substringWithRange: since:
+ // A) Can dispose of it straight away rather than filling autorelease pool
+ // B) range doesn't need casting
+ CFStringRef substring = CFStringCreateWithSubstring(NULL, (__bridge CFStringRef)string, range);
+ [super writeString:(__bridge NSString *)substring];
+ CFRelease(substring);
+
+ break;
+ }
+ }
+}
+
+@end
+
+
+#pragma mark -
+
+
+@implementation KSXMLAttributes (KSXMLWriter)
+
+- (void)writeAttributes:(KSXMLWriter *)writer;
+{
+ for (int i = 0; i < [_attributes count]; i+=2)
+ {
+ NSString *attribute = [_attributes objectAtIndex:i];
+ NSString *value = [_attributes objectAtIndex:i+1];
+ [writer writeAttribute:attribute value:value];
+ }
+}
+
+@end
+
+
+
+#pragma mark -
+
+
+@implementation KSXMLElementContentsProxy
+
+- (void)ks_prepareWithTarget:(id)target XMLWriter:(KSXMLWriter *)writer;
+{
+ NSParameterAssert(writer);
+
+ _target = target;
+ _XMLWriter = writer;
+ _elementsCount = [writer openElementsCount];
+}
+
+- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel
+{
+ return [_target methodSignatureForSelector:sel];
+}
+
+- (void)forwardInvocation:(NSInvocation *)invocation;
+{
+ KSXMLWriter *writer = _XMLWriter; // copy to local vars since invocation may fire off another
+ NSUInteger elementsCount = _elementsCount; // invocation internally, resetting these ivars. #103849
+
+ // Forward on
+ [invocation invokeWithTarget:_target];
+ _target = nil;
+
+ // End element
+ NSAssert([writer openElementsCount] == elementsCount, @"Writing element contents did not end the same number of sub-elements as it started");(void)elementsCount;
+ [writer endElement];
+ _XMLWriter = nil;
+}
+
+@end
+
View
22 evernote-sdk-ios/3rdParty/KSHTMLWriter/LICENSE.txt
@@ -0,0 +1,22 @@
+KSHTMLWriter Copyright (c) 2010, Mike Abdullah and Karelia Software All
+rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met: * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer. *
+Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MIKE ABDULLAH OR
+KARELIA SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
View
23 evernote-sdk-ios/3rdParty/KSHTMLWriter/NSString+XMLAdditions.h
@@ -0,0 +1,23 @@
+//
+// NSString+XMLAdditions.h
+// Evernote
+//
+// Created by Steve White on 10/5/07.
+// Copyright 2007 Evernote Corporation. All rights reserved.
+//
+
+
+#import <Foundation/Foundation.h>
+
+@interface NSString (XMLAdditions)
+
+/**
+ * Escape the standard 5 XML entities: &, <, >, ", '
+ */
+- (NSString *) stringByEscapingCriticalXMLEntities;
+/**
+ * Unescape the standard 5 XML entities: &, <, >, ", '
+ */
+- (NSString *) stringByUnescapingCrititcalXMLEntities;
+
+@end
View
66 evernote-sdk-ios/3rdParty/KSHTMLWriter/NSString+XMLAdditions.m
@@ -0,0 +1,66 @@
+//
+// NSString+XMLAdditions.m
+// Evernote
+//
+// Created by Steve White on 10/5/07.
+// Copyright 2007 Evernote Corporation. All rights reserved.
+//
+
+#import "NSString+XMLAdditions.h"
+
+@implementation NSString (XMLAdditions)
+
+// see .h
+- (NSString *) stringByEscapingCriticalXMLEntities
+{
+ NSMutableString * mutable = [NSMutableString stringWithString:self];
+ [mutable replaceOccurrencesOfString: @"&"
+ withString: @"&amp;"
+ options: NSLiteralSearch
+ range: NSMakeRange(0, mutable.length)];
+ [mutable replaceOccurrencesOfString: @"<"
+ withString: @"&lt;"
+ options: NSLiteralSearch
+ range: NSMakeRange(0, mutable.length)];
+ [mutable replaceOccurrencesOfString: @">"
+ withString: @"&gt;"
+ options: NSLiteralSearch
+ range: NSMakeRange(0, mutable.length)];
+ [mutable replaceOccurrencesOfString: @"'"
+ withString: @"&#x27;"
+ options: NSLiteralSearch
+ range: NSMakeRange(0, mutable.length)];
+ [mutable replaceOccurrencesOfString: @"\""
+ withString: @"&quot;"
+ options: NSLiteralSearch
+ range: NSMakeRange(0, mutable.length)];
+ return mutable;
+}
+
+- (NSString *) stringByUnescapingCrititcalXMLEntities
+{
+ NSMutableString *mutable = [NSMutableString stringWithString:self];
+ [mutable replaceOccurrencesOfString:@"&amp;"
+ withString:@"&"
+ options:NSLiteralSearch
+ range:NSMakeRange(0, mutable.length)];
+ [mutable replaceOccurrencesOfString:@"&lt;"
+ withString:@"<"
+ options:NSLiteralSearch
+ range:NSMakeRange(0, mutable.length)];
+ [mutable replaceOccurrencesOfString:@"&gt;"
+ withString:@">"
+ options:NSLiteralSearch
+ range:NSMakeRange(0, mutable.length)];
+ [mutable replaceOccurrencesOfString:@"&#x27;"
+ withString:@"'"
+ options:NSLiteralSearch
+ range:NSMakeRange(0, mutable.length)];
+ [mutable replaceOccurrencesOfString:@"&quot;"
+ withString:@"\""
+ options:NSLiteralSearch
+ range:NSMakeRange(0, mutable.length)];
+ return mutable;
+};
+
+@end
View
16 evernote-sdk-ios/ENConstants.h
@@ -44,4 +44,20 @@ FOUNDATION_EXPORT NSString * const BootstrapServerBaseURLStringSandbox;
FOUNDATION_EXPORT NSString * const BusinessHostNameSuffix;
+FOUNDATION_EXPORT NSString * const ENMLTagCrypt;
+FOUNDATION_EXPORT NSString * const ENMLTagTodo;
+FOUNDATION_EXPORT NSString * const ENMLTagNote;
+FOUNDATION_EXPORT NSString * const ENHTMLClassInkSlice;
+FOUNDATION_EXPORT NSString * const ENHTMLClassInkContainer;
+FOUNDATION_EXPORT NSString * const ENHTMLClassIgnore;
+FOUNDATION_EXPORT NSString * const ENHTMLClassAttachment;
+
+FOUNDATION_EXPORT NSString * const ENHTMLAttributeMime;
+
+FOUNDATION_EXPORT NSString * const ENHTMLEncryptionAttributeHint;
+FOUNDATION_EXPORT NSString * const ENHTMLEncryptionAttributeCipher;
+
+FOUNDATION_EXPORT NSString * const ENMIMETypeOctetStream;
+FOUNDATION_EXPORT NSString * const ENMLTagMedia;
+
@end
View
17 evernote-sdk-ios/ENConstants.m
@@ -43,4 +43,21 @@ @implementation ENConstants
NSString * const BusinessHostNameSuffix = @"-business";
+NSString * const ENMLTagCrypt = @"en-crypt";
+NSString * const ENMLTagTodo = @"en-todo";
+NSString * const ENMLTagNote = @"en-note";
+NSString * const ENHTMLClassInkSlice = @"en-ink-slice";
+NSString * const ENHTMLClassInkContainer = @"en-ink-media";
+
+NSString * const ENHTMLClassIgnore = @"en-ignore";
+NSString * const ENHTMLClassAttachment = @"en-attachment";
+
+NSString * const ENHTMLAttributeMime = @"x-evernote-mime";
+
+NSString * const ENHTMLEncryptionAttributeHint = @"title";
+NSString * const ENHTMLEncryptionAttributeCipher = @"alt";
+
+NSString * const ENMIMETypeOctetStream = @"application/octet-stream";
+NSString * const ENMLTagMedia = @"en-media";
+
@end
View
20 evernote-sdk-ios/Utilities/ENMLUtility.h
@@ -28,10 +28,11 @@
*/
#import <Foundation/Foundation.h>
+#import "KSHTMLWriter.h"
/** Utility methods to work with ENML.
*/
-@interface ENMLUtility : NSObject
+@interface ENMLUtility : NSObject <NSXMLParserDelegate>
/** Utility function to create an enml media tag.
@@ -41,4 +42,21 @@
+ (NSString*) mediaTagWithDataHash:(NSData *)dataHash
mime:(NSString *)mime;
+
+/** Utility function to convert ENML to HTML.
+
+ @param enmlContent The enml content of the note
+ @param block The completion block that will be called on completion
+ */
+- (void) convertENMLToHTML:(NSString*)enmlContent completionBlock:(void(^)(NSString* html, NSError *error))block;
+
+
+/** Utility function to convert ENML to HTML.
+
+ @param enmlContent The enml content of the note
+ @param resources The resources array
+ @param block The completion block that will be called on completion
+ */
+- (void) convertENMLToHTML:(NSString*)enmlContent withResources:(NSArray*)resources completionBlock:(void(^)(NSString* html, NSError *error))block;
+
@end
View
153 evernote-sdk-ios/Utilities/ENMLUtility.m
@@ -29,16 +29,29 @@
#import "ENMLUtility.h"
#import "NSData+EvernoteSDK.h"
+#import "EvernoteSDK.h"
+#import "KSHTMLWriter.h"
+#import "NSDataBase64Additions.h"
-NSString * const ENMIMETypeOctetStream = @"application/octet-stream";
-NSString * const ENMLTagMedia = @"en-media";
+
+typedef void (^ENMLHTMLCompletionBlock)(NSString* html, NSError *error);
+
+
+@interface ENMLUtility ()
+
+@property (nonatomic,strong) NSMutableString* outputHTML;
+@property (nonatomic,strong) KSHTMLWriter* htmlWriter;
+@property (nonatomic,strong) NSArray* resources;
+@property (nonatomic,copy) ENMLHTMLCompletionBlock completionBlock;
+@property (nonatomic,strong) NSXMLParser* xmlParser;
+
+@end
@implementation ENMLUtility
+ (NSString*) mediaTagWithDataHash:(NSData *)dataHash
mime:(NSString *)mime
{
-
if (mime == nil) {
mime = ENMIMETypeOctetStream;
}
@@ -50,4 +63,138 @@ + (NSString*) mediaTagWithDataHash:(NSData *)dataHash
return mediaTag;
}
+- (void) convertENMLToHTML:(NSString*)enmlContent completionBlock:(void(^)(NSString* html, NSError *error))block {
+ [self convertENMLToHTML:enmlContent withResources:nil completionBlock:block];
+}
+
+
+- (void) convertENMLToHTML:(NSString*)enmlContent withResources:(NSArray*)resources completionBlock:(void(^)(NSString* html, NSError *error))block {
+ self.xmlParser = [[NSXMLParser alloc] initWithData:[enmlContent dataUsingEncoding:NSUTF8StringEncoding]];
+ self.outputHTML = [NSMutableString string];
+ self.htmlWriter = [[KSHTMLWriter alloc] initWithOutputWriter:self.outputHTML];
+ [self.xmlParser setDelegate:self];
+ self.resources = resources;
+ self.completionBlock = block;
+ dispatch_async(dispatch_get_global_queue(0, 0), ^{
+ [self.xmlParser parse];
+ });
+}
+
+#pragma mark -
+#pragma NSXMLParser delegate functions
+
+- (void)parserDidEndDocument:(NSXMLParser *)parser {
+ [self.htmlWriter close];
+ self.completionBlock(self.outputHTML,nil);
+}
+
+- (void) parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError {
+ self.completionBlock(nil,parseError);
+}
+
+- (void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
+ if([elementName isEqualToString:ENMLTagNote]) {
+ [self.htmlWriter startElement:@"body"];
+ }
+ else if([elementName isEqualToString:ENMLTagTodo]) {
+ if([attributeDict[@"checked"] isEqualToString:@"true"]) {
+ [self.htmlWriter startElement:@"input" attributes:@{@"disabled": @"true",@"type":@"checkbox",@"checked":@"true"}];
+ }
+ else {
+ [self.htmlWriter startElement:@"input" attributes:@{@"disabled": @"true",@"type":@"checkbox"}];
+ }
+ }
+ else if([elementName isEqualToString:ENMLTagMedia] && self.resources) {
+ NSString *mediaHash = [attributeDict objectForKey:@"hash"];
+ NSData* dataHash = [NSData dataWithHexDigits:mediaHash];
+ EDAMResource *foundResource = nil;
+ for (EDAMResource* resource in self.resources) {
+ if([[[resource data] bodyHash] isEqualToData:dataHash]) {
+ foundResource = resource;
+ }
+ }
+ NSMutableDictionary *scrubbedAttributes = [NSMutableDictionary dictionaryWithDictionary:attributeDict];
+ [scrubbedAttributes removeObjectForKey:@"hash"];
+ [scrubbedAttributes removeObjectForKey:@"type"];
+ [self writeResource:foundResource withAttributes:scrubbedAttributes];
+ }
+ else {
+ [self.htmlWriter startElement:elementName];
+ }
+
+}
+
+- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
+ [self.htmlWriter endElement];
+}
+
+- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
+ [self.htmlWriter writeCharacters:string];
+}
+
+- (void)parser:(NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock {
+ [self.htmlWriter startCDATA];
+ [self.htmlWriter writeString:[[NSString alloc] initWithData:CDATABlock encoding:NSUTF8StringEncoding]];
+ [self.htmlWriter endCDATA];
+}
+
+- (void)parser:(NSXMLParser *)parser foundComment:(NSString *)comment {
+ [self.htmlWriter writeComment:comment];
+}
+
+#pragma mark -
+#pragma Internal functions
+
+- (void) writeResource:(EDAMResource*)resource
+ withAttributes:(NSDictionary *)attributes
+{
+ if (resource == nil) {
+ return;
+ }
+ NSString *mime = [resource mime];
+
+ NSMutableDictionary *scrubbedAttributes = [NSMutableDictionary dictionaryWithDictionary:attributes];
+
+ if ([mime hasPrefix:@"image/"] == YES) {
+ [self writeImageTagForResource:resource
+ withAttributes:scrubbedAttributes];
+ }
+ else {