commit 3f0bc2ba58901473f99a2be5a9c4f452e12db532 Author: GRMrGecko Date: Sat Sep 13 17:13:32 2014 -0500 EmailScheduler Start. diff --git a/EmailScheduler.xcodeproj/project.pbxproj b/EmailScheduler.xcodeproj/project.pbxproj new file mode 100644 index 0000000..2e6e43a --- /dev/null +++ b/EmailScheduler.xcodeproj/project.pbxproj @@ -0,0 +1,431 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXAggregateTarget section */ + 2A452C8119C476C30095EEF6 /* Build Directory */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 2A452C8219C476C30095EEF6 /* Build configuration list for PBXAggregateTarget "Build Directory" */; + buildPhases = ( + 2A452C8519C476C60095EEF6 /* ShellScript */, + ); + dependencies = ( + ); + name = "Build Directory"; + productName = "Build Directory"; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 2A452C7019C475790095EEF6 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2A452C6F19C475790095EEF6 /* Foundation.framework */; }; + 2A452C7319C475790095EEF6 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A452C7219C475790095EEF6 /* main.m */; }; + 2A452C7719C475790095EEF6 /* EmailScheduler.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 2A452C7619C475790095EEF6 /* EmailScheduler.1 */; }; + 2A452C7E19C476900095EEF6 /* MailCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2A452C7D19C476900095EEF6 /* MailCore.framework */; }; + 2A452C8019C476A40095EEF6 /* MailCore.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 2A452C7D19C476900095EEF6 /* MailCore.framework */; }; + 2A452C8A19C4776A0095EEF6 /* MGMController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A452C8919C4776A0095EEF6 /* MGMController.m */; }; + 2A452C9719C479030095EEF6 /* MGMHTTPAddons.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A452C8D19C479030095EEF6 /* MGMHTTPAddons.m */; }; + 2A452C9819C479030095EEF6 /* MGMHTTPClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A452C8F19C479030095EEF6 /* MGMHTTPClient.m */; }; + 2A452C9A19C479030095EEF6 /* MGMHTTPResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A452C9419C479030095EEF6 /* MGMHTTPResponse.m */; }; + 2A452C9B19C479030095EEF6 /* MGMHTTPServer.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A452C9619C479030095EEF6 /* MGMHTTPServer.m */; }; + 2A452C9E19C47A160095EEF6 /* AsyncSocket.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A452C9D19C47A160095EEF6 /* AsyncSocket.m */; }; + 2A452CA119C47B7D0095EEF6 /* MGMHTTPClientClass.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A452CA019C47B7D0095EEF6 /* MGMHTTPClientClass.m */; }; + 2A452CA519C481C70095EEF6 /* MGMJSON.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A452CA419C481C70095EEF6 /* MGMJSON.m */; }; + 2A452CA819C4850A0095EEF6 /* MGMEmail.m in Sources */ = {isa = PBXBuildFile; fileRef = 2A452CA719C4850A0095EEF6 /* MGMEmail.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 2A452C8619C476D70095EEF6 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 2A452C6419C475790095EEF6 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 2A452C8119C476C30095EEF6; + remoteInfo = "Build Directory"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 2A452C6A19C475790095EEF6 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + 2A452C7719C475790095EEF6 /* EmailScheduler.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; + 2A452C7F19C4769D0095EEF6 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 2A452C8019C476A40095EEF6 /* MailCore.framework in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 2A452C6C19C475790095EEF6 /* EmailScheduler */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = EmailScheduler; sourceTree = BUILT_PRODUCTS_DIR; }; + 2A452C6F19C475790095EEF6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 2A452C7219C475790095EEF6 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 2A452C7519C475790095EEF6 /* EmailScheduler-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "EmailScheduler-Prefix.pch"; sourceTree = ""; }; + 2A452C7619C475790095EEF6 /* EmailScheduler.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = EmailScheduler.1; sourceTree = ""; }; + 2A452C7D19C476900095EEF6 /* MailCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = MailCore.framework; sourceTree = ""; }; + 2A452C8819C4776A0095EEF6 /* MGMController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGMController.h; sourceTree = ""; }; + 2A452C8919C4776A0095EEF6 /* MGMController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGMController.m; sourceTree = ""; }; + 2A452C8C19C479030095EEF6 /* MGMHTTPAddons.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGMHTTPAddons.h; sourceTree = ""; }; + 2A452C8D19C479030095EEF6 /* MGMHTTPAddons.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGMHTTPAddons.m; sourceTree = ""; }; + 2A452C8E19C479030095EEF6 /* MGMHTTPClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGMHTTPClient.h; sourceTree = ""; }; + 2A452C8F19C479030095EEF6 /* MGMHTTPClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGMHTTPClient.m; sourceTree = ""; }; + 2A452C9219C479030095EEF6 /* MGMHTTPDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGMHTTPDefines.h; sourceTree = ""; }; + 2A452C9319C479030095EEF6 /* MGMHTTPResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGMHTTPResponse.h; sourceTree = ""; }; + 2A452C9419C479030095EEF6 /* MGMHTTPResponse.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGMHTTPResponse.m; sourceTree = ""; }; + 2A452C9519C479030095EEF6 /* MGMHTTPServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGMHTTPServer.h; sourceTree = ""; }; + 2A452C9619C479030095EEF6 /* MGMHTTPServer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGMHTTPServer.m; sourceTree = ""; }; + 2A452C9C19C47A160095EEF6 /* AsyncSocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AsyncSocket.h; sourceTree = ""; }; + 2A452C9D19C47A160095EEF6 /* AsyncSocket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AsyncSocket.m; sourceTree = ""; }; + 2A452C9F19C47B7D0095EEF6 /* MGMHTTPClientClass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGMHTTPClientClass.h; sourceTree = ""; }; + 2A452CA019C47B7D0095EEF6 /* MGMHTTPClientClass.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGMHTTPClientClass.m; sourceTree = ""; }; + 2A452CA319C481C70095EEF6 /* MGMJSON.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGMJSON.h; sourceTree = ""; }; + 2A452CA419C481C70095EEF6 /* MGMJSON.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGMJSON.m; sourceTree = ""; }; + 2A452CA619C4850A0095EEF6 /* MGMEmail.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGMEmail.h; sourceTree = ""; }; + 2A452CA719C4850A0095EEF6 /* MGMEmail.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGMEmail.m; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 2A452C6919C475790095EEF6 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 2A452C7E19C476900095EEF6 /* MailCore.framework in Frameworks */, + 2A452C7019C475790095EEF6 /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 2A452C6319C475790095EEF6 = { + isa = PBXGroup; + children = ( + 2A452C7D19C476900095EEF6 /* MailCore.framework */, + 2A452C7119C475790095EEF6 /* EmailScheduler */, + 2A452C6E19C475790095EEF6 /* Frameworks */, + 2A452C6D19C475790095EEF6 /* Products */, + ); + sourceTree = ""; + }; + 2A452C6D19C475790095EEF6 /* Products */ = { + isa = PBXGroup; + children = ( + 2A452C6C19C475790095EEF6 /* EmailScheduler */, + ); + name = Products; + sourceTree = ""; + }; + 2A452C6E19C475790095EEF6 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 2A452C6F19C475790095EEF6 /* Foundation.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 2A452C7119C475790095EEF6 /* EmailScheduler */ = { + isa = PBXGroup; + children = ( + 2A452C7219C475790095EEF6 /* main.m */, + 2A452C7619C475790095EEF6 /* EmailScheduler.1 */, + 2A452C7419C475790095EEF6 /* Supporting Files */, + 2A452CA219C481C70095EEF6 /* JSON */, + 2A452C8B19C479030095EEF6 /* MGMHTTP */, + 2A452C8819C4776A0095EEF6 /* MGMController.h */, + 2A452C8919C4776A0095EEF6 /* MGMController.m */, + 2A452C9F19C47B7D0095EEF6 /* MGMHTTPClientClass.h */, + 2A452CA019C47B7D0095EEF6 /* MGMHTTPClientClass.m */, + 2A452CA619C4850A0095EEF6 /* MGMEmail.h */, + 2A452CA719C4850A0095EEF6 /* MGMEmail.m */, + ); + path = EmailScheduler; + sourceTree = ""; + }; + 2A452C7419C475790095EEF6 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 2A452C7519C475790095EEF6 /* EmailScheduler-Prefix.pch */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 2A452C8B19C479030095EEF6 /* MGMHTTP */ = { + isa = PBXGroup; + children = ( + 2A452C9C19C47A160095EEF6 /* AsyncSocket.h */, + 2A452C9D19C47A160095EEF6 /* AsyncSocket.m */, + 2A452C8C19C479030095EEF6 /* MGMHTTPAddons.h */, + 2A452C8D19C479030095EEF6 /* MGMHTTPAddons.m */, + 2A452C8E19C479030095EEF6 /* MGMHTTPClient.h */, + 2A452C8F19C479030095EEF6 /* MGMHTTPClient.m */, + 2A452C9219C479030095EEF6 /* MGMHTTPDefines.h */, + 2A452C9319C479030095EEF6 /* MGMHTTPResponse.h */, + 2A452C9419C479030095EEF6 /* MGMHTTPResponse.m */, + 2A452C9519C479030095EEF6 /* MGMHTTPServer.h */, + 2A452C9619C479030095EEF6 /* MGMHTTPServer.m */, + ); + path = MGMHTTP; + sourceTree = ""; + }; + 2A452CA219C481C70095EEF6 /* JSON */ = { + isa = PBXGroup; + children = ( + 2A452CA319C481C70095EEF6 /* MGMJSON.h */, + 2A452CA419C481C70095EEF6 /* MGMJSON.m */, + ); + path = JSON; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 2A452C6B19C475790095EEF6 /* EmailScheduler */ = { + isa = PBXNativeTarget; + buildConfigurationList = 2A452C7A19C475790095EEF6 /* Build configuration list for PBXNativeTarget "EmailScheduler" */; + buildPhases = ( + 2A452C6819C475790095EEF6 /* Sources */, + 2A452C6919C475790095EEF6 /* Frameworks */, + 2A452C6A19C475790095EEF6 /* CopyFiles */, + 2A452C7F19C4769D0095EEF6 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + 2A452C8719C476D70095EEF6 /* PBXTargetDependency */, + ); + name = EmailScheduler; + productName = EmailScheduler; + productReference = 2A452C6C19C475790095EEF6 /* EmailScheduler */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 2A452C6419C475790095EEF6 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0510; + ORGANIZATIONNAME = "Mr. Gecko's Media"; + }; + buildConfigurationList = 2A452C6719C475790095EEF6 /* Build configuration list for PBXProject "EmailScheduler" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 2A452C6319C475790095EEF6; + productRefGroup = 2A452C6D19C475790095EEF6 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 2A452C6B19C475790095EEF6 /* EmailScheduler */, + 2A452C8119C476C30095EEF6 /* Build Directory */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXShellScriptBuildPhase section */ + 2A452C8519C476C60095EEF6 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "#!/bin/bash\n#\n# Build Directory\n#\n# Created by Mr. Gecko on 4/21/11.\n# No Copyright Claimed. Public Domain.\n#\n# DISCLAIMER: This script is provided as-is. I am not responsible if this script somehow causes harm to you or your system in any way, I am providing this for free in hope that it will of use to someone. I WILL NOT pay you any amount of money if anything happen to your data or you because of the changes this script makes nor am I obligated to help you fix issues this causes.\n#\n\nif [ \"$SRCROOT/build\" != \"$SYMROOT\" ]; then\n if [ -d \"$SRCROOT/build\" ]; then\n /bin/rm -Rf \"$SRCROOT/build\"\n fi\n /bin/ln -fs \"$SYMROOT\" \"$SRCROOT/build\"\nfi"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 2A452C6819C475790095EEF6 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 2A452C9A19C479030095EEF6 /* MGMHTTPResponse.m in Sources */, + 2A452C7319C475790095EEF6 /* main.m in Sources */, + 2A452CA819C4850A0095EEF6 /* MGMEmail.m in Sources */, + 2A452C9B19C479030095EEF6 /* MGMHTTPServer.m in Sources */, + 2A452C8A19C4776A0095EEF6 /* MGMController.m in Sources */, + 2A452C9819C479030095EEF6 /* MGMHTTPClient.m in Sources */, + 2A452CA519C481C70095EEF6 /* MGMJSON.m in Sources */, + 2A452CA119C47B7D0095EEF6 /* MGMHTTPClientClass.m in Sources */, + 2A452C9719C479030095EEF6 /* MGMHTTPAddons.m in Sources */, + 2A452C9E19C47A160095EEF6 /* AsyncSocket.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 2A452C8719C476D70095EEF6 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 2A452C8119C476C30095EEF6 /* Build Directory */; + targetProxy = 2A452C8619C476D70095EEF6 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 2A452C7819C475790095EEF6 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.9; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 2A452C7919C475790095EEF6 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.9; + SDKROOT = macosx; + }; + name = Release; + }; + 2A452C7B19C475790095EEF6 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_OBJC_ARC = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "EmailScheduler/EmailScheduler-Prefix.pch"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 2A452C7C19C475790095EEF6 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_OBJC_ARC = NO; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "EmailScheduler/EmailScheduler-Prefix.pch"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 2A452C8319C476C30095EEF6 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 2A452C8419C476C30095EEF6 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 2A452C6719C475790095EEF6 /* Build configuration list for PBXProject "EmailScheduler" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2A452C7819C475790095EEF6 /* Debug */, + 2A452C7919C475790095EEF6 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 2A452C7A19C475790095EEF6 /* Build configuration list for PBXNativeTarget "EmailScheduler" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2A452C7B19C475790095EEF6 /* Debug */, + 2A452C7C19C475790095EEF6 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 2A452C8219C476C30095EEF6 /* Build configuration list for PBXAggregateTarget "Build Directory" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 2A452C8319C476C30095EEF6 /* Debug */, + 2A452C8419C476C30095EEF6 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = 2A452C6419C475790095EEF6 /* Project object */; +} diff --git a/EmailScheduler.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/EmailScheduler.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..f892f0c --- /dev/null +++ b/EmailScheduler.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/EmailScheduler.xcodeproj/project.xcworkspace/xcuserdata/grmrgecko.xcuserdatad/UserInterfaceState.xcuserstate b/EmailScheduler.xcodeproj/project.xcworkspace/xcuserdata/grmrgecko.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..38b1fb8 Binary files /dev/null and b/EmailScheduler.xcodeproj/project.xcworkspace/xcuserdata/grmrgecko.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/EmailScheduler.xcodeproj/xcuserdata/grmrgecko.xcuserdatad/xcschemes/Build Directory.xcscheme b/EmailScheduler.xcodeproj/xcuserdata/grmrgecko.xcuserdatad/xcschemes/Build Directory.xcscheme new file mode 100644 index 0000000..c98757a --- /dev/null +++ b/EmailScheduler.xcodeproj/xcuserdata/grmrgecko.xcuserdatad/xcschemes/Build Directory.xcscheme @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/EmailScheduler.xcodeproj/xcuserdata/grmrgecko.xcuserdatad/xcschemes/EmailScheduler.xcscheme b/EmailScheduler.xcodeproj/xcuserdata/grmrgecko.xcuserdatad/xcschemes/EmailScheduler.xcscheme new file mode 100644 index 0000000..f211b2d --- /dev/null +++ b/EmailScheduler.xcodeproj/xcuserdata/grmrgecko.xcuserdatad/xcschemes/EmailScheduler.xcscheme @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/EmailScheduler.xcodeproj/xcuserdata/grmrgecko.xcuserdatad/xcschemes/xcschememanagement.plist b/EmailScheduler.xcodeproj/xcuserdata/grmrgecko.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..42b3b8b --- /dev/null +++ b/EmailScheduler.xcodeproj/xcuserdata/grmrgecko.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,32 @@ + + + + + SchemeUserState + + Build Directory.xcscheme + + orderHint + 1 + + EmailScheduler.xcscheme + + orderHint + 0 + + + SuppressBuildableAutocreation + + 2A452C6B19C475790095EEF6 + + primary + + + 2A452C8119C476C30095EEF6 + + primary + + + + + diff --git a/EmailScheduler/EmailScheduler-Prefix.pch b/EmailScheduler/EmailScheduler-Prefix.pch new file mode 100644 index 0000000..37fdbe6 --- /dev/null +++ b/EmailScheduler/EmailScheduler-Prefix.pch @@ -0,0 +1,9 @@ +// +// Prefix header +// +// The contents of this file are implicitly included at the beginning of every source file. +// + +#ifdef __OBJC__ + #import +#endif diff --git a/EmailScheduler/EmailScheduler.1 b/EmailScheduler/EmailScheduler.1 new file mode 100644 index 0000000..257ed31 --- /dev/null +++ b/EmailScheduler/EmailScheduler.1 @@ -0,0 +1,79 @@ +.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples. +.\"See Also: +.\"man mdoc.samples for a complete listing of options +.\"man mdoc for the short list of editing options +.\"/usr/share/misc/mdoc.template +.Dd 9/13/14 \" DATE +.Dt EmailScheduler 1 \" Program name and manual section number +.Os Darwin +.Sh NAME \" Section Header - required - don't modify +.Nm EmailScheduler, +.\" The following lines are read in generating the apropos(man -k) database. Use only key +.\" words here as the database is built based on the words here and in the .ND line. +.Nm Other_name_for_same_program(), +.Nm Yet another name for the same program. +.\" Use .Nm macro to designate other names for the documented program. +.Nd This line parsed for whatis database. +.Sh SYNOPSIS \" Section Header - required - don't modify +.Nm +.Op Fl abcd \" [-abcd] +.Op Fl a Ar path \" [-a path] +.Op Ar file \" [file] +.Op Ar \" [file ...] +.Ar arg0 \" Underlined argument - use .Ar anywhere to underline +arg2 ... \" Arguments +.Sh DESCRIPTION \" Section Header - required - don't modify +Use the .Nm macro to refer to your program throughout the man page like such: +.Nm +Underlining is accomplished with the .Ar macro like this: +.Ar underlined text . +.Pp \" Inserts a space +A list of items with descriptions: +.Bl -tag -width -indent \" Begins a tagged list +.It item a \" Each item preceded by .It macro +Description of item a +.It item b +Description of item b +.El \" Ends the list +.Pp +A list of flags and their descriptions: +.Bl -tag -width -indent \" Differs from above in tag removed +.It Fl a \"-a flag as a list item +Description of -a flag +.It Fl b +Description of -b flag +.El \" Ends the list +.Pp +.\" .Sh ENVIRONMENT \" May not be needed +.\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1 +.\" .It Ev ENV_VAR_1 +.\" Description of ENV_VAR_1 +.\" .It Ev ENV_VAR_2 +.\" Description of ENV_VAR_2 +.\" .El +.Sh FILES \" File used or created by the topic of the man page +.Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact +.It Pa /usr/share/file_name +FILE_1 description +.It Pa /Users/joeuser/Library/really_long_file_name +FILE_2 description +.El \" Ends the list +.\" .Sh DIAGNOSTICS \" May not be needed +.\" .Bl -diag +.\" .It Diagnostic Tag +.\" Diagnostic informtion here. +.\" .It Diagnostic Tag +.\" Diagnostic informtion here. +.\" .El +.Sh SEE ALSO +.\" List links in ascending order by section, alphabetically within a section. +.\" Please do not reference files that do not exist without filing a bug report +.Xr a 1 , +.Xr b 1 , +.Xr c 1 , +.Xr a 2 , +.Xr b 2 , +.Xr a 3 , +.Xr b 3 +.\" .Sh BUGS \" Document known, unremedied bugs +.\" .Sh HISTORY \" Document history if command behaves in a unique manner \ No newline at end of file diff --git a/EmailScheduler/JSON/MGMJSON.h b/EmailScheduler/JSON/MGMJSON.h new file mode 100644 index 0000000..579603c --- /dev/null +++ b/EmailScheduler/JSON/MGMJSON.h @@ -0,0 +1,76 @@ +// +// MGMJSON.h +// MGMUsers +// +// Created by Mr. Gecko on 7/31/10. +// Copyright (c) 2014 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +#import + +@interface NSString (MGMJSON) +- (id)parseJSON; +- (NSString *)JSONValue; +@end +@interface NSData (MGMJSON) +- (id)parseJSON; +@end +@interface NSNumber (MGMJSON) +- (NSString *)JSONValue; +@end +@interface NSNull (MGMJSON) +- (NSString *)JSONValue; +@end +@interface NSDictionary (MGMJSON) +- (NSString *)JSONValue; +@end +@interface NSArray (MGMJSON) +- (NSString *)JSONValue; +@end + +@interface MGMJSON : NSObject { +@private + NSMutableCharacterSet *escapeSet; + NSString *JSONString; + unsigned long position; + unsigned long length; +} +- (id)initWithString:(NSString *)theString; +- (id)parse; +- (void)skipWhitespace; +- (void)skipDigits; +- (id)parseForObject; +- (NSDictionary *)parseForDictionary; +- (NSArray *)parseForArray; +- (NSString *)parseForString; +- (unichar)parseForUnicodeChar; +- (NSNumber *)parseForYES; +- (id)parseForNONULL; +- (NSNumber *)parseForNumber; + +- (NSString *)convert:(id)theObject; +- (NSString *)writeString:(NSString *)theString; +- (NSString *)writeNumber:(NSNumber *)theNumber; +- (NSString *)writeBool:(NSNumber *)theNumber; +- (NSString *)writeNull:(NSNull *)theNull; +- (NSString *)writeDictionary:(NSDictionary *)theDictionary; +- (NSString *)writeArray:(NSArray *)theArray; +@end \ No newline at end of file diff --git a/EmailScheduler/JSON/MGMJSON.m b/EmailScheduler/JSON/MGMJSON.m new file mode 100644 index 0000000..f836ac2 --- /dev/null +++ b/EmailScheduler/JSON/MGMJSON.m @@ -0,0 +1,542 @@ +// +// MGMJSON.m +// MGMUsers +// +// Created by Mr. Gecko on 7/31/10. +// Copyright (c) 2014 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +#import "MGMJSON.h" + +@implementation NSString (MGMJSON) +- (id)parseJSON { + MGMJSON *parser = [[MGMJSON alloc] initWithString:self]; + id object = [parser parse]; + [parser release]; + return object; +} +- (NSString *)JSONValue { + MGMJSON *writer = [[MGMJSON alloc] init]; + NSString *value = [writer convert:self]; + [writer release]; + return value; +} +@end +@implementation NSData (MGMJSON) +- (id)parseJSON { + NSString *string = [[NSString alloc] initWithData:self encoding:NSUTF8StringEncoding]; + MGMJSON *parser = [[MGMJSON alloc] initWithString:string]; + [string release]; + id object = [parser parse]; + [parser release]; + return object; +} +@end +@implementation NSNumber (MGMJSON) +- (NSString *)JSONValue { + MGMJSON *writer = [[MGMJSON alloc] init]; + NSString *value = [writer convert:self]; + [writer release]; + return value; +} +@end +@implementation NSNull (MGMJSON) +- (NSString *)JSONValue { + MGMJSON *writer = [[MGMJSON alloc] init]; + NSString *value = [writer convert:self]; + [writer release]; + return value; +} +@end +@implementation NSDictionary (MGMJSON) +- (NSString *)JSONValue { + MGMJSON *writer = [[MGMJSON alloc] init]; + NSString *value = [writer convert:self]; + [writer release]; + return value; +} +@end +@implementation NSArray (MGMJSON) +- (NSString *)JSONValue { + MGMJSON *writer = [[MGMJSON alloc] init]; + NSString *value = [writer convert:self]; + [writer release]; + return value; +} +@end + + +@implementation MGMJSON +- (id)init { + if ((self = [super init])) { + escapeSet = [[NSMutableCharacterSet characterSetWithRange:NSMakeRange(0,32)] retain]; + [escapeSet addCharactersInString:@"\"\\"]; + } + return self; +} +- (id)initWithString:(NSString *)theString { + if ((self = [super init])) { + JSONString = [theString retain]; + length = [JSONString length]; + } + return self; +} +- (void)dealloc { + [escapeSet release]; + [JSONString release]; + [super dealloc]; +} + +- (id)parse { + position = 0; + if ([JSONString isEqual:@""]) + return nil; + return [self parseForObject]; +} +- (void)skipWhitespace { + NSCharacterSet *set = [NSCharacterSet whitespaceAndNewlineCharacterSet]; + while (positionlength) { + NSLog(@"JSON: Unexpected end of input."); + return 0x0; + } + int len = 0; + NSMutableString *hexValue = [NSMutableString string]; + [hexValue appendString:@"0x"]; + while (position + +@class MGMHTTPServer, MGMEmail; + +@interface MGMController : NSObject { + MGMHTTPServer *server; + NSDictionary *emailAddresses; + NSMutableArray *queue; + BOOL sendingEmail; +} ++ (id)sharedController; +- (NSDictionary *)emailAddresses; +- (void)addToQueue:(MGMEmail *)email; +@end diff --git a/EmailScheduler/MGMController.m b/EmailScheduler/MGMController.m new file mode 100644 index 0000000..9334573 --- /dev/null +++ b/EmailScheduler/MGMController.m @@ -0,0 +1,137 @@ +// +// MGMController.m +// EmailScheduler +// +// Created by James Coleman on 9/13/14. +// Copyright (c) 2014 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +#import "MGMController.h" +#import "MGMHTTP/MGMHTTPServer.h" +#import "MGMHTTP/MGMHTTPClient.h" +#import "MGMHTTP/MGMHTTPResponse.h" +#import "MGMHTTPClientClass.h" +#import "MGMEmail.h" +#import + +static MGMController *controller; + +@implementation MGMController +- (id)init { + if ((self = [super init])) { + controller = self; + server = [[MGMHTTPServer serverWithPort:28001 delegate:self] retain]; + [server setHTTPClientClass:[MGMHTTPClientClass class]]; + NSError *error = nil; + if (![server start:&error]) { + NSLog(@"Error: %@", error); + } + emailAddresses = [[NSDictionary dictionaryWithObjectsAndKeys:nil] retain]; + + queue = [NSMutableArray new]; + sendingEmail = NO; + } + return self; +} ++ (id)sharedController { + return controller; +} +- (NSDictionary *)emailAddresses { + return emailAddresses; +} +- (void)addToQueue:(MGMEmail *)email { + @synchronized(queue) { + [queue addObject:email]; + if (!sendingEmail) { + sendingEmail = YES; + [NSThread detachNewThreadSelector:@selector(sendNextEmail) toTarget:self withObject:nil]; + } + } +} +- (void)sendNextEmail { + NSAutoreleasePool *pool = [NSAutoreleasePool new]; + MGMEmail *email = nil; + @synchronized(queue) { + email = [queue objectAtIndex:0]; + } + + MCOSMTPSession *smtpSession = [email session]; + MCOSMTPSendOperation *sendOperation = [smtpSession sendOperationWithData:[email rfc822Data]]; + [sendOperation start:^(NSError *error) { + if(error) { + NSLog(@"Error sending email: %@", error); + } else { + NSLog(@"Successfully sent email!"); + } + }]; + + if ([[email eamilAddress] isEqual:@"password@birdim.com"]) {//Email address to automatically delete email for. Make sure gmail has a filter to move sent email to trash. + MCOIMAPSession *session = [email imapSession]; + + MCOIndexSet *uidSet = [MCOIndexSet indexSetWithRange:MCORangeMake(1,UINT64_MAX)]; + MCOIMAPFetchMessagesOperation *fetchOp = [session fetchMessagesByUIDOperationWithFolder:@"[Gmail]/Trash" + requestKind:MCOIMAPMessagesRequestKindHeaders + uids:uidSet]; + + [fetchOp start:^(NSError *err, NSArray *msgs, MCOIndexSet *vanished) { + for (MCOIMAPMessage *message in msgs) { + MCOMessageFlag flags = MCOMessageFlagDeleted; + BOOL deleted = flags & MCOMessageFlagDeleted; + + MCOIMAPOperation *op = [session storeFlagsOperationWithFolder:@"[Gmail]/Trash" + uids:[MCOIndexSet indexSetWithIndex:[message gmailThreadID]] + kind:MCOIMAPStoreFlagsRequestKindSet + flags:flags]; + [op start:^(NSError * error) { + if(!error) { + NSLog(@"Updated flags!"); + } else { + NSLog(@"Error updating flags: %@", error); + } + + if(deleted) { + MCOIMAPOperation *deleteOp = [session expungeOperation:@"[Gmail]/Trash"]; + [deleteOp start:^(NSError *error) { + if(error) { + NSLog(@"Error expunging folder: %@", error); + } else { + NSLog(@"Successfully expunged folder"); + } + }]; + } + }]; + + } + }]; + } + + @synchronized(queue) { + [queue removeObjectAtIndex:0]; + if ([queue count]!=0) { + [NSThread detachNewThreadSelector:@selector(sendNextEmail) toTarget:self withObject:nil]; + } else { + sendingEmail = NO; + } + } + + [pool drain]; +} +@end diff --git a/EmailScheduler/MGMEmail.h b/EmailScheduler/MGMEmail.h new file mode 100644 index 0000000..a811ccd --- /dev/null +++ b/EmailScheduler/MGMEmail.h @@ -0,0 +1,41 @@ +// +// MGMEmail.h +// EmailScheduler +// +// Created by James Coleman on 9/13/14. +// Copyright (c) 2014 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +#import + +@class MCOSMTPSession, MCOIMAPSession; + +@interface MGMEmail : NSObject { + NSString *emailAddress; + NSData *rfc822Data; +} +- (void)setEmailAddress:(NSString *)email; +- (NSString *)eamilAddress; +- (MCOSMTPSession *)session; +- (MCOIMAPSession *)imapSession; +- (void)setRFC822Data:(NSData *)data; +- (NSData *)rfc822Data; +@end diff --git a/EmailScheduler/MGMEmail.m b/EmailScheduler/MGMEmail.m new file mode 100644 index 0000000..2e776a1 --- /dev/null +++ b/EmailScheduler/MGMEmail.m @@ -0,0 +1,68 @@ +// +// MGMEmail.m +// EmailScheduler +// +// Created by James Coleman on 9/13/14. +// Copyright (c) 2014 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +#import "MGMEmail.h" +#import "MGMController.h" +#import + +@implementation MGMEmail +- (void)setEmailAddress:(NSString *)email { + [emailAddress autorelease]; + emailAddress = [email retain]; +} +- (NSString *)eamilAddress { + return emailAddress; +} +- (MCOSMTPSession *)session { + MGMController *controller = [MGMController sharedController]; + MCOSMTPSession *smtpSession = [[[MCOSMTPSession alloc] init] autorelease]; + smtpSession.hostname = @"smtp.gmail.com"; + smtpSession.port = 465; + smtpSession.username = emailAddress; + smtpSession.password = [[controller emailAddresses] objectForKey:emailAddress]; + smtpSession.authType = MCOAuthTypeSASLPlain; + smtpSession.connectionType = MCOConnectionTypeTLS; + return smtpSession; +} +- (MCOIMAPSession *)imapSession { + MGMController *controller = [MGMController sharedController]; + MCOIMAPSession *session = [[[MCOIMAPSession alloc] init] autorelease]; + session.hostname = @"imap.gmail.com"; + session.port = 993; + session.username = emailAddress; + session.password = [[controller emailAddresses] objectForKey:emailAddress]; + session.connectionType = MCOConnectionTypeTLS; + return session; +} + +- (void)setRFC822Data:(NSData *)data { + [rfc822Data autorelease]; + rfc822Data = [data retain]; +} +- (NSData *)rfc822Data { + return rfc822Data; +} +@end diff --git a/EmailScheduler/MGMHTTP/AsyncSocket.h b/EmailScheduler/MGMHTTP/AsyncSocket.h new file mode 100644 index 0000000..8382cd3 --- /dev/null +++ b/EmailScheduler/MGMHTTP/AsyncSocket.h @@ -0,0 +1,659 @@ +// +// AsyncSocket.h +// +// This class is in the public domain. +// Originally created by Dustin Voss on Wed Jan 29 2003. +// Updated and maintained by Deusty Designs and the Mac development community. +// +// http://code.google.com/p/cocoaasyncsocket/ +// + +#import + +@class AsyncSocket; +@class AsyncReadPacket; +@class AsyncWritePacket; + +extern NSString *const AsyncSocketException; +extern NSString *const AsyncSocketErrorDomain; + +enum AsyncSocketError +{ + AsyncSocketCFSocketError = kCFSocketError, // From CFSocketError enum. + AsyncSocketNoError = 0, // Never used. + AsyncSocketCanceledError, // onSocketWillConnect: returned NO. + AsyncSocketConnectTimeoutError, + AsyncSocketReadMaxedOutError, // Reached set maxLength without completing + AsyncSocketReadTimeoutError, + AsyncSocketWriteTimeoutError +}; +typedef enum AsyncSocketError AsyncSocketError; + +@protocol AsyncSocketDelegate +@optional + +/** + * In the event of an error, the socket is closed. + * You may call "unreadData" during this call-back to get the last bit of data off the socket. + * When connecting, this delegate method may be called + * before"onSocket:didAcceptNewSocket:" or "onSocket:didConnectToHost:". +**/ +- (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err; + +/** + * Called when a socket disconnects with or without error. If you want to release a socket after it disconnects, + * do so here. It is not safe to do that during "onSocket:willDisconnectWithError:". + * + * If you call the disconnect method, and the socket wasn't already disconnected, + * this delegate method will be called before the disconnect method returns. +**/ +- (void)onSocketDidDisconnect:(AsyncSocket *)sock; + +/** + * Called when a socket accepts a connection. Another socket is spawned to handle it. The new socket will have + * the same delegate and will call "onSocket:didConnectToHost:port:". +**/ +- (void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket; + +/** + * Called when a new socket is spawned to handle a connection. This method should return the run-loop of the + * thread on which the new socket and its delegate should operate. If omitted, [NSRunLoop currentRunLoop] is used. +**/ +- (NSRunLoop *)onSocket:(AsyncSocket *)sock wantsRunLoopForNewSocket:(AsyncSocket *)newSocket; + +/** + * Called when a socket is about to connect. This method should return YES to continue, or NO to abort. + * If aborted, will result in AsyncSocketCanceledError. + * + * If the connectToHost:onPort:error: method was called, the delegate will be able to access and configure the + * CFReadStream and CFWriteStream as desired prior to connection. + * + * If the connectToAddress:error: method was called, the delegate will be able to access and configure the + * CFSocket and CFSocketNativeHandle (BSD socket) as desired prior to connection. You will be able to access and + * configure the CFReadStream and CFWriteStream in the onSocket:didConnectToHost:port: method. +**/ +- (BOOL)onSocketWillConnect:(AsyncSocket *)sock; + +/** + * Called when a socket connects and is ready for reading and writing. + * The host parameter will be an IP address, not a DNS name. +**/ +- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port; + +/** + * Called when a socket has completed reading the requested data into memory. + * Not called if there is an error. +**/ +- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag; + +/** + * Called when a socket has read in data, but has not yet completed the read. + * This would occur if using readToData: or readToLength: methods. + * It may be used to for things such as updating progress bars. +**/ +- (void)onSocket:(AsyncSocket *)sock didReadPartialDataOfLength:(NSUInteger)partialLength tag:(long)tag; + +/** + * Called when a socket has completed writing the requested data. Not called if there is an error. +**/ +- (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag; + +/** + * Called when a socket has written some data, but has not yet completed the entire write. + * It may be used to for things such as updating progress bars. +**/ +- (void)onSocket:(AsyncSocket *)sock didWritePartialDataOfLength:(NSUInteger)partialLength tag:(long)tag; + +/** + * Called if a read operation has reached its timeout without completing. + * This method allows you to optionally extend the timeout. + * If you return a positive time interval (> 0) the read's timeout will be extended by the given amount. + * If you don't implement this method, or return a non-positive time interval (<= 0) the read will timeout as usual. + * + * The elapsed parameter is the sum of the original timeout, plus any additions previously added via this method. + * The length parameter is the number of bytes that have been read so far for the read operation. + * + * Note that this method may be called multiple times for a single read if you return positive numbers. +**/ +- (NSTimeInterval)onSocket:(AsyncSocket *)sock + shouldTimeoutReadWithTag:(long)tag + elapsed:(NSTimeInterval)elapsed + bytesDone:(NSUInteger)length; + +/** + * Called if a write operation has reached its timeout without completing. + * This method allows you to optionally extend the timeout. + * If you return a positive time interval (> 0) the write's timeout will be extended by the given amount. + * If you don't implement this method, or return a non-positive time interval (<= 0) the write will timeout as usual. + * + * The elapsed parameter is the sum of the original timeout, plus any additions previously added via this method. + * The length parameter is the number of bytes that have been written so far for the write operation. + * + * Note that this method may be called multiple times for a single write if you return positive numbers. +**/ +- (NSTimeInterval)onSocket:(AsyncSocket *)sock + shouldTimeoutWriteWithTag:(long)tag + elapsed:(NSTimeInterval)elapsed + bytesDone:(NSUInteger)length; + +/** + * Called after the socket has successfully completed SSL/TLS negotiation. + * This method is not called unless you use the provided startTLS method. + * + * If a SSL/TLS negotiation fails (invalid certificate, etc) then the socket will immediately close, + * and the onSocket:willDisconnectWithError: delegate method will be called with the specific SSL error code. +**/ +- (void)onSocketDidSecure:(AsyncSocket *)sock; + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +@interface AsyncSocket : NSObject +{ + CFSocketNativeHandle theNativeSocket4; + CFSocketNativeHandle theNativeSocket6; + + CFSocketRef theSocket4; // IPv4 accept or connect socket + CFSocketRef theSocket6; // IPv6 accept or connect socket + + CFReadStreamRef theReadStream; + CFWriteStreamRef theWriteStream; + + CFRunLoopSourceRef theSource4; // For theSocket4 + CFRunLoopSourceRef theSource6; // For theSocket6 + CFRunLoopRef theRunLoop; + CFSocketContext theContext; + NSArray *theRunLoopModes; + + NSTimer *theConnectTimer; + + NSMutableArray *theReadQueue; + AsyncReadPacket *theCurrentRead; + NSTimer *theReadTimer; + NSMutableData *partialReadBuffer; + + NSMutableArray *theWriteQueue; + AsyncWritePacket *theCurrentWrite; + NSTimer *theWriteTimer; + + id theDelegate; + UInt16 theFlags; + + long theUserData; +} + +- (id)init; +- (id)initWithDelegate:(id)delegate; +- (id)initWithDelegate:(id)delegate userData:(long)userData; + +/* String representation is long but has no "\n". */ +- (NSString *)description; + +/** + * Use "canSafelySetDelegate" to see if there is any pending business (reads and writes) with the current delegate + * before changing it. It is, of course, safe to change the delegate before connecting or accepting connections. +**/ +- (id)delegate; +- (BOOL)canSafelySetDelegate; +- (void)setDelegate:(id)delegate; + +/* User data can be a long, or an id or void * cast to a long. */ +- (long)userData; +- (void)setUserData:(long)userData; + +/* Don't use these to read or write. And don't close them either! */ +- (CFSocketRef)getCFSocket; +- (CFReadStreamRef)getCFReadStream; +- (CFWriteStreamRef)getCFWriteStream; + +// Once one of the accept or connect methods are called, the AsyncSocket instance is locked in +// and the other accept/connect methods can't be called without disconnecting the socket first. +// If the attempt fails or times out, these methods either return NO or +// call "onSocket:willDisconnectWithError:" and "onSockedDidDisconnect:". + +// When an incoming connection is accepted, AsyncSocket invokes several delegate methods. +// These methods are (in chronological order): +// 1. onSocket:didAcceptNewSocket: +// 2. onSocket:wantsRunLoopForNewSocket: +// 3. onSocketWillConnect: +// +// Your server code will need to retain the accepted socket (if you want to accept it). +// The best place to do this is probably in the onSocket:didAcceptNewSocket: method. +// +// After the read and write streams have been setup for the newly accepted socket, +// the onSocket:didConnectToHost:port: method will be called on the proper run loop. +// +// Multithreading Note: If you're going to be moving the newly accepted socket to another run +// loop by implementing onSocket:wantsRunLoopForNewSocket:, then you should wait until the +// onSocket:didConnectToHost:port: method before calling read, write, or startTLS methods. +// Otherwise read/write events are scheduled on the incorrect runloop, and chaos may ensue. + +/** + * Tells the socket to begin listening and accepting connections on the given port. + * When a connection comes in, the AsyncSocket instance will call the various delegate methods (see above). + * The socket will listen on all available interfaces (e.g. wifi, ethernet, etc) +**/ +- (BOOL)acceptOnPort:(UInt16)port error:(NSError **)errPtr; + +/** + * This method is the same as acceptOnPort:error: with the additional option + * of specifying which interface to listen on. So, for example, if you were writing code for a server that + * has multiple IP addresses, you could specify which address you wanted to listen on. Or you could use it + * to specify that the socket should only accept connections over ethernet, and not other interfaces such as wifi. + * You may also use the special strings "localhost" or "loopback" to specify that + * the socket only accept connections from the local machine. + * + * To accept connections on any interface pass nil, or simply use the acceptOnPort:error: method. +**/ +- (BOOL)acceptOnInterface:(NSString *)interface port:(UInt16)port error:(NSError **)errPtr; + +/** + * Connects to the given host and port. + * The host may be a domain name (e.g. "deusty.com") or an IP address string (e.g. "192.168.0.2") +**/ +- (BOOL)connectToHost:(NSString *)hostname onPort:(UInt16)port error:(NSError **)errPtr; + +/** + * This method is the same as connectToHost:onPort:error: with an additional timeout option. + * To not time out use a negative time interval, or simply use the connectToHost:onPort:error: method. +**/ +- (BOOL)connectToHost:(NSString *)hostname + onPort:(UInt16)port + withTimeout:(NSTimeInterval)timeout + error:(NSError **)errPtr; + +/** + * Connects to the given address, specified as a sockaddr structure wrapped in a NSData object. + * For example, a NSData object returned from NSNetservice's addresses method. + * + * If you have an existing struct sockaddr you can convert it to a NSData object like so: + * struct sockaddr sa -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len]; + * struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len]; +**/ +- (BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError **)errPtr; + +/** + * This method is the same as connectToAddress:error: with an additional timeout option. + * To not time out use a negative time interval, or simply use the connectToAddress:error: method. +**/ +- (BOOL)connectToAddress:(NSData *)remoteAddr withTimeout:(NSTimeInterval)timeout error:(NSError **)errPtr; + +- (BOOL)connectToAddress:(NSData *)remoteAddr + viaInterfaceAddress:(NSData *)interfaceAddr + withTimeout:(NSTimeInterval)timeout + error:(NSError **)errPtr; + +/** + * Disconnects immediately. Any pending reads or writes are dropped. + * If the socket is not already disconnected, the onSocketDidDisconnect delegate method + * will be called immediately, before this method returns. + * + * Please note the recommended way of releasing an AsyncSocket instance (e.g. in a dealloc method) + * [asyncSocket setDelegate:nil]; + * [asyncSocket disconnect]; + * [asyncSocket release]; +**/ +- (void)disconnect; + +/** + * Disconnects after all pending reads have completed. + * After calling this, the read and write methods will do nothing. + * The socket will disconnect even if there are still pending writes. +**/ +- (void)disconnectAfterReading; + +/** + * Disconnects after all pending writes have completed. + * After calling this, the read and write methods will do nothing. + * The socket will disconnect even if there are still pending reads. +**/ +- (void)disconnectAfterWriting; + +/** + * Disconnects after all pending reads and writes have completed. + * After calling this, the read and write methods will do nothing. +**/ +- (void)disconnectAfterReadingAndWriting; + +/* Returns YES if the socket and streams are open, connected, and ready for reading and writing. */ +- (BOOL)isConnected; + +/** + * Returns the local or remote host and port to which this socket is connected, or nil and 0 if not connected. + * The host will be an IP address. +**/ +- (NSString *)connectedHost; +- (UInt16)connectedPort; + +- (NSString *)localHost; +- (UInt16)localPort; + +/** + * Returns the local or remote address to which this socket is connected, + * specified as a sockaddr structure wrapped in a NSData object. + * + * See also the connectedHost, connectedPort, localHost and localPort methods. +**/ +- (NSData *)connectedAddress; +- (NSData *)localAddress; + +/** + * Returns whether the socket is IPv4 or IPv6. + * An accepting socket may be both. +**/ +- (BOOL)isIPv4; +- (BOOL)isIPv6; + +// The readData and writeData methods won't block (they are asynchronous). +// +// When a read is complete the onSocket:didReadData:withTag: delegate method is called. +// When a write is complete the onSocket:didWriteDataWithTag: delegate method is called. +// +// You may optionally set a timeout for any read/write operation. (To not timeout, use a negative time interval.) +// If a read/write opertion times out, the corresponding "onSocket:shouldTimeout..." delegate method +// is called to optionally allow you to extend the timeout. +// Upon a timeout, the "onSocket:willDisconnectWithError:" method is called, followed by "onSocketDidDisconnect". +// +// The tag is for your convenience. +// You can use it as an array index, step number, state id, pointer, etc. + +/** + * Reads the first available bytes that become available on the socket. + * + * If the timeout value is negative, the read operation will not use a timeout. +**/ +- (void)readDataWithTimeout:(NSTimeInterval)timeout tag:(long)tag; + +/** + * Reads the first available bytes that become available on the socket. + * The bytes will be appended to the given byte buffer starting at the given offset. + * The given buffer will automatically be increased in size if needed. + * + * If the timeout value is negative, the read operation will not use a timeout. + * If the buffer if nil, the socket will create a buffer for you. + * + * If the bufferOffset is greater than the length of the given buffer, + * the method will do nothing, and the delegate will not be called. + * + * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it. + * After completion, the data returned in onSocket:didReadData:withTag: will be a subset of the given buffer. + * That is, it will reference the bytes that were appended to the given buffer. +**/ +- (void)readDataWithTimeout:(NSTimeInterval)timeout + buffer:(NSMutableData *)buffer + bufferOffset:(NSUInteger)offset + tag:(long)tag; + +/** + * Reads the first available bytes that become available on the socket. + * The bytes will be appended to the given byte buffer starting at the given offset. + * The given buffer will automatically be increased in size if needed. + * A maximum of length bytes will be read. + * + * If the timeout value is negative, the read operation will not use a timeout. + * If the buffer if nil, a buffer will automatically be created for you. + * If maxLength is zero, no length restriction is enforced. + * + * If the bufferOffset is greater than the length of the given buffer, + * the method will do nothing, and the delegate will not be called. + * + * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it. + * After completion, the data returned in onSocket:didReadData:withTag: will be a subset of the given buffer. + * That is, it will reference the bytes that were appended to the given buffer. +**/ +- (void)readDataWithTimeout:(NSTimeInterval)timeout + buffer:(NSMutableData *)buffer + bufferOffset:(NSUInteger)offset + maxLength:(NSUInteger)length + tag:(long)tag; + +/** + * Reads the given number of bytes. + * + * If the timeout value is negative, the read operation will not use a timeout. + * + * If the length is 0, this method does nothing and the delegate is not called. +**/ +- (void)readDataToLength:(NSUInteger)length withTimeout:(NSTimeInterval)timeout tag:(long)tag; + +/** + * Reads the given number of bytes. + * The bytes will be appended to the given byte buffer starting at the given offset. + * The given buffer will automatically be increased in size if needed. + * + * If the timeout value is negative, the read operation will not use a timeout. + * If the buffer if nil, a buffer will automatically be created for you. + * + * If the length is 0, this method does nothing and the delegate is not called. + * If the bufferOffset is greater than the length of the given buffer, + * the method will do nothing, and the delegate will not be called. + * + * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it. + * After completion, the data returned in onSocket:didReadData:withTag: will be a subset of the given buffer. + * That is, it will reference the bytes that were appended to the given buffer. +**/ +- (void)readDataToLength:(NSUInteger)length + withTimeout:(NSTimeInterval)timeout + buffer:(NSMutableData *)buffer + bufferOffset:(NSUInteger)offset + tag:(long)tag; + +/** + * Reads bytes until (and including) the passed "data" parameter, which acts as a separator. + * + * If the timeout value is negative, the read operation will not use a timeout. + * + * If you pass nil or zero-length data as the "data" parameter, + * the method will do nothing, and the delegate will not be called. + * + * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the "data" parameter. + * Note that this method is not character-set aware, so if a separator can occur naturally as part of the encoding for + * a character, the read will prematurely end. +**/ +- (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag; + +/** + * Reads bytes until (and including) the passed "data" parameter, which acts as a separator. + * The bytes will be appended to the given byte buffer starting at the given offset. + * The given buffer will automatically be increased in size if needed. + * + * If the timeout value is negative, the read operation will not use a timeout. + * If the buffer if nil, a buffer will automatically be created for you. + * + * If the bufferOffset is greater than the length of the given buffer, + * the method will do nothing, and the delegate will not be called. + * + * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it. + * After completion, the data returned in onSocket:didReadData:withTag: will be a subset of the given buffer. + * That is, it will reference the bytes that were appended to the given buffer. + * + * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the "data" parameter. + * Note that this method is not character-set aware, so if a separator can occur naturally as part of the encoding for + * a character, the read will prematurely end. +**/ +- (void)readDataToData:(NSData *)data + withTimeout:(NSTimeInterval)timeout + buffer:(NSMutableData *)buffer + bufferOffset:(NSUInteger)offset + tag:(long)tag; + +/** + * Reads bytes until (and including) the passed "data" parameter, which acts as a separator. + * + * If the timeout value is negative, the read operation will not use a timeout. + * + * If maxLength is zero, no length restriction is enforced. + * Otherwise if maxLength bytes are read without completing the read, + * it is treated similarly to a timeout - the socket is closed with a AsyncSocketReadMaxedOutError. + * The read will complete successfully if exactly maxLength bytes are read and the given data is found at the end. + * + * If you pass nil or zero-length data as the "data" parameter, + * the method will do nothing, and the delegate will not be called. + * If you pass a maxLength parameter that is less than the length of the data parameter, + * the method will do nothing, and the delegate will not be called. + * + * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the "data" parameter. + * Note that this method is not character-set aware, so if a separator can occur naturally as part of the encoding for + * a character, the read will prematurely end. +**/ +- (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout maxLength:(NSUInteger)length tag:(long)tag; + +/** + * Reads bytes until (and including) the passed "data" parameter, which acts as a separator. + * The bytes will be appended to the given byte buffer starting at the given offset. + * The given buffer will automatically be increased in size if needed. + * A maximum of length bytes will be read. + * + * If the timeout value is negative, the read operation will not use a timeout. + * If the buffer if nil, a buffer will automatically be created for you. + * + * If maxLength is zero, no length restriction is enforced. + * Otherwise if maxLength bytes are read without completing the read, + * it is treated similarly to a timeout - the socket is closed with a AsyncSocketReadMaxedOutError. + * The read will complete successfully if exactly maxLength bytes are read and the given data is found at the end. + * + * If you pass a maxLength parameter that is less than the length of the data parameter, + * the method will do nothing, and the delegate will not be called. + * If the bufferOffset is greater than the length of the given buffer, + * the method will do nothing, and the delegate will not be called. + * + * If you pass a buffer, you must not alter it in any way while AsyncSocket is using it. + * After completion, the data returned in onSocket:didReadData:withTag: will be a subset of the given buffer. + * That is, it will reference the bytes that were appended to the given buffer. + * + * To read a line from the socket, use the line separator (e.g. CRLF for HTTP, see below) as the "data" parameter. + * Note that this method is not character-set aware, so if a separator can occur naturally as part of the encoding for + * a character, the read will prematurely end. +**/ +- (void)readDataToData:(NSData *)data + withTimeout:(NSTimeInterval)timeout + buffer:(NSMutableData *)buffer + bufferOffset:(NSUInteger)offset + maxLength:(NSUInteger)length + tag:(long)tag; + +/** + * Writes data to the socket, and calls the delegate when finished. + * + * If you pass in nil or zero-length data, this method does nothing and the delegate will not be called. + * If the timeout value is negative, the write operation will not use a timeout. +**/ +- (void)writeData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag; + +/** + * Returns progress of current read or write, from 0.0 to 1.0, or NaN if no read/write (use isnan() to check). + * "tag", "done" and "total" will be filled in if they aren't NULL. +**/ +- (float)progressOfReadReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total; +- (float)progressOfWriteReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total; + +/** + * Secures the connection using SSL/TLS. + * + * This method may be called at any time, and the TLS handshake will occur after all pending reads and writes + * are finished. This allows one the option of sending a protocol dependent StartTLS message, and queuing + * the upgrade to TLS at the same time, without having to wait for the write to finish. + * Any reads or writes scheduled after this method is called will occur over the secured connection. + * + * The possible keys and values for the TLS settings are well documented. + * Some possible keys are: + * - kCFStreamSSLLevel + * - kCFStreamSSLAllowsExpiredCertificates + * - kCFStreamSSLAllowsExpiredRoots + * - kCFStreamSSLAllowsAnyRoot + * - kCFStreamSSLValidatesCertificateChain + * - kCFStreamSSLPeerName + * - kCFStreamSSLCertificates + * - kCFStreamSSLIsServer + * + * Please refer to Apple's documentation for associated values, as well as other possible keys. + * + * If you pass in nil or an empty dictionary, the default settings will be used. + * + * The default settings will check to make sure the remote party's certificate is signed by a + * trusted 3rd party certificate agency (e.g. verisign) and that the certificate is not expired. + * However it will not verify the name on the certificate unless you + * give it a name to verify against via the kCFStreamSSLPeerName key. + * The security implications of this are important to understand. + * Imagine you are attempting to create a secure connection to MySecureServer.com, + * but your socket gets directed to MaliciousServer.com because of a hacked DNS server. + * If you simply use the default settings, and MaliciousServer.com has a valid certificate, + * the default settings will not detect any problems since the certificate is valid. + * To properly secure your connection in this particular scenario you + * should set the kCFStreamSSLPeerName property to "MySecureServer.com". + * If you do not know the peer name of the remote host in advance (for example, you're not sure + * if it will be "domain.com" or "www.domain.com"), then you can use the default settings to validate the + * certificate, and then use the X509Certificate class to verify the issuer after the socket has been secured. + * The X509Certificate class is part of the CocoaAsyncSocket open source project. +**/ +- (void)startTLS:(NSDictionary *)tlsSettings; + +/** + * For handling readDataToData requests, data is necessarily read from the socket in small increments. + * The performance can be much improved by allowing AsyncSocket to read larger chunks at a time and + * store any overflow in a small internal buffer. + * This is termed pre-buffering, as some data may be read for you before you ask for it. + * If you use readDataToData a lot, enabling pre-buffering will result in better performance, especially on the iPhone. + * + * The default pre-buffering state is controlled by the DEFAULT_PREBUFFERING definition. + * It is highly recommended one leave this set to YES. + * + * This method exists in case pre-buffering needs to be disabled by default for some unforeseen reason. + * In that case, this method exists to allow one to easily enable pre-buffering when ready. +**/ +- (void)enablePreBuffering; + +/** + * When you create an AsyncSocket, it is added to the runloop of the current thread. + * So for manually created sockets, it is easiest to simply create the socket on the thread you intend to use it. + * + * If a new socket is accepted, the delegate method onSocket:wantsRunLoopForNewSocket: is called to + * allow you to place the socket on a separate thread. This works best in conjunction with a thread pool design. + * + * If, however, you need to move the socket to a separate thread at a later time, this + * method may be used to accomplish the task. + * + * This method must be called from the thread/runloop the socket is currently running on. + * + * Note: After calling this method, all further method calls to this object should be done from the given runloop. + * Also, all delegate calls will be sent on the given runloop. +**/ +- (BOOL)moveToRunLoop:(NSRunLoop *)runLoop; + +/** + * Allows you to configure which run loop modes the socket uses. + * The default set of run loop modes is NSDefaultRunLoopMode. + * + * If you'd like your socket to continue operation during other modes, you may want to add modes such as + * NSModalPanelRunLoopMode or NSEventTrackingRunLoopMode. Or you may simply want to use NSRunLoopCommonModes. + * + * Accepted sockets will automatically inherit the same run loop modes as the listening socket. + * + * Note: NSRunLoopCommonModes is defined in 10.5. For previous versions one can use kCFRunLoopCommonModes. +**/ +- (BOOL)setRunLoopModes:(NSArray *)runLoopModes; +- (BOOL)addRunLoopMode:(NSString *)runLoopMode; +- (BOOL)removeRunLoopMode:(NSString *)runLoopMode; + +/** + * Returns the current run loop modes the AsyncSocket instance is operating in. + * The default set of run loop modes is NSDefaultRunLoopMode. +**/ +- (NSArray *)runLoopModes; + +/** + * In the event of an error, this method may be called during onSocket:willDisconnectWithError: to read + * any data that's left on the socket. +**/ +- (NSData *)unreadData; + +/* A few common line separators, for use with the readDataToData:... methods. */ ++ (NSData *)CRLFData; // 0x0D0A ++ (NSData *)CRData; // 0x0D ++ (NSData *)LFData; // 0x0A ++ (NSData *)ZeroData; // 0x00 + +@end diff --git a/EmailScheduler/MGMHTTP/AsyncSocket.m b/EmailScheduler/MGMHTTP/AsyncSocket.m new file mode 100644 index 0000000..4325611 --- /dev/null +++ b/EmailScheduler/MGMHTTP/AsyncSocket.m @@ -0,0 +1,4192 @@ +// +// AsyncSocket.m +// +// This class is in the public domain. +// Originally created by Dustin Voss on Wed Jan 29 2003. +// Updated and maintained by Deusty Designs and the Mac development community. +// +// http://code.google.com/p/cocoaasyncsocket/ +// + +#import "AsyncSocket.h" +#import +#import +#import +#import + +#if TARGET_OS_IPHONE +// Note: You may need to add the CFNetwork Framework to your project +#import +#endif + +#pragma mark Declarations + +#define DEFAULT_PREBUFFERING YES // Whether pre-buffering is enabled by default + +#define READQUEUE_CAPACITY 5 // Initial capacity +#define WRITEQUEUE_CAPACITY 5 // Initial capacity +#define READALL_CHUNKSIZE 256 // Incremental increase in buffer size +#define WRITE_CHUNKSIZE (1024 * 4) // Limit on size of each write pass + +NSString *const AsyncSocketException = @"AsyncSocketException"; +NSString *const AsyncSocketErrorDomain = @"AsyncSocketErrorDomain"; + +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 +// Mutex lock used by all instances of AsyncSocket, to protect getaddrinfo. +// Prior to Mac OS X 10.5 this method was not thread-safe. +static NSString *getaddrinfoLock = @"lock"; +#endif + +enum AsyncSocketFlags +{ + kEnablePreBuffering = 1 << 0, // If set, pre-buffering is enabled + kDidStartDelegate = 1 << 1, // If set, disconnection results in delegate call + kDidCompleteOpenForRead = 1 << 2, // If set, open callback has been called for read stream + kDidCompleteOpenForWrite = 1 << 3, // If set, open callback has been called for write stream + kStartingReadTLS = 1 << 4, // If set, we're waiting for TLS negotiation to complete + kStartingWriteTLS = 1 << 5, // If set, we're waiting for TLS negotiation to complete + kForbidReadsWrites = 1 << 6, // If set, no new reads or writes are allowed + kDisconnectAfterReads = 1 << 7, // If set, disconnect after no more reads are queued + kDisconnectAfterWrites = 1 << 8, // If set, disconnect after no more writes are queued + kClosingWithError = 1 << 9, // If set, the socket is being closed due to an error + kDequeueReadScheduled = 1 << 10, // If set, a maybeDequeueRead operation is already scheduled + kDequeueWriteScheduled = 1 << 11, // If set, a maybeDequeueWrite operation is already scheduled + kSocketCanAcceptBytes = 1 << 12, // If set, we know socket can accept bytes. If unset, it's unknown. + kSocketHasBytesAvailable = 1 << 13, // If set, we know socket has bytes available. If unset, it's unknown. +}; + +@interface AsyncSocket (Private) + +// Connecting +- (void)startConnectTimeout:(NSTimeInterval)timeout; +- (void)endConnectTimeout; + +// Socket Implementation +- (CFSocketRef)newAcceptSocketForAddress:(NSData *)addr error:(NSError **)errPtr; +- (BOOL)createSocketForAddress:(NSData *)remoteAddr error:(NSError **)errPtr; +- (BOOL)bindSocketToAddress:(NSData *)interfaceAddr error:(NSError **)errPtr; +- (BOOL)attachSocketsToRunLoop:(NSRunLoop *)runLoop error:(NSError **)errPtr; +- (BOOL)configureSocketAndReturnError:(NSError **)errPtr; +- (BOOL)connectSocketToAddress:(NSData *)remoteAddr error:(NSError **)errPtr; +- (void)doAcceptWithSocket:(CFSocketNativeHandle)newSocket; +- (void)doSocketOpen:(CFSocketRef)sock withCFSocketError:(CFSocketError)err; + +// Stream Implementation +- (BOOL)createStreamsFromNative:(CFSocketNativeHandle)native error:(NSError **)errPtr; +- (BOOL)createStreamsToHost:(NSString *)hostname onPort:(UInt16)port error:(NSError **)errPtr; +- (BOOL)attachStreamsToRunLoop:(NSRunLoop *)runLoop error:(NSError **)errPtr; +- (BOOL)configureStreamsAndReturnError:(NSError **)errPtr; +- (BOOL)openStreamsAndReturnError:(NSError **)errPtr; +- (void)doStreamOpen; +- (BOOL)setSocketFromStreamsAndReturnError:(NSError **)errPtr; + +// Disconnect Implementation +- (void)closeWithError:(NSError *)err; +- (void)recoverUnreadData; +- (void)emptyQueues; +- (void)close; + +// Errors +- (NSError *)getErrnoError; +- (NSError *)getAbortError; +- (NSError *)getStreamError; +- (NSError *)getSocketError; +- (NSError *)getConnectTimeoutError; +- (NSError *)getReadMaxedOutError; +- (NSError *)getReadTimeoutError; +- (NSError *)getWriteTimeoutError; +- (NSError *)errorFromCFStreamError:(CFStreamError)err; + +// Diagnostics +- (BOOL)isDisconnected; +- (BOOL)areStreamsConnected; +- (NSString *)connectedHostFromNativeSocket4:(CFSocketNativeHandle)theNativeSocket; +- (NSString *)connectedHostFromNativeSocket6:(CFSocketNativeHandle)theNativeSocket; +- (NSString *)connectedHostFromCFSocket4:(CFSocketRef)socket; +- (NSString *)connectedHostFromCFSocket6:(CFSocketRef)socket; +- (UInt16)connectedPortFromNativeSocket4:(CFSocketNativeHandle)theNativeSocket; +- (UInt16)connectedPortFromNativeSocket6:(CFSocketNativeHandle)theNativeSocket; +- (UInt16)connectedPortFromCFSocket4:(CFSocketRef)socket; +- (UInt16)connectedPortFromCFSocket6:(CFSocketRef)socket; +- (NSString *)localHostFromNativeSocket4:(CFSocketNativeHandle)theNativeSocket; +- (NSString *)localHostFromNativeSocket6:(CFSocketNativeHandle)theNativeSocket; +- (NSString *)localHostFromCFSocket4:(CFSocketRef)socket; +- (NSString *)localHostFromCFSocket6:(CFSocketRef)socket; +- (UInt16)localPortFromNativeSocket4:(CFSocketNativeHandle)theNativeSocket; +- (UInt16)localPortFromNativeSocket6:(CFSocketNativeHandle)theNativeSocket; +- (UInt16)localPortFromCFSocket4:(CFSocketRef)socket; +- (UInt16)localPortFromCFSocket6:(CFSocketRef)socket; +- (NSString *)hostFromAddress4:(struct sockaddr_in *)pSockaddr4; +- (NSString *)hostFromAddress6:(struct sockaddr_in6 *)pSockaddr6; +- (UInt16)portFromAddress4:(struct sockaddr_in *)pSockaddr4; +- (UInt16)portFromAddress6:(struct sockaddr_in6 *)pSockaddr6; + +// Reading +- (void)doBytesAvailable; +- (void)completeCurrentRead; +- (void)endCurrentRead; +- (void)scheduleDequeueRead; +- (void)maybeDequeueRead; +- (void)doReadTimeout:(NSTimer *)timer; + +// Writing +- (void)doSendBytes; +- (void)completeCurrentWrite; +- (void)endCurrentWrite; +- (void)scheduleDequeueWrite; +- (void)maybeDequeueWrite; +- (void)maybeScheduleDisconnect; +- (void)doWriteTimeout:(NSTimer *)timer; + +// Run Loop +- (void)runLoopAddSource:(CFRunLoopSourceRef)source; +- (void)runLoopRemoveSource:(CFRunLoopSourceRef)source; +- (void)runLoopAddTimer:(NSTimer *)timer; +- (void)runLoopRemoveTimer:(NSTimer *)timer; +- (void)runLoopUnscheduleReadStream; +- (void)runLoopUnscheduleWriteStream; + +// Security +- (void)maybeStartTLS; +- (void)onTLSHandshakeSuccessful; + +// Callbacks +- (void)doCFCallback:(CFSocketCallBackType)type + forSocket:(CFSocketRef)sock withAddress:(NSData *)address withData:(const void *)pData; +- (void)doCFReadStreamCallback:(CFStreamEventType)type forStream:(CFReadStreamRef)stream; +- (void)doCFWriteStreamCallback:(CFStreamEventType)type forStream:(CFWriteStreamRef)stream; + +@end + +static void MyCFSocketCallback(CFSocketRef, CFSocketCallBackType, CFDataRef, const void *, void *); +static void MyCFReadStreamCallback(CFReadStreamRef stream, CFStreamEventType type, void *pInfo); +static void MyCFWriteStreamCallback(CFWriteStreamRef stream, CFStreamEventType type, void *pInfo); + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * The AsyncReadPacket encompasses the instructions for any given read. + * The content of a read packet allows the code to determine if we're: + * - reading to a certain length + * - reading to a certain separator + * - or simply reading the first chunk of available data +**/ +@interface AsyncReadPacket : NSObject +{ + @public + NSMutableData *buffer; + NSUInteger startOffset; + NSUInteger bytesDone; + NSUInteger maxLength; + NSTimeInterval timeout; + NSUInteger readLength; + NSData *term; + BOOL bufferOwner; + NSUInteger originalBufferLength; + long tag; +} +- (id)initWithData:(NSMutableData *)d + startOffset:(NSUInteger)s + maxLength:(NSUInteger)m + timeout:(NSTimeInterval)t + readLength:(NSUInteger)l + terminator:(NSData *)e + tag:(long)i; + +- (NSUInteger)readLengthForNonTerm; +- (NSUInteger)readLengthForTerm; +- (NSUInteger)readLengthForTermWithPreBuffer:(NSData *)preBuffer found:(BOOL *)foundPtr; + +- (NSUInteger)prebufferReadLengthForTerm; +- (NSInteger)searchForTermAfterPreBuffering:(NSUInteger)numBytes; +@end + +@implementation AsyncReadPacket + +- (id)initWithData:(NSMutableData *)d + startOffset:(NSUInteger)s + maxLength:(NSUInteger)m + timeout:(NSTimeInterval)t + readLength:(NSUInteger)l + terminator:(NSData *)e + tag:(long)i +{ + if((self = [super init])) + { + if (d) + { + buffer = [d retain]; + startOffset = s; + bufferOwner = NO; + originalBufferLength = [d length]; + } + else + { + if (readLength > 0) + buffer = [[NSMutableData alloc] initWithLength:readLength]; + else + buffer = [[NSMutableData alloc] initWithLength:0]; + + startOffset = 0; + bufferOwner = YES; + originalBufferLength = 0; + } + + bytesDone = 0; + maxLength = m; + timeout = t; + readLength = l; + term = [e copy]; + tag = i; + } + return self; +} + +/** + * For read packets without a set terminator, returns the safe length of data that can be read + * without exceeding the maxLength, or forcing a resize of the buffer if at all possible. +**/ +- (NSUInteger)readLengthForNonTerm +{ + NSAssert(term == nil, @"This method does not apply to term reads"); + + if (readLength > 0) + { + // Read a specific length of data + + return readLength - bytesDone; + + // No need to avoid resizing the buffer. + // It should be resized if the buffer space is less than the requested read length. + } + else + { + // Read all available data + + NSUInteger result = READALL_CHUNKSIZE; + + if (maxLength > 0) + { + result = MIN(result, (maxLength - bytesDone)); + } + + if (!bufferOwner) + { + // We did NOT create the buffer. + // It is owned by the caller. + // Avoid resizing the buffer if at all possible. + + if ([buffer length] == originalBufferLength) + { + NSUInteger buffSize = [buffer length]; + NSUInteger buffSpace = buffSize - startOffset - bytesDone; + + if (buffSpace > 0) + { + result = MIN(result, buffSpace); + } + } + } + + return result; + } +} + +/** + * For read packets with a set terminator, returns the safe length of data that can be read + * without going over a terminator, or the maxLength, or forcing a resize of the buffer if at all possible. + * + * It is assumed the terminator has not already been read. +**/ +- (NSUInteger)readLengthForTerm +{ + NSAssert(term != nil, @"This method does not apply to non-term reads"); + + // What we're going to do is look for a partial sequence of the terminator at the end of the buffer. + // If a partial sequence occurs, then we must assume the next bytes to arrive will be the rest of the term, + // and we can only read that amount. + // Otherwise, we're safe to read the entire length of the term. + + NSUInteger termLength = [term length]; + + // Shortcuts + if (bytesDone == 0) return termLength; + if (termLength == 1) return termLength; + + // i = index within buffer at which to check data + // j = length of term to check against + + NSUInteger i, j; + if (bytesDone >= termLength) + { + i = bytesDone - termLength + 1; + j = termLength - 1; + } + else + { + i = 0; + j = bytesDone; + } + + NSUInteger result = termLength; + + void *buf = [buffer mutableBytes]; + const void *termBuf = [term bytes]; + + while (i < bytesDone) + { + void *subbuf = buf + startOffset + i; + + if (memcmp(subbuf, termBuf, j) == 0) + { + result = termLength - j; + break; + } + + i++; + j--; + } + + if (maxLength > 0) + { + result = MIN(result, (maxLength - bytesDone)); + } + + if (!bufferOwner) + { + // We did NOT create the buffer. + // It is owned by the caller. + // Avoid resizing the buffer if at all possible. + + if ([buffer length] == originalBufferLength) + { + NSUInteger buffSize = [buffer length]; + NSUInteger buffSpace = buffSize - startOffset - bytesDone; + + if (buffSpace > 0) + { + result = MIN(result, buffSpace); + } + } + } + + return result; +} + +/** + * For read packets with a set terminator, + * returns the safe length of data that can be read from the given preBuffer, + * without going over a terminator or the maxLength. + * + * It is assumed the terminator has not already been read. +**/ +- (NSUInteger)readLengthForTermWithPreBuffer:(NSData *)preBuffer found:(BOOL *)foundPtr +{ + NSAssert(term != nil, @"This method does not apply to non-term reads"); + NSAssert([preBuffer length] > 0, @"Invoked with empty pre buffer!"); + + // We know that the terminator, as a whole, doesn't exist in our own buffer. + // But it is possible that a portion of it exists in our buffer. + // So we're going to look for the terminator starting with a portion of our own buffer. + // + // Example: + // + // term length = 3 bytes + // bytesDone = 5 bytes + // preBuffer length = 5 bytes + // + // If we append the preBuffer to our buffer, + // it would look like this: + // + // --------------------- + // |B|B|B|B|B|P|P|P|P|P| + // --------------------- + // + // So we start our search here: + // + // --------------------- + // |B|B|B|B|B|P|P|P|P|P| + // -------^-^-^--------- + // + // And move forwards... + // + // --------------------- + // |B|B|B|B|B|P|P|P|P|P| + // ---------^-^-^------- + // + // Until we find the terminator or reach the end. + // + // --------------------- + // |B|B|B|B|B|P|P|P|P|P| + // ---------------^-^-^- + + BOOL found = NO; + + NSUInteger termLength = [term length]; + NSUInteger preBufferLength = [preBuffer length]; + + if ((bytesDone + preBufferLength) < termLength) + { + // Not enough data for a full term sequence yet + return preBufferLength; + } + + NSUInteger maxPreBufferLength; + if (maxLength > 0) { + maxPreBufferLength = MIN(preBufferLength, (maxLength - bytesDone)); + + // Note: maxLength >= termLength + } + else { + maxPreBufferLength = preBufferLength; + } + + Byte seq[termLength]; + const void *termBuf = [term bytes]; + + NSUInteger bufLen = MIN(bytesDone, (termLength - 1)); + void *buf = [buffer mutableBytes] + startOffset + bytesDone - bufLen; + + NSUInteger preLen = termLength - bufLen; + void *pre = (void *)[preBuffer bytes]; + + NSUInteger loopCount = bufLen + maxPreBufferLength - termLength + 1; // Plus one. See example above. + + NSUInteger result = preBufferLength; + + NSUInteger i; + for (i = 0; i < loopCount; i++) + { + if (bufLen > 0) + { + // Combining bytes from buffer and preBuffer + + memcpy(seq, buf, bufLen); + memcpy(seq + bufLen, pre, preLen); + + if (memcmp(seq, termBuf, termLength) == 0) + { + result = preLen; + found = YES; + break; + } + + buf++; + bufLen--; + preLen++; + } + else + { + // Comparing directly from preBuffer + + if (memcmp(pre, termBuf, termLength) == 0) + { + NSUInteger preOffset = pre - [preBuffer bytes]; // pointer arithmetic + + result = preOffset + termLength; + found = YES; + break; + } + + pre++; + } + } + + // There is no need to avoid resizing the buffer in this particular situation. + + if (foundPtr) *foundPtr = found; + return result; +} + +/** + * Assuming pre-buffering is enabled, returns the amount of data that can be read + * without going over the maxLength. +**/ +- (NSUInteger)prebufferReadLengthForTerm +{ + NSAssert(term != nil, @"This method does not apply to non-term reads"); + + NSUInteger result = READALL_CHUNKSIZE; + + if (maxLength > 0) + { + result = MIN(result, (maxLength - bytesDone)); + } + + if (!bufferOwner) + { + // We did NOT create the buffer. + // It is owned by the caller. + // Avoid resizing the buffer if at all possible. + + if ([buffer length] == originalBufferLength) + { + NSUInteger buffSize = [buffer length]; + NSUInteger buffSpace = buffSize - startOffset - bytesDone; + + if (buffSpace > 0) + { + result = MIN(result, buffSpace); + } + } + } + + return result; +} + +/** + * For read packets with a set terminator, scans the packet buffer for the term. + * It is assumed the terminator had not been fully read prior to the new bytes. + * + * If the term is found, the number of excess bytes after the term are returned. + * If the term is not found, this method will return -1. + * + * Note: A return value of zero means the term was found at the very end. +**/ +- (NSInteger)searchForTermAfterPreBuffering:(NSUInteger)numBytes +{ + NSAssert(term != nil, @"This method does not apply to non-term reads"); + NSAssert(bytesDone >= numBytes, @"Invoked with invalid numBytes!"); + + // We try to start the search such that the first new byte read matches up with the last byte of the term. + // We continue searching forward after this until the term no longer fits into the buffer. + + NSUInteger termLength = [term length]; + const void *termBuffer = [term bytes]; + + // Remember: This method is called after the bytesDone variable has been updated. + + NSUInteger prevBytesDone = bytesDone - numBytes; + + NSUInteger i; + if (prevBytesDone >= termLength) + i = prevBytesDone - termLength + 1; + else + i = 0; + + while ((i + termLength) <= bytesDone) + { + void *subBuffer = [buffer mutableBytes] + startOffset + i; + + if(memcmp(subBuffer, termBuffer, termLength) == 0) + { + return bytesDone - (i + termLength); + } + + i++; + } + + return -1; +} + +- (void)dealloc +{ + [buffer release]; + [term release]; + [super dealloc]; +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * The AsyncWritePacket encompasses the instructions for any given write. +**/ +@interface AsyncWritePacket : NSObject +{ + @public + NSData *buffer; + NSUInteger bytesDone; + long tag; + NSTimeInterval timeout; +} +- (id)initWithData:(NSData *)d timeout:(NSTimeInterval)t tag:(long)i; +@end + +@implementation AsyncWritePacket + +- (id)initWithData:(NSData *)d timeout:(NSTimeInterval)t tag:(long)i +{ + if((self = [super init])) + { + buffer = [d retain]; + timeout = t; + tag = i; + bytesDone = 0; + } + return self; +} + +- (void)dealloc +{ + [buffer release]; + [super dealloc]; +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * The AsyncSpecialPacket encompasses special instructions for interruptions in the read/write queues. + * This class my be altered to support more than just TLS in the future. +**/ +@interface AsyncSpecialPacket : NSObject +{ + @public + NSDictionary *tlsSettings; +} +- (id)initWithTLSSettings:(NSDictionary *)settings; +@end + +@implementation AsyncSpecialPacket + +- (id)initWithTLSSettings:(NSDictionary *)settings +{ + if((self = [super init])) + { + tlsSettings = [settings copy]; + } + return self; +} + +- (void)dealloc +{ + [tlsSettings release]; + [super dealloc]; +} + +@end + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark - +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation AsyncSocket + +- (id)init +{ + return [self initWithDelegate:nil userData:0]; +} + +- (id)initWithDelegate:(id)delegate +{ + return [self initWithDelegate:delegate userData:0]; +} + +// Designated initializer. +- (id)initWithDelegate:(id)delegate userData:(long)userData +{ + if((self = [super init])) + { + theFlags = DEFAULT_PREBUFFERING ? kEnablePreBuffering : 0; + theDelegate = delegate; + theUserData = userData; + + theNativeSocket4 = 0; + theNativeSocket6 = 0; + + theSocket4 = NULL; + theSource4 = NULL; + + theSocket6 = NULL; + theSource6 = NULL; + + theRunLoop = NULL; + theReadStream = NULL; + theWriteStream = NULL; + + theConnectTimer = nil; + + theReadQueue = [[NSMutableArray alloc] initWithCapacity:READQUEUE_CAPACITY]; + theCurrentRead = nil; + theReadTimer = nil; + + partialReadBuffer = [[NSMutableData alloc] initWithCapacity:READALL_CHUNKSIZE]; + + theWriteQueue = [[NSMutableArray alloc] initWithCapacity:WRITEQUEUE_CAPACITY]; + theCurrentWrite = nil; + theWriteTimer = nil; + + // Socket context + NSAssert(sizeof(CFSocketContext) == sizeof(CFStreamClientContext), @"CFSocketContext != CFStreamClientContext"); + theContext.version = 0; + theContext.info = self; + theContext.retain = nil; + theContext.release = nil; + theContext.copyDescription = nil; + + // Default run loop modes + theRunLoopModes = [[NSArray arrayWithObject:NSDefaultRunLoopMode] retain]; + } + return self; +} + +// The socket may been initialized in a connected state and auto-released, so this should close it down cleanly. +- (void)dealloc +{ + [self close]; + [theReadQueue release]; + [theWriteQueue release]; + [theRunLoopModes release]; + [partialReadBuffer release]; + [NSObject cancelPreviousPerformRequestsWithTarget:self]; + [super dealloc]; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Accessors +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +- (long)userData +{ + return theUserData; +} + +- (void)setUserData:(long)userData +{ + theUserData = userData; +} + +- (id)delegate +{ + return theDelegate; +} + +- (void)setDelegate:(id)delegate +{ + theDelegate = delegate; +} + +- (BOOL)canSafelySetDelegate +{ + return ([theReadQueue count] == 0 && [theWriteQueue count] == 0 && theCurrentRead == nil && theCurrentWrite == nil); +} + +- (CFSocketRef)getCFSocket +{ + if(theSocket4) + return theSocket4; + else + return theSocket6; +} + +- (CFReadStreamRef)getCFReadStream +{ + return theReadStream; +} + +- (CFWriteStreamRef)getCFWriteStream +{ + return theWriteStream; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Progress +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +- (float)progressOfReadReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total +{ + // Check to make sure we're actually reading something right now, + // and that the read packet isn't an AsyncSpecialPacket (upgrade to TLS). + if (!theCurrentRead || ![theCurrentRead isKindOfClass:[AsyncReadPacket class]]) + { + if (tag != NULL) *tag = 0; + if (done != NULL) *done = 0; + if (total != NULL) *total = 0; + + return NAN; + } + + // It's only possible to know the progress of our read if we're reading to a certain length. + // If we're reading to data, we of course have no idea when the data will arrive. + // If we're reading to timeout, then we have no idea when the next chunk of data will arrive. + + NSUInteger d = theCurrentRead->bytesDone; + NSUInteger t = theCurrentRead->readLength; + + if (tag != NULL) *tag = theCurrentRead->tag; + if (done != NULL) *done = d; + if (total != NULL) *total = t; + + if (t > 0.0) + return (float)d / (float)t; + else + return 1.0F; +} + +- (float)progressOfWriteReturningTag:(long *)tag bytesDone:(NSUInteger *)done total:(NSUInteger *)total +{ + // Check to make sure we're actually writing something right now, + // and that the write packet isn't an AsyncSpecialPacket (upgrade to TLS). + if (!theCurrentWrite || ![theCurrentWrite isKindOfClass:[AsyncWritePacket class]]) + { + if (tag != NULL) *tag = 0; + if (done != NULL) *done = 0; + if (total != NULL) *total = 0; + + return NAN; + } + + NSUInteger d = theCurrentWrite->bytesDone; + NSUInteger t = [theCurrentWrite->buffer length]; + + if (tag != NULL) *tag = theCurrentWrite->tag; + if (done != NULL) *done = d; + if (total != NULL) *total = t; + + return (float)d / (float)t; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Run Loop +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +- (void)runLoopAddSource:(CFRunLoopSourceRef)source +{ + NSUInteger i, count = [theRunLoopModes count]; + for(i = 0; i < count; i++) + { + CFStringRef runLoopMode = (CFStringRef)[theRunLoopModes objectAtIndex:i]; + CFRunLoopAddSource(theRunLoop, source, runLoopMode); + } +} + +- (void)runLoopRemoveSource:(CFRunLoopSourceRef)source +{ + NSUInteger i, count = [theRunLoopModes count]; + for(i = 0; i < count; i++) + { + CFStringRef runLoopMode = (CFStringRef)[theRunLoopModes objectAtIndex:i]; + CFRunLoopRemoveSource(theRunLoop, source, runLoopMode); + } +} + +- (void)runLoopAddSource:(CFRunLoopSourceRef)source mode:(NSString *)runLoopMode +{ + CFRunLoopAddSource(theRunLoop, source, (CFStringRef)runLoopMode); +} + +- (void)runLoopRemoveSource:(CFRunLoopSourceRef)source mode:(NSString *)runLoopMode +{ + CFRunLoopRemoveSource(theRunLoop, source, (CFStringRef)runLoopMode); +} + +- (void)runLoopAddTimer:(NSTimer *)timer +{ + NSUInteger i, count = [theRunLoopModes count]; + for(i = 0; i < count; i++) + { + CFStringRef runLoopMode = (CFStringRef)[theRunLoopModes objectAtIndex:i]; + CFRunLoopAddTimer(theRunLoop, (CFRunLoopTimerRef)timer, runLoopMode); + } +} + +- (void)runLoopRemoveTimer:(NSTimer *)timer +{ + NSUInteger i, count = [theRunLoopModes count]; + for(i = 0; i < count; i++) + { + CFStringRef runLoopMode = (CFStringRef)[theRunLoopModes objectAtIndex:i]; + CFRunLoopRemoveTimer(theRunLoop, (CFRunLoopTimerRef)timer, runLoopMode); + } +} + +- (void)runLoopAddTimer:(NSTimer *)timer mode:(NSString *)runLoopMode +{ + CFRunLoopAddTimer(theRunLoop, (CFRunLoopTimerRef)timer, (CFStringRef)runLoopMode); +} + +- (void)runLoopRemoveTimer:(NSTimer *)timer mode:(NSString *)runLoopMode +{ + CFRunLoopRemoveTimer(theRunLoop, (CFRunLoopTimerRef)timer, (CFStringRef)runLoopMode); +} + +- (void)runLoopUnscheduleReadStream +{ + NSUInteger i, count = [theRunLoopModes count]; + for(i = 0; i < count; i++) + { + CFStringRef runLoopMode = (CFStringRef)[theRunLoopModes objectAtIndex:i]; + CFReadStreamUnscheduleFromRunLoop(theReadStream, theRunLoop, runLoopMode); + } + CFReadStreamSetClient(theReadStream, kCFStreamEventNone, NULL, NULL); +} + +- (void)runLoopUnscheduleWriteStream +{ + NSUInteger i, count = [theRunLoopModes count]; + for(i = 0; i < count; i++) + { + CFStringRef runLoopMode = (CFStringRef)[theRunLoopModes objectAtIndex:i]; + CFWriteStreamUnscheduleFromRunLoop(theWriteStream, theRunLoop, runLoopMode); + } + CFWriteStreamSetClient(theWriteStream, kCFStreamEventNone, NULL, NULL); +} + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Configuration +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * See the header file for a full explanation of pre-buffering. +**/ +- (void)enablePreBuffering +{ + theFlags |= kEnablePreBuffering; +} + +/** + * See the header file for a full explanation of this method. +**/ +- (BOOL)moveToRunLoop:(NSRunLoop *)runLoop +{ + NSAssert((theRunLoop == NULL) || (theRunLoop == CFRunLoopGetCurrent()), + @"moveToRunLoop must be called from within the current RunLoop!"); + + if(runLoop == nil) + { + return NO; + } + if(theRunLoop == [runLoop getCFRunLoop]) + { + return YES; + } + + [NSObject cancelPreviousPerformRequestsWithTarget:self]; + theFlags &= ~kDequeueReadScheduled; + theFlags &= ~kDequeueWriteScheduled; + + if(theReadStream && theWriteStream) + { + [self runLoopUnscheduleReadStream]; + [self runLoopUnscheduleWriteStream]; + } + + if(theSource4) [self runLoopRemoveSource:theSource4]; + if(theSource6) [self runLoopRemoveSource:theSource6]; + + // We do not retain the timers - they get retained by the runloop when we add them as a source. + // Since we're about to remove them as a source, we retain now, and release again below. + [theReadTimer retain]; + [theWriteTimer retain]; + + if(theReadTimer) [self runLoopRemoveTimer:theReadTimer]; + if(theWriteTimer) [self runLoopRemoveTimer:theWriteTimer]; + + theRunLoop = [runLoop getCFRunLoop]; + + if(theReadTimer) [self runLoopAddTimer:theReadTimer]; + if(theWriteTimer) [self runLoopAddTimer:theWriteTimer]; + + // Release timers since we retained them above + [theReadTimer release]; + [theWriteTimer release]; + + if(theSource4) [self runLoopAddSource:theSource4]; + if(theSource6) [self runLoopAddSource:theSource6]; + + if(theReadStream && theWriteStream) + { + if(![self attachStreamsToRunLoop:runLoop error:nil]) + { + return NO; + } + } + + [runLoop performSelector:@selector(maybeDequeueRead) target:self argument:nil order:0 modes:theRunLoopModes]; + [runLoop performSelector:@selector(maybeDequeueWrite) target:self argument:nil order:0 modes:theRunLoopModes]; + [runLoop performSelector:@selector(maybeScheduleDisconnect) target:self argument:nil order:0 modes:theRunLoopModes]; + + return YES; +} + +/** + * See the header file for a full explanation of this method. +**/ +- (BOOL)setRunLoopModes:(NSArray *)runLoopModes +{ + NSAssert((theRunLoop == NULL) || (theRunLoop == CFRunLoopGetCurrent()), + @"setRunLoopModes must be called from within the current RunLoop!"); + + if([runLoopModes count] == 0) + { + return NO; + } + if([theRunLoopModes isEqualToArray:runLoopModes]) + { + return YES; + } + + [NSObject cancelPreviousPerformRequestsWithTarget:self]; + theFlags &= ~kDequeueReadScheduled; + theFlags &= ~kDequeueWriteScheduled; + + if(theReadStream && theWriteStream) + { + [self runLoopUnscheduleReadStream]; + [self runLoopUnscheduleWriteStream]; + } + + if(theSource4) [self runLoopRemoveSource:theSource4]; + if(theSource6) [self runLoopRemoveSource:theSource6]; + + // We do not retain the timers - they get retained by the runloop when we add them as a source. + // Since we're about to remove them as a source, we retain now, and release again below. + [theReadTimer retain]; + [theWriteTimer retain]; + + if(theReadTimer) [self runLoopRemoveTimer:theReadTimer]; + if(theWriteTimer) [self runLoopRemoveTimer:theWriteTimer]; + + [theRunLoopModes release]; + theRunLoopModes = [runLoopModes copy]; + + if(theReadTimer) [self runLoopAddTimer:theReadTimer]; + if(theWriteTimer) [self runLoopAddTimer:theWriteTimer]; + + // Release timers since we retained them above + [theReadTimer release]; + [theWriteTimer release]; + + if(theSource4) [self runLoopAddSource:theSource4]; + if(theSource6) [self runLoopAddSource:theSource6]; + + if(theReadStream && theWriteStream) + { + // Note: theRunLoop variable is a CFRunLoop, and NSRunLoop is NOT toll-free bridged with CFRunLoop. + // So we cannot pass theRunLoop to the method below, which is expecting a NSRunLoop parameter. + // Instead we pass nil, which will result in the method properly using the current run loop. + + if(![self attachStreamsToRunLoop:nil error:nil]) + { + return NO; + } + } + + [self performSelector:@selector(maybeDequeueRead) withObject:nil afterDelay:0 inModes:theRunLoopModes]; + [self performSelector:@selector(maybeDequeueWrite) withObject:nil afterDelay:0 inModes:theRunLoopModes]; + [self performSelector:@selector(maybeScheduleDisconnect) withObject:nil afterDelay:0 inModes:theRunLoopModes]; + + return YES; +} + +- (BOOL)addRunLoopMode:(NSString *)runLoopMode +{ + NSAssert((theRunLoop == NULL) || (theRunLoop == CFRunLoopGetCurrent()), + @"addRunLoopMode must be called from within the current RunLoop!"); + + if(runLoopMode == nil) + { + return NO; + } + if([theRunLoopModes containsObject:runLoopMode]) + { + return YES; + } + + [NSObject cancelPreviousPerformRequestsWithTarget:self]; + theFlags &= ~kDequeueReadScheduled; + theFlags &= ~kDequeueWriteScheduled; + + NSArray *newRunLoopModes = [theRunLoopModes arrayByAddingObject:runLoopMode]; + [theRunLoopModes release]; + theRunLoopModes = [newRunLoopModes retain]; + + if(theReadTimer) [self runLoopAddTimer:theReadTimer mode:runLoopMode]; + if(theWriteTimer) [self runLoopAddTimer:theWriteTimer mode:runLoopMode]; + + if(theSource4) [self runLoopAddSource:theSource4 mode:runLoopMode]; + if(theSource6) [self runLoopAddSource:theSource6 mode:runLoopMode]; + + if(theReadStream && theWriteStream) + { + CFReadStreamScheduleWithRunLoop(theReadStream, CFRunLoopGetCurrent(), (CFStringRef)runLoopMode); + CFWriteStreamScheduleWithRunLoop(theWriteStream, CFRunLoopGetCurrent(), (CFStringRef)runLoopMode); + } + + [self performSelector:@selector(maybeDequeueRead) withObject:nil afterDelay:0 inModes:theRunLoopModes]; + [self performSelector:@selector(maybeDequeueWrite) withObject:nil afterDelay:0 inModes:theRunLoopModes]; + [self performSelector:@selector(maybeScheduleDisconnect) withObject:nil afterDelay:0 inModes:theRunLoopModes]; + + return YES; +} + +- (BOOL)removeRunLoopMode:(NSString *)runLoopMode +{ + NSAssert((theRunLoop == NULL) || (theRunLoop == CFRunLoopGetCurrent()), + @"addRunLoopMode must be called from within the current RunLoop!"); + + if(runLoopMode == nil) + { + return NO; + } + if(![theRunLoopModes containsObject:runLoopMode]) + { + return YES; + } + + NSMutableArray *newRunLoopModes = [[theRunLoopModes mutableCopy] autorelease]; + [newRunLoopModes removeObject:runLoopMode]; + + if([newRunLoopModes count] == 0) + { + return NO; + } + + [NSObject cancelPreviousPerformRequestsWithTarget:self]; + theFlags &= ~kDequeueReadScheduled; + theFlags &= ~kDequeueWriteScheduled; + + [theRunLoopModes release]; + theRunLoopModes = [newRunLoopModes copy]; + + if(theReadTimer) [self runLoopRemoveTimer:theReadTimer mode:runLoopMode]; + if(theWriteTimer) [self runLoopRemoveTimer:theWriteTimer mode:runLoopMode]; + + if(theSource4) [self runLoopRemoveSource:theSource4 mode:runLoopMode]; + if(theSource6) [self runLoopRemoveSource:theSource6 mode:runLoopMode]; + + if(theReadStream && theWriteStream) + { + CFReadStreamScheduleWithRunLoop(theReadStream, CFRunLoopGetCurrent(), (CFStringRef)runLoopMode); + CFWriteStreamScheduleWithRunLoop(theWriteStream, CFRunLoopGetCurrent(), (CFStringRef)runLoopMode); + } + + [self performSelector:@selector(maybeDequeueRead) withObject:nil afterDelay:0 inModes:theRunLoopModes]; + [self performSelector:@selector(maybeDequeueWrite) withObject:nil afterDelay:0 inModes:theRunLoopModes]; + [self performSelector:@selector(maybeScheduleDisconnect) withObject:nil afterDelay:0 inModes:theRunLoopModes]; + + return YES; +} + +- (NSArray *)runLoopModes +{ + return [[theRunLoopModes retain] autorelease]; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Accepting +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +- (BOOL)acceptOnPort:(UInt16)port error:(NSError **)errPtr +{ + return [self acceptOnInterface:nil port:port error:errPtr]; +} + +/** + * To accept on a certain interface, pass the address to accept on. + * To accept on any interface, pass nil or an empty string. + * To accept only connections from localhost pass "localhost" or "loopback". +**/ +- (BOOL)acceptOnInterface:(NSString *)interface port:(UInt16)port error:(NSError **)errPtr +{ + if (theDelegate == NULL) + { + [NSException raise:AsyncSocketException + format:@"Attempting to accept without a delegate. Set a delegate first."]; + } + + if (theSocket4 != NULL || theSocket6 != NULL) + { + [NSException raise:AsyncSocketException + format:@"Attempting to accept while connected or accepting connections. Disconnect first."]; + } + + // Clear queues (spurious read/write requests post disconnect) + [self emptyQueues]; + + // Set up the listen sockaddr structs if needed. + + NSData *address4 = nil, *address6 = nil; + if(interface == nil || ([interface length] == 0)) + { + // Accept on ANY address + struct sockaddr_in nativeAddr4; + nativeAddr4.sin_len = sizeof(struct sockaddr_in); + nativeAddr4.sin_family = AF_INET; + nativeAddr4.sin_port = htons(port); + nativeAddr4.sin_addr.s_addr = htonl(INADDR_ANY); + memset(&(nativeAddr4.sin_zero), 0, sizeof(nativeAddr4.sin_zero)); + + struct sockaddr_in6 nativeAddr6; + nativeAddr6.sin6_len = sizeof(struct sockaddr_in6); + nativeAddr6.sin6_family = AF_INET6; + nativeAddr6.sin6_port = htons(port); + nativeAddr6.sin6_flowinfo = 0; + nativeAddr6.sin6_addr = in6addr_any; + nativeAddr6.sin6_scope_id = 0; + + // Wrap the native address structures for CFSocketSetAddress. + address4 = [NSData dataWithBytes:&nativeAddr4 length:sizeof(nativeAddr4)]; + address6 = [NSData dataWithBytes:&nativeAddr6 length:sizeof(nativeAddr6)]; + } + else if([interface isEqualToString:@"localhost"] || [interface isEqualToString:@"loopback"]) + { + // Accept only on LOOPBACK address + struct sockaddr_in nativeAddr4; + nativeAddr4.sin_len = sizeof(struct sockaddr_in); + nativeAddr4.sin_family = AF_INET; + nativeAddr4.sin_port = htons(port); + nativeAddr4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + memset(&(nativeAddr4.sin_zero), 0, sizeof(nativeAddr4.sin_zero)); + + struct sockaddr_in6 nativeAddr6; + nativeAddr6.sin6_len = sizeof(struct sockaddr_in6); + nativeAddr6.sin6_family = AF_INET6; + nativeAddr6.sin6_port = htons(port); + nativeAddr6.sin6_flowinfo = 0; + nativeAddr6.sin6_addr = in6addr_loopback; + nativeAddr6.sin6_scope_id = 0; + + // Wrap the native address structures for CFSocketSetAddress. + address4 = [NSData dataWithBytes:&nativeAddr4 length:sizeof(nativeAddr4)]; + address6 = [NSData dataWithBytes:&nativeAddr6 length:sizeof(nativeAddr6)]; + } + else + { + NSString *portStr = [NSString stringWithFormat:@"%hu", port]; + +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 + @synchronized (getaddrinfoLock) +#endif + { + struct addrinfo hints, *res, *res0; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + hints.ai_flags = AI_PASSIVE; + + int error = getaddrinfo([interface UTF8String], [portStr UTF8String], &hints, &res0); + + if(error) + { + if(errPtr) + { + NSString *errMsg = [NSString stringWithCString:gai_strerror(error) encoding:NSASCIIStringEncoding]; + NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + + *errPtr = [NSError errorWithDomain:@"kCFStreamErrorDomainNetDB" code:error userInfo:info]; + } + } + + for(res = res0; res; res = res->ai_next) + { + if(!address4 && (res->ai_family == AF_INET)) + { + // Found IPv4 address + // Wrap the native address structures for CFSocketSetAddress. + address4 = [NSData dataWithBytes:res->ai_addr length:res->ai_addrlen]; + } + else if(!address6 && (res->ai_family == AF_INET6)) + { + // Found IPv6 address + // Wrap the native address structures for CFSocketSetAddress. + address6 = [NSData dataWithBytes:res->ai_addr length:res->ai_addrlen]; + } + } + freeaddrinfo(res0); + } + + if(!address4 && !address6) return NO; + } + + // Create the sockets. + + if (address4) + { + theSocket4 = [self newAcceptSocketForAddress:address4 error:errPtr]; + if (theSocket4 == NULL) goto Failed; + } + + if (address6) + { + theSocket6 = [self newAcceptSocketForAddress:address6 error:errPtr]; + + // Note: The iPhone doesn't currently support IPv6 + +#if !TARGET_OS_IPHONE + if (theSocket6 == NULL) goto Failed; +#endif + } + + // Attach the sockets to the run loop so that callback methods work + + [self attachSocketsToRunLoop:nil error:nil]; + + // Set the SO_REUSEADDR flags. + + int reuseOn = 1; + if (theSocket4) setsockopt(CFSocketGetNative(theSocket4), SOL_SOCKET, SO_REUSEADDR, &reuseOn, sizeof(reuseOn)); + if (theSocket6) setsockopt(CFSocketGetNative(theSocket6), SOL_SOCKET, SO_REUSEADDR, &reuseOn, sizeof(reuseOn)); + + // Set the local bindings which causes the sockets to start listening. + + CFSocketError err; + if (theSocket4) + { + err = CFSocketSetAddress(theSocket4, (CFDataRef)address4); + if (err != kCFSocketSuccess) goto Failed; + + //NSLog(@"theSocket4: %hu", [self localPortFromCFSocket4:theSocket4]); + } + + if(port == 0 && theSocket4 && theSocket6) + { + // The user has passed in port 0, which means he wants to allow the kernel to choose the port for them + // However, the kernel will choose a different port for both theSocket4 and theSocket6 + // So we grab the port the kernel choose for theSocket4, and set it as the port for theSocket6 + UInt16 chosenPort = [self localPortFromCFSocket4:theSocket4]; + + struct sockaddr_in6 *pSockAddr6 = (struct sockaddr_in6 *)[address6 bytes]; + pSockAddr6->sin6_port = htons(chosenPort); + } + + if (theSocket6) + { + err = CFSocketSetAddress(theSocket6, (CFDataRef)address6); + if (err != kCFSocketSuccess) goto Failed; + + //NSLog(@"theSocket6: %hu", [self localPortFromCFSocket6:theSocket6]); + } + + theFlags |= kDidStartDelegate; + return YES; + +Failed: + if(errPtr) *errPtr = [self getSocketError]; + if(theSocket4 != NULL) + { + CFSocketInvalidate(theSocket4); + CFRelease(theSocket4); + theSocket4 = NULL; + } + if(theSocket6 != NULL) + { + CFSocketInvalidate(theSocket6); + CFRelease(theSocket6); + theSocket6 = NULL; + } + return NO; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Connecting +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +- (BOOL)connectToHost:(NSString*)hostname onPort:(UInt16)port error:(NSError **)errPtr +{ + return [self connectToHost:hostname onPort:port withTimeout:-1 error:errPtr]; +} + +/** + * This method creates an initial CFReadStream and CFWriteStream to the given host on the given port. + * The connection is then opened, and the corresponding CFSocket will be extracted after the connection succeeds. + * + * Thus the delegate will have access to the CFReadStream and CFWriteStream prior to connection, + * specifically in the onSocketWillConnect: method. +**/ +- (BOOL)connectToHost:(NSString *)hostname + onPort:(UInt16)port + withTimeout:(NSTimeInterval)timeout + error:(NSError **)errPtr +{ + if(theDelegate == NULL) + { + [NSException raise:AsyncSocketException + format:@"Attempting to connect without a delegate. Set a delegate first."]; + } + + if(![self isDisconnected]) + { + [NSException raise:AsyncSocketException + format:@"Attempting to connect while connected or accepting connections. Disconnect first."]; + } + + // Clear queues (spurious read/write requests post disconnect) + [self emptyQueues]; + + if(![self createStreamsToHost:hostname onPort:port error:errPtr]) goto Failed; + if(![self attachStreamsToRunLoop:nil error:errPtr]) goto Failed; + if(![self configureStreamsAndReturnError:errPtr]) goto Failed; + if(![self openStreamsAndReturnError:errPtr]) goto Failed; + + [self startConnectTimeout:timeout]; + theFlags |= kDidStartDelegate; + + return YES; + +Failed: + [self close]; + return NO; +} + +- (BOOL)connectToAddress:(NSData *)remoteAddr error:(NSError **)errPtr +{ + return [self connectToAddress:remoteAddr viaInterfaceAddress:nil withTimeout:-1 error:errPtr]; +} + +/** + * This method creates an initial CFSocket to the given address. + * The connection is then opened, and the corresponding CFReadStream and CFWriteStream will be + * created from the low-level sockets after the connection succeeds. + * + * Thus the delegate will have access to the CFSocket and CFSocketNativeHandle (BSD socket) prior to connection, + * specifically in the onSocketWillConnect: method. + * + * Note: The NSData parameter is expected to be a sockaddr structure. For example, an NSData object returned from + * NSNetservice addresses method. + * If you have an existing struct sockaddr you can convert it to an NSData object like so: + * struct sockaddr sa -> NSData *dsa = [NSData dataWithBytes:&remoteAddr length:remoteAddr.sa_len]; + * struct sockaddr *sa -> NSData *dsa = [NSData dataWithBytes:remoteAddr length:remoteAddr->sa_len]; +**/ +- (BOOL)connectToAddress:(NSData *)remoteAddr withTimeout:(NSTimeInterval)timeout error:(NSError **)errPtr +{ + return [self connectToAddress:remoteAddr viaInterfaceAddress:nil withTimeout:timeout error:errPtr]; +} + +/** + * This method is similar to the one above, but allows you to specify which socket interface + * the connection should run over. E.g. ethernet, wifi, bluetooth, etc. +**/ +- (BOOL)connectToAddress:(NSData *)remoteAddr + viaInterfaceAddress:(NSData *)interfaceAddr + withTimeout:(NSTimeInterval)timeout + error:(NSError **)errPtr +{ + if (theDelegate == NULL) + { + [NSException raise:AsyncSocketException + format:@"Attempting to connect without a delegate. Set a delegate first."]; + } + + if (![self isDisconnected]) + { + [NSException raise:AsyncSocketException + format:@"Attempting to connect while connected or accepting connections. Disconnect first."]; + } + + // Clear queues (spurious read/write requests post disconnect) + [self emptyQueues]; + + if(![self createSocketForAddress:remoteAddr error:errPtr]) goto Failed; + if(![self bindSocketToAddress:interfaceAddr error:errPtr]) goto Failed; + if(![self attachSocketsToRunLoop:nil error:errPtr]) goto Failed; + if(![self configureSocketAndReturnError:errPtr]) goto Failed; + if(![self connectSocketToAddress:remoteAddr error:errPtr]) goto Failed; + + [self startConnectTimeout:timeout]; + theFlags |= kDidStartDelegate; + + return YES; + +Failed: + [self close]; + return NO; +} + +- (void)startConnectTimeout:(NSTimeInterval)timeout +{ + if(timeout >= 0.0) + { + theConnectTimer = [NSTimer timerWithTimeInterval:timeout + target:self + selector:@selector(doConnectTimeout:) + userInfo:nil + repeats:NO]; + [self runLoopAddTimer:theConnectTimer]; + } +} + +- (void)endConnectTimeout +{ + [theConnectTimer invalidate]; + theConnectTimer = nil; +} + +- (void)doConnectTimeout:(NSTimer *)timer +{ + [self endConnectTimeout]; + [self closeWithError:[self getConnectTimeoutError]]; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Socket Implementation +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * Creates the accept sockets. + * Returns true if either IPv4 or IPv6 is created. + * If either is missing, an error is returned (even though the method may return true). +**/ +- (CFSocketRef)newAcceptSocketForAddress:(NSData *)addr error:(NSError **)errPtr +{ + struct sockaddr *pSockAddr = (struct sockaddr *)[addr bytes]; + int addressFamily = pSockAddr->sa_family; + + CFSocketRef theSocket = CFSocketCreate(kCFAllocatorDefault, + addressFamily, + SOCK_STREAM, + 0, + kCFSocketAcceptCallBack, // Callback flags + (CFSocketCallBack)&MyCFSocketCallback, // Callback method + &theContext); + + if(theSocket == NULL) + { + if(errPtr) *errPtr = [self getSocketError]; + } + + return theSocket; +} + +- (BOOL)createSocketForAddress:(NSData *)remoteAddr error:(NSError **)errPtr +{ + struct sockaddr *pSockAddr = (struct sockaddr *)[remoteAddr bytes]; + + if(pSockAddr->sa_family == AF_INET) + { + theSocket4 = CFSocketCreate(NULL, // Default allocator + PF_INET, // Protocol Family + SOCK_STREAM, // Socket Type + IPPROTO_TCP, // Protocol + kCFSocketConnectCallBack, // Callback flags + (CFSocketCallBack)&MyCFSocketCallback, // Callback method + &theContext); // Socket Context + + if(theSocket4 == NULL) + { + if (errPtr) *errPtr = [self getSocketError]; + return NO; + } + } + else if(pSockAddr->sa_family == AF_INET6) + { + theSocket6 = CFSocketCreate(NULL, // Default allocator + PF_INET6, // Protocol Family + SOCK_STREAM, // Socket Type + IPPROTO_TCP, // Protocol + kCFSocketConnectCallBack, // Callback flags + (CFSocketCallBack)&MyCFSocketCallback, // Callback method + &theContext); // Socket Context + + if(theSocket6 == NULL) + { + if (errPtr) *errPtr = [self getSocketError]; + return NO; + } + } + else + { + if (errPtr) + { + NSString *errMsg = @"Remote address is not IPv4 or IPv6"; + NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + + *errPtr = [NSError errorWithDomain:AsyncSocketErrorDomain code:AsyncSocketCFSocketError userInfo:info]; + } + return NO; + } + + return YES; +} + +- (BOOL)bindSocketToAddress:(NSData *)interfaceAddr error:(NSError **)errPtr +{ + if (interfaceAddr == nil) return YES; + + struct sockaddr *pSockAddr = (struct sockaddr *)[interfaceAddr bytes]; + + CFSocketRef theSocket = (theSocket4 != NULL) ? theSocket4 : theSocket6; + NSAssert((theSocket != NULL), @"bindSocketToAddress called without valid socket"); + + CFSocketNativeHandle nativeSocket = CFSocketGetNative(theSocket); + + if (pSockAddr->sa_family == AF_INET || pSockAddr->sa_family == AF_INET6) + { + int result = bind(nativeSocket, pSockAddr, (socklen_t)[interfaceAddr length]); + if (result != 0) + { + if (errPtr) *errPtr = [self getErrnoError]; + return NO; + } + } + else + { + if (errPtr) + { + NSString *errMsg = @"Interface address is not IPv4 or IPv6"; + NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + + *errPtr = [NSError errorWithDomain:AsyncSocketErrorDomain code:AsyncSocketCFSocketError userInfo:info]; + } + return NO; + } + + return YES; +} + +/** + * Adds the CFSocket's to the run-loop so that callbacks will work properly. +**/ +- (BOOL)attachSocketsToRunLoop:(NSRunLoop *)runLoop error:(NSError **)errPtr +{ + // Get the CFRunLoop to which the socket should be attached. + theRunLoop = (runLoop == nil) ? CFRunLoopGetCurrent() : [runLoop getCFRunLoop]; + + if(theSocket4) + { + theSource4 = CFSocketCreateRunLoopSource (kCFAllocatorDefault, theSocket4, 0); + [self runLoopAddSource:theSource4]; + } + + if(theSocket6) + { + theSource6 = CFSocketCreateRunLoopSource (kCFAllocatorDefault, theSocket6, 0); + [self runLoopAddSource:theSource6]; + } + + return YES; +} + +/** + * Allows the delegate method to configure the CFSocket or CFNativeSocket as desired before we connect. + * Note that the CFReadStream and CFWriteStream will not be available until after the connection is opened. +**/ +- (BOOL)configureSocketAndReturnError:(NSError **)errPtr +{ + // Call the delegate method for further configuration. + if([theDelegate respondsToSelector:@selector(onSocketWillConnect:)]) + { + if([theDelegate onSocketWillConnect:self] == NO) + { + if (errPtr) *errPtr = [self getAbortError]; + return NO; + } + } + return YES; +} + +- (BOOL)connectSocketToAddress:(NSData *)remoteAddr error:(NSError **)errPtr +{ + // Start connecting to the given address in the background + // The MyCFSocketCallback method will be called when the connection succeeds or fails + if(theSocket4) + { + CFSocketError err = CFSocketConnectToAddress(theSocket4, (CFDataRef)remoteAddr, -1); + if(err != kCFSocketSuccess) + { + if (errPtr) *errPtr = [self getSocketError]; + return NO; + } + } + else if(theSocket6) + { + CFSocketError err = CFSocketConnectToAddress(theSocket6, (CFDataRef)remoteAddr, -1); + if(err != kCFSocketSuccess) + { + if (errPtr) *errPtr = [self getSocketError]; + return NO; + } + } + + return YES; +} + +/** + * Attempt to make the new socket. + * If an error occurs, ignore this event. +**/ +- (void)doAcceptFromSocket:(CFSocketRef)parentSocket withNewNativeSocket:(CFSocketNativeHandle)newNativeSocket +{ + if(newNativeSocket) + { + // New socket inherits same delegate and run loop modes. + // Note: We use [self class] to support subclassing AsyncSocket. + AsyncSocket *newSocket = [[[[self class] alloc] initWithDelegate:theDelegate] autorelease]; + [newSocket setRunLoopModes:theRunLoopModes]; + + if(![newSocket createStreamsFromNative:newNativeSocket error:nil]) + goto Failed; + + if (parentSocket == theSocket4) + newSocket->theNativeSocket4 = newNativeSocket; + else + newSocket->theNativeSocket6 = newNativeSocket; + + if ([theDelegate respondsToSelector:@selector(onSocket:didAcceptNewSocket:)]) + [theDelegate onSocket:self didAcceptNewSocket:newSocket]; + + newSocket->theFlags |= kDidStartDelegate; + + NSRunLoop *runLoop = nil; + if ([theDelegate respondsToSelector:@selector(onSocket:wantsRunLoopForNewSocket:)]) + { + runLoop = [theDelegate onSocket:self wantsRunLoopForNewSocket:newSocket]; + } + + if(![newSocket attachStreamsToRunLoop:runLoop error:nil]) goto Failed; + if(![newSocket configureStreamsAndReturnError:nil]) goto Failed; + if(![newSocket openStreamsAndReturnError:nil]) goto Failed; + + return; + + Failed: + [newSocket close]; + } +} + +/** + * This method is called as a result of connectToAddress:withTimeout:error:. + * At this point we have an open CFSocket from which we need to create our read and write stream. +**/ +- (void)doSocketOpen:(CFSocketRef)sock withCFSocketError:(CFSocketError)socketError +{ + NSParameterAssert ((sock == theSocket4) || (sock == theSocket6)); + + if(socketError == kCFSocketTimeout || socketError == kCFSocketError) + { + [self closeWithError:[self getSocketError]]; + return; + } + + // Get the underlying native (BSD) socket + CFSocketNativeHandle nativeSocket = CFSocketGetNative(sock); + + // Store a reference to it + if (sock == theSocket4) + theNativeSocket4 = nativeSocket; + else + theNativeSocket6 = nativeSocket; + + // Setup the CFSocket so that invalidating it will not close the underlying native socket + CFSocketSetSocketFlags(sock, 0); + + // Invalidate and release the CFSocket - All we need from here on out is the nativeSocket. + // Note: If we don't invalidate the CFSocket (leaving the native socket open) + // then theReadStream and theWriteStream won't function properly. + // Specifically, their callbacks won't work, with the exception of kCFStreamEventOpenCompleted. + // + // This is likely due to the mixture of the CFSocketCreateWithNative method, + // along with the CFStreamCreatePairWithSocket method. + // The documentation for CFSocketCreateWithNative states: + // + // If a CFSocket object already exists for sock, + // the function returns the pre-existing object instead of creating a new object; + // the context, callout, and callBackTypes parameters are ignored in this case. + // + // So the CFStreamCreateWithNative method invokes the CFSocketCreateWithNative method, + // thinking that is creating a new underlying CFSocket for it's own purposes. + // When it does this, it uses the context/callout/callbackTypes parameters to setup everything appropriately. + // However, if a CFSocket already exists for the native socket, + // then it is returned (as per the documentation), which in turn screws up the CFStreams. + + CFSocketInvalidate(sock); + CFRelease(sock); + theSocket4 = NULL; + theSocket6 = NULL; + + NSError *err; + BOOL pass = YES; + + if(pass && ![self createStreamsFromNative:nativeSocket error:&err]) pass = NO; + if(pass && ![self attachStreamsToRunLoop:nil error:&err]) pass = NO; + if(pass && ![self openStreamsAndReturnError:&err]) pass = NO; + + if(!pass) + { + [self closeWithError:err]; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Stream Implementation +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * Creates the CFReadStream and CFWriteStream from the given native socket. + * The CFSocket may be extracted from either stream after the streams have been opened. + * + * Note: The given native socket must already be connected! +**/ +- (BOOL)createStreamsFromNative:(CFSocketNativeHandle)native error:(NSError **)errPtr +{ + // Create the socket & streams. + CFStreamCreatePairWithSocket(kCFAllocatorDefault, native, &theReadStream, &theWriteStream); + if (theReadStream == NULL || theWriteStream == NULL) + { + NSError *err = [self getStreamError]; + + NSLog(@"AsyncSocket %p couldn't create streams from accepted socket: %@", self, err); + + if (errPtr) *errPtr = err; + return NO; + } + + // Ensure the CF & BSD socket is closed when the streams are closed. + CFReadStreamSetProperty(theReadStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue); + CFWriteStreamSetProperty(theWriteStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue); + + return YES; +} + +/** + * Creates the CFReadStream and CFWriteStream from the given hostname and port number. + * The CFSocket may be extracted from either stream after the streams have been opened. +**/ +- (BOOL)createStreamsToHost:(NSString *)hostname onPort:(UInt16)port error:(NSError **)errPtr +{ + // Create the socket & streams. + CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, (CFStringRef)hostname, port, &theReadStream, &theWriteStream); + if (theReadStream == NULL || theWriteStream == NULL) + { + if (errPtr) *errPtr = [self getStreamError]; + return NO; + } + + // Ensure the CF & BSD socket is closed when the streams are closed. + CFReadStreamSetProperty(theReadStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue); + CFWriteStreamSetProperty(theWriteStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue); + + return YES; +} + +- (BOOL)attachStreamsToRunLoop:(NSRunLoop *)runLoop error:(NSError **)errPtr +{ + // Get the CFRunLoop to which the socket should be attached. + theRunLoop = (runLoop == nil) ? CFRunLoopGetCurrent() : [runLoop getCFRunLoop]; + + // Setup read stream callbacks + + CFOptionFlags readStreamEvents = kCFStreamEventHasBytesAvailable | + kCFStreamEventErrorOccurred | + kCFStreamEventEndEncountered | + kCFStreamEventOpenCompleted; + + if (!CFReadStreamSetClient(theReadStream, + readStreamEvents, + (CFReadStreamClientCallBack)&MyCFReadStreamCallback, + (CFStreamClientContext *)(&theContext))) + { + NSError *err = [self getStreamError]; + + NSLog (@"AsyncSocket %p couldn't attach read stream to run-loop,", self); + NSLog (@"Error: %@", err); + + if (errPtr) *errPtr = err; + return NO; + } + + // Setup write stream callbacks + + CFOptionFlags writeStreamEvents = kCFStreamEventCanAcceptBytes | + kCFStreamEventErrorOccurred | + kCFStreamEventEndEncountered | + kCFStreamEventOpenCompleted; + + if (!CFWriteStreamSetClient (theWriteStream, + writeStreamEvents, + (CFWriteStreamClientCallBack)&MyCFWriteStreamCallback, + (CFStreamClientContext *)(&theContext))) + { + NSError *err = [self getStreamError]; + + NSLog (@"AsyncSocket %p couldn't attach write stream to run-loop,", self); + NSLog (@"Error: %@", err); + + if (errPtr) *errPtr = err; + return NO; + } + + // Add read and write streams to run loop + + NSUInteger i, count = [theRunLoopModes count]; + for(i = 0; i < count; i++) + { + CFStringRef runLoopMode = (CFStringRef)[theRunLoopModes objectAtIndex:i]; + CFReadStreamScheduleWithRunLoop(theReadStream, theRunLoop, runLoopMode); + CFWriteStreamScheduleWithRunLoop(theWriteStream, theRunLoop, runLoopMode); + } + + return YES; +} + +/** + * Allows the delegate method to configure the CFReadStream and/or CFWriteStream as desired before we connect. + * + * If being called from a connect method, + * the CFSocket and CFNativeSocket will not be available until after the connection is opened. +**/ +- (BOOL)configureStreamsAndReturnError:(NSError **)errPtr +{ + // Call the delegate method for further configuration. + if([theDelegate respondsToSelector:@selector(onSocketWillConnect:)]) + { + if([theDelegate onSocketWillConnect:self] == NO) + { + if (errPtr) *errPtr = [self getAbortError]; + return NO; + } + } + return YES; +} + +- (BOOL)openStreamsAndReturnError:(NSError **)errPtr +{ + BOOL pass = YES; + + if(pass && !CFReadStreamOpen(theReadStream)) + { + NSLog (@"AsyncSocket %p couldn't open read stream,", self); + pass = NO; + } + + if(pass && !CFWriteStreamOpen(theWriteStream)) + { + NSLog (@"AsyncSocket %p couldn't open write stream,", self); + pass = NO; + } + + if(!pass) + { + if (errPtr) *errPtr = [self getStreamError]; + } + + return pass; +} + +/** + * Called when read or write streams open. + * When the socket is connected and both streams are open, consider the AsyncSocket instance to be ready. +**/ +- (void)doStreamOpen +{ + if ((theFlags & kDidCompleteOpenForRead) && (theFlags & kDidCompleteOpenForWrite)) + { + NSError *err = nil; + + // Get the socket + if (![self setSocketFromStreamsAndReturnError: &err]) + { + NSLog (@"AsyncSocket %p couldn't get socket from streams, %@. Disconnecting.", self, err); + [self closeWithError:err]; + return; + } + + // Stop the connection attempt timeout timer + [self endConnectTimeout]; + + if ([theDelegate respondsToSelector:@selector(onSocket:didConnectToHost:port:)]) + { + [theDelegate onSocket:self didConnectToHost:[self connectedHost] port:[self connectedPort]]; + } + + // Immediately deal with any already-queued requests. + [self maybeDequeueRead]; + [self maybeDequeueWrite]; + } +} + +- (BOOL)setSocketFromStreamsAndReturnError:(NSError **)errPtr +{ + // Get the CFSocketNativeHandle from theReadStream + CFSocketNativeHandle native; + CFDataRef nativeProp = CFReadStreamCopyProperty(theReadStream, kCFStreamPropertySocketNativeHandle); + if(nativeProp == NULL) + { + if (errPtr) *errPtr = [self getStreamError]; + return NO; + } + + CFIndex nativePropLen = CFDataGetLength(nativeProp); + CFIndex nativeLen = (CFIndex)sizeof(native); + + CFIndex len = MIN(nativePropLen, nativeLen); + + CFDataGetBytes(nativeProp, CFRangeMake(0, len), (UInt8 *)&native); + CFRelease(nativeProp); + + CFSocketRef theSocket = CFSocketCreateWithNative(kCFAllocatorDefault, native, 0, NULL, NULL); + if(theSocket == NULL) + { + if (errPtr) *errPtr = [self getSocketError]; + return NO; + } + + // Determine whether the connection was IPv4 or IPv6. + // We may already know if this was an accepted socket, + // or if the connectToAddress method was used. + // In either of the above two cases, the native socket variable would already be set. + + if (theNativeSocket4 > 0) + { + theSocket4 = theSocket; + return YES; + } + if (theNativeSocket6 > 0) + { + theSocket6 = theSocket; + return YES; + } + + CFDataRef peeraddr = CFSocketCopyPeerAddress(theSocket); + if(peeraddr == NULL) + { + NSLog(@"AsyncSocket couldn't determine IP version of socket"); + + CFRelease(theSocket); + + if (errPtr) *errPtr = [self getSocketError]; + return NO; + } + struct sockaddr *sa = (struct sockaddr *)CFDataGetBytePtr(peeraddr); + + if(sa->sa_family == AF_INET) + { + theSocket4 = theSocket; + theNativeSocket4 = native; + } + else + { + theSocket6 = theSocket; + theNativeSocket6 = native; + } + + CFRelease(peeraddr); + + return YES; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Disconnect Implementation +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// Sends error message and disconnects +- (void)closeWithError:(NSError *)err +{ + theFlags |= kClosingWithError; + + if (theFlags & kDidStartDelegate) + { + // Try to salvage what data we can. + [self recoverUnreadData]; + + // Let the delegate know, so it can try to recover if it likes. + if ([theDelegate respondsToSelector:@selector(onSocket:willDisconnectWithError:)]) + { + [theDelegate onSocket:self willDisconnectWithError:err]; + } + } + [self close]; +} + +// Prepare partially read data for recovery. +- (void)recoverUnreadData +{ + if(theCurrentRead != nil) + { + // We never finished the current read. + // Check to see if it's a normal read packet (not AsyncSpecialPacket) and if it had read anything yet. + + if(([theCurrentRead isKindOfClass:[AsyncReadPacket class]]) && (theCurrentRead->bytesDone > 0)) + { + // We need to move its data into the front of the partial read buffer. + + void *buffer = [theCurrentRead->buffer mutableBytes] + theCurrentRead->startOffset; + + [partialReadBuffer replaceBytesInRange:NSMakeRange(0, 0) + withBytes:buffer + length:theCurrentRead->bytesDone]; + } + } + + [self emptyQueues]; +} + +- (void)emptyQueues +{ + if (theCurrentRead != nil) [self endCurrentRead]; + if (theCurrentWrite != nil) [self endCurrentWrite]; + + [theReadQueue removeAllObjects]; + [theWriteQueue removeAllObjects]; + + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(maybeDequeueRead) object:nil]; + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(maybeDequeueWrite) object:nil]; + + theFlags &= ~kDequeueReadScheduled; + theFlags &= ~kDequeueWriteScheduled; +} + +/** + * Disconnects. This is called for both error and clean disconnections. +**/ +- (void)close +{ + // Empty queues + [self emptyQueues]; + + // Clear partialReadBuffer (pre-buffer and also unreadData buffer in case of error) + [partialReadBuffer replaceBytesInRange:NSMakeRange(0, [partialReadBuffer length]) withBytes:NULL length:0]; + + [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(disconnect) object:nil]; + + // Stop the connection attempt timeout timer + if (theConnectTimer != nil) + { + [self endConnectTimeout]; + } + + // Close streams. + if (theReadStream != NULL) + { + [self runLoopUnscheduleReadStream]; + CFReadStreamClose(theReadStream); + CFRelease(theReadStream); + theReadStream = NULL; + } + if (theWriteStream != NULL) + { + [self runLoopUnscheduleWriteStream]; + CFWriteStreamClose(theWriteStream); + CFRelease(theWriteStream); + theWriteStream = NULL; + } + + // Close sockets. + if (theSocket4 != NULL) + { + CFSocketInvalidate (theSocket4); + CFRelease (theSocket4); + theSocket4 = NULL; + } + if (theSocket6 != NULL) + { + CFSocketInvalidate (theSocket6); + CFRelease (theSocket6); + theSocket6 = NULL; + } + + // Closing the streams or sockets resulted in closing the underlying native socket + theNativeSocket4 = 0; + theNativeSocket6 = 0; + + // Remove run loop sources + if (theSource4 != NULL) + { + [self runLoopRemoveSource:theSource4]; + CFRelease (theSource4); + theSource4 = NULL; + } + if (theSource6 != NULL) + { + [self runLoopRemoveSource:theSource6]; + CFRelease (theSource6); + theSource6 = NULL; + } + theRunLoop = NULL; + + // If the client has passed the connect/accept method, then the connection has at least begun. + // Notify delegate that it is now ending. + BOOL shouldCallDelegate = (theFlags & kDidStartDelegate); + + // Clear all flags (except the pre-buffering flag, which should remain as is) + theFlags &= kEnablePreBuffering; + + if (shouldCallDelegate) + { + if ([theDelegate respondsToSelector: @selector(onSocketDidDisconnect:)]) + { + [theDelegate onSocketDidDisconnect:self]; + } + } + + // Do not access any instance variables after calling onSocketDidDisconnect. + // This gives the delegate freedom to release us without returning here and crashing. +} + +/** + * Disconnects immediately. Any pending reads or writes are dropped. +**/ +- (void)disconnect +{ + [self close]; +} + +/** + * Diconnects after all pending reads have completed. +**/ +- (void)disconnectAfterReading +{ + theFlags |= (kForbidReadsWrites | kDisconnectAfterReads); + + [self maybeScheduleDisconnect]; +} + +/** + * Disconnects after all pending writes have completed. +**/ +- (void)disconnectAfterWriting +{ + theFlags |= (kForbidReadsWrites | kDisconnectAfterWrites); + + [self maybeScheduleDisconnect]; +} + +/** + * Disconnects after all pending reads and writes have completed. +**/ +- (void)disconnectAfterReadingAndWriting +{ + theFlags |= (kForbidReadsWrites | kDisconnectAfterReads | kDisconnectAfterWrites); + + [self maybeScheduleDisconnect]; +} + +/** + * Schedules a call to disconnect if possible. + * That is, if all writes have completed, and we're set to disconnect after writing, + * or if all reads have completed, and we're set to disconnect after reading. +**/ +- (void)maybeScheduleDisconnect +{ + BOOL shouldDisconnect = NO; + + if(theFlags & kDisconnectAfterReads) + { + if(([theReadQueue count] == 0) && (theCurrentRead == nil)) + { + if(theFlags & kDisconnectAfterWrites) + { + if(([theWriteQueue count] == 0) && (theCurrentWrite == nil)) + { + shouldDisconnect = YES; + } + } + else + { + shouldDisconnect = YES; + } + } + } + else if(theFlags & kDisconnectAfterWrites) + { + if(([theWriteQueue count] == 0) && (theCurrentWrite == nil)) + { + shouldDisconnect = YES; + } + } + + if(shouldDisconnect) + { + [self performSelector:@selector(disconnect) withObject:nil afterDelay:0 inModes:theRunLoopModes]; + } +} + +/** + * In the event of an error, this method may be called during onSocket:willDisconnectWithError: to read + * any data that's left on the socket. +**/ +- (NSData *)unreadData +{ + // Ensure this method will only return data in the event of an error + if (!(theFlags & kClosingWithError)) return nil; + + if (theReadStream == NULL) return nil; + + NSUInteger totalBytesRead = [partialReadBuffer length]; + + BOOL error = NO; + while (!error && CFReadStreamHasBytesAvailable(theReadStream)) + { + if (totalBytesRead == [partialReadBuffer length]) + { + [partialReadBuffer increaseLengthBy:READALL_CHUNKSIZE]; + } + + // Number of bytes to read is space left in packet buffer. + NSUInteger bytesToRead = [partialReadBuffer length] - totalBytesRead; + + // Read data into packet buffer + UInt8 *packetbuf = (UInt8 *)( [partialReadBuffer mutableBytes] + totalBytesRead ); + + CFIndex result = CFReadStreamRead(theReadStream, packetbuf, bytesToRead); + + // Check results + if (result < 0) + { + error = YES; + } + else + { + CFIndex bytesRead = result; + + totalBytesRead += bytesRead; + } + } + + [partialReadBuffer setLength:totalBytesRead]; + + return partialReadBuffer; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Errors +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * Returns a standard error object for the current errno value. + * Errno is used for low-level BSD socket errors. +**/ +- (NSError *)getErrnoError +{ + NSString *errorMsg = [NSString stringWithUTF8String:strerror(errno)]; + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:errorMsg forKey:NSLocalizedDescriptionKey]; + + return [NSError errorWithDomain:NSPOSIXErrorDomain code:errno userInfo:userInfo]; +} + +/** + * Returns a standard error message for a CFSocket error. + * Unfortunately, CFSocket offers no feedback on its errors. +**/ +- (NSError *)getSocketError +{ + NSString *errMsg = NSLocalizedStringWithDefaultValue(@"AsyncSocketCFSocketError", + @"AsyncSocket", [NSBundle mainBundle], + @"General CFSocket error", nil); + + NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + + return [NSError errorWithDomain:AsyncSocketErrorDomain code:AsyncSocketCFSocketError userInfo:info]; +} + +- (NSError *)getStreamError +{ + CFStreamError err; + if (theReadStream != NULL) + { + err = CFReadStreamGetError (theReadStream); + if (err.error != 0) return [self errorFromCFStreamError: err]; + } + + if (theWriteStream != NULL) + { + err = CFWriteStreamGetError (theWriteStream); + if (err.error != 0) return [self errorFromCFStreamError: err]; + } + + return nil; +} + +/** + * Returns a standard AsyncSocket abort error. +**/ +- (NSError *)getAbortError +{ + NSString *errMsg = NSLocalizedStringWithDefaultValue(@"AsyncSocketCanceledError", + @"AsyncSocket", [NSBundle mainBundle], + @"Connection canceled", nil); + + NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + + return [NSError errorWithDomain:AsyncSocketErrorDomain code:AsyncSocketCanceledError userInfo:info]; +} + +/** + * Returns a standard AsyncSocket connect timeout error. +**/ +- (NSError *)getConnectTimeoutError +{ + NSString *errMsg = NSLocalizedStringWithDefaultValue(@"AsyncSocketConnectTimeoutError", + @"AsyncSocket", [NSBundle mainBundle], + @"Attempt to connect to host timed out", nil); + + NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + + return [NSError errorWithDomain:AsyncSocketErrorDomain code:AsyncSocketConnectTimeoutError userInfo:info]; +} + +/** + * Returns a standard AsyncSocket maxed out error. +**/ +- (NSError *)getReadMaxedOutError +{ + NSString *errMsg = NSLocalizedStringWithDefaultValue(@"AsyncSocketReadMaxedOutError", + @"AsyncSocket", [NSBundle mainBundle], + @"Read operation reached set maximum length", nil); + + NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + + return [NSError errorWithDomain:AsyncSocketErrorDomain code:AsyncSocketReadMaxedOutError userInfo:info]; +} + +/** + * Returns a standard AsyncSocket read timeout error. +**/ +- (NSError *)getReadTimeoutError +{ + NSString *errMsg = NSLocalizedStringWithDefaultValue(@"AsyncSocketReadTimeoutError", + @"AsyncSocket", [NSBundle mainBundle], + @"Read operation timed out", nil); + + NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + + return [NSError errorWithDomain:AsyncSocketErrorDomain code:AsyncSocketReadTimeoutError userInfo:info]; +} + +/** + * Returns a standard AsyncSocket write timeout error. +**/ +- (NSError *)getWriteTimeoutError +{ + NSString *errMsg = NSLocalizedStringWithDefaultValue(@"AsyncSocketWriteTimeoutError", + @"AsyncSocket", [NSBundle mainBundle], + @"Write operation timed out", nil); + + NSDictionary *info = [NSDictionary dictionaryWithObject:errMsg forKey:NSLocalizedDescriptionKey]; + + return [NSError errorWithDomain:AsyncSocketErrorDomain code:AsyncSocketWriteTimeoutError userInfo:info]; +} + +- (NSError *)errorFromCFStreamError:(CFStreamError)err +{ + if (err.domain == 0 && err.error == 0) return nil; + + // Can't use switch; these constants aren't int literals. + NSString *domain = @"CFStreamError (unlisted domain)"; + NSString *message = nil; + + if(err.domain == kCFStreamErrorDomainPOSIX) { + domain = NSPOSIXErrorDomain; + } + else if(err.domain == kCFStreamErrorDomainMacOSStatus) { + domain = NSOSStatusErrorDomain; + } + else if(err.domain == kCFStreamErrorDomainMach) { + domain = NSMachErrorDomain; + } + else if(err.domain == kCFStreamErrorDomainNetDB) + { + domain = @"kCFStreamErrorDomainNetDB"; + message = [NSString stringWithCString:gai_strerror(err.error) encoding:NSASCIIStringEncoding]; + } + else if(err.domain == kCFStreamErrorDomainNetServices) { + domain = @"kCFStreamErrorDomainNetServices"; + } + else if(err.domain == kCFStreamErrorDomainSOCKS) { + domain = @"kCFStreamErrorDomainSOCKS"; + } + else if(err.domain == kCFStreamErrorDomainSystemConfiguration) { + domain = @"kCFStreamErrorDomainSystemConfiguration"; + } + else if(err.domain == kCFStreamErrorDomainSSL) { + domain = @"kCFStreamErrorDomainSSL"; + } + + NSDictionary *info = nil; + if(message != nil) + { + info = [NSDictionary dictionaryWithObject:message forKey:NSLocalizedDescriptionKey]; + } + return [NSError errorWithDomain:domain code:err.error userInfo:info]; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Diagnostics +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +- (BOOL)isDisconnected +{ + if (theNativeSocket4 > 0) return NO; + if (theNativeSocket6 > 0) return NO; + + if (theSocket4) return NO; + if (theSocket6) return NO; + + if (theReadStream) return NO; + if (theWriteStream) return NO; + + return YES; +} + +- (BOOL)isConnected +{ + return [self areStreamsConnected]; +} + +- (NSString *)connectedHost +{ + if(theSocket4) + return [self connectedHostFromCFSocket4:theSocket4]; + if(theSocket6) + return [self connectedHostFromCFSocket6:theSocket6]; + + if(theNativeSocket4 > 0) + return [self connectedHostFromNativeSocket4:theNativeSocket4]; + if(theNativeSocket6 > 0) + return [self connectedHostFromNativeSocket6:theNativeSocket6]; + + return nil; +} + +- (UInt16)connectedPort +{ + if(theSocket4) + return [self connectedPortFromCFSocket4:theSocket4]; + if(theSocket6) + return [self connectedPortFromCFSocket6:theSocket6]; + + if(theNativeSocket4 > 0) + return [self connectedPortFromNativeSocket4:theNativeSocket4]; + if(theNativeSocket6 > 0) + return [self connectedPortFromNativeSocket6:theNativeSocket6]; + + return 0; +} + +- (NSString *)localHost +{ + if(theSocket4) + return [self localHostFromCFSocket4:theSocket4]; + if(theSocket6) + return [self localHostFromCFSocket6:theSocket6]; + + if(theNativeSocket4 > 0) + return [self localHostFromNativeSocket4:theNativeSocket4]; + if(theNativeSocket6 > 0) + return [self localHostFromNativeSocket6:theNativeSocket6]; + + return nil; +} + +- (UInt16)localPort +{ + if(theSocket4) + return [self localPortFromCFSocket4:theSocket4]; + if(theSocket6) + return [self localPortFromCFSocket6:theSocket6]; + + if(theNativeSocket4 > 0) + return [self localPortFromNativeSocket4:theNativeSocket4]; + if(theNativeSocket6 > 0) + return [self localPortFromNativeSocket6:theNativeSocket6]; + + return 0; +} + +- (NSString *)connectedHost4 +{ + if(theSocket4) + return [self connectedHostFromCFSocket4:theSocket4]; + if(theNativeSocket4 > 0) + return [self connectedHostFromNativeSocket4:theNativeSocket4]; + + return nil; +} + +- (NSString *)connectedHost6 +{ + if(theSocket6) + return [self connectedHostFromCFSocket6:theSocket6]; + if(theNativeSocket6 > 0) + return [self connectedHostFromNativeSocket6:theNativeSocket6]; + + return nil; +} + +- (UInt16)connectedPort4 +{ + if(theSocket4) + return [self connectedPortFromCFSocket4:theSocket4]; + if(theNativeSocket4 > 0) + return [self connectedPortFromNativeSocket4:theNativeSocket4]; + + return 0; +} + +- (UInt16)connectedPort6 +{ + if(theSocket6) + return [self connectedPortFromCFSocket6:theSocket6]; + if(theNativeSocket6 > 0) + return [self connectedPortFromNativeSocket6:theNativeSocket6]; + + return 0; +} + +- (NSString *)localHost4 +{ + if(theSocket4) + return [self localHostFromCFSocket4:theSocket4]; + if(theNativeSocket4 > 0) + return [self localHostFromNativeSocket4:theNativeSocket4]; + + return nil; +} + +- (NSString *)localHost6 +{ + if(theSocket6) + return [self localHostFromCFSocket6:theSocket6]; + if(theNativeSocket6 > 0) + return [self localHostFromNativeSocket6:theNativeSocket6]; + + return nil; +} + +- (UInt16)localPort4 +{ + if(theSocket4) + return [self localPortFromCFSocket4:theSocket4]; + if(theNativeSocket4 > 0) + return [self localPortFromNativeSocket4:theNativeSocket4]; + + return 0; +} + +- (UInt16)localPort6 +{ + if(theSocket6) + return [self localPortFromCFSocket6:theSocket6]; + if(theNativeSocket6 > 0) + return [self localPortFromNativeSocket6:theNativeSocket6]; + + return 0; +} + +- (NSString *)connectedHostFromNativeSocket4:(CFSocketNativeHandle)theNativeSocket +{ + struct sockaddr_in sockaddr4; + socklen_t sockaddr4len = sizeof(sockaddr4); + + if(getpeername(theNativeSocket, (struct sockaddr *)&sockaddr4, &sockaddr4len) < 0) + { + return nil; + } + return [self hostFromAddress4:&sockaddr4]; +} + +- (NSString *)connectedHostFromNativeSocket6:(CFSocketNativeHandle)theNativeSocket +{ + struct sockaddr_in6 sockaddr6; + socklen_t sockaddr6len = sizeof(sockaddr6); + + if(getpeername(theNativeSocket, (struct sockaddr *)&sockaddr6, &sockaddr6len) < 0) + { + return nil; + } + return [self hostFromAddress6:&sockaddr6]; +} + +- (NSString *)connectedHostFromCFSocket4:(CFSocketRef)theSocket +{ + CFDataRef peeraddr; + NSString *peerstr = nil; + + if((peeraddr = CFSocketCopyPeerAddress(theSocket))) + { + struct sockaddr_in *pSockAddr = (struct sockaddr_in *)CFDataGetBytePtr(peeraddr); + + peerstr = [self hostFromAddress4:pSockAddr]; + CFRelease (peeraddr); + } + + return peerstr; +} + +- (NSString *)connectedHostFromCFSocket6:(CFSocketRef)theSocket +{ + CFDataRef peeraddr; + NSString *peerstr = nil; + + if((peeraddr = CFSocketCopyPeerAddress(theSocket))) + { + struct sockaddr_in6 *pSockAddr = (struct sockaddr_in6 *)CFDataGetBytePtr(peeraddr); + + peerstr = [self hostFromAddress6:pSockAddr]; + CFRelease (peeraddr); + } + + return peerstr; +} + +- (UInt16)connectedPortFromNativeSocket4:(CFSocketNativeHandle)theNativeSocket +{ + struct sockaddr_in sockaddr4; + socklen_t sockaddr4len = sizeof(sockaddr4); + + if(getpeername(theNativeSocket, (struct sockaddr *)&sockaddr4, &sockaddr4len) < 0) + { + return 0; + } + return [self portFromAddress4:&sockaddr4]; +} + +- (UInt16)connectedPortFromNativeSocket6:(CFSocketNativeHandle)theNativeSocket +{ + struct sockaddr_in6 sockaddr6; + socklen_t sockaddr6len = sizeof(sockaddr6); + + if(getpeername(theNativeSocket, (struct sockaddr *)&sockaddr6, &sockaddr6len) < 0) + { + return 0; + } + return [self portFromAddress6:&sockaddr6]; +} + +- (UInt16)connectedPortFromCFSocket4:(CFSocketRef)theSocket +{ + CFDataRef peeraddr; + UInt16 peerport = 0; + + if((peeraddr = CFSocketCopyPeerAddress(theSocket))) + { + struct sockaddr_in *pSockAddr = (struct sockaddr_in *)CFDataGetBytePtr(peeraddr); + + peerport = [self portFromAddress4:pSockAddr]; + CFRelease (peeraddr); + } + + return peerport; +} + +- (UInt16)connectedPortFromCFSocket6:(CFSocketRef)theSocket +{ + CFDataRef peeraddr; + UInt16 peerport = 0; + + if((peeraddr = CFSocketCopyPeerAddress(theSocket))) + { + struct sockaddr_in6 *pSockAddr = (struct sockaddr_in6 *)CFDataGetBytePtr(peeraddr); + + peerport = [self portFromAddress6:pSockAddr]; + CFRelease (peeraddr); + } + + return peerport; +} + +- (NSString *)localHostFromNativeSocket4:(CFSocketNativeHandle)theNativeSocket +{ + struct sockaddr_in sockaddr4; + socklen_t sockaddr4len = sizeof(sockaddr4); + + if(getsockname(theNativeSocket, (struct sockaddr *)&sockaddr4, &sockaddr4len) < 0) + { + return nil; + } + return [self hostFromAddress4:&sockaddr4]; +} + +- (NSString *)localHostFromNativeSocket6:(CFSocketNativeHandle)theNativeSocket +{ + struct sockaddr_in6 sockaddr6; + socklen_t sockaddr6len = sizeof(sockaddr6); + + if(getsockname(theNativeSocket, (struct sockaddr *)&sockaddr6, &sockaddr6len) < 0) + { + return nil; + } + return [self hostFromAddress6:&sockaddr6]; +} + +- (NSString *)localHostFromCFSocket4:(CFSocketRef)theSocket +{ + CFDataRef selfaddr; + NSString *selfstr = nil; + + if((selfaddr = CFSocketCopyAddress(theSocket))) + { + struct sockaddr_in *pSockAddr = (struct sockaddr_in *)CFDataGetBytePtr(selfaddr); + + selfstr = [self hostFromAddress4:pSockAddr]; + CFRelease (selfaddr); + } + + return selfstr; +} + +- (NSString *)localHostFromCFSocket6:(CFSocketRef)theSocket +{ + CFDataRef selfaddr; + NSString *selfstr = nil; + + if((selfaddr = CFSocketCopyAddress(theSocket))) + { + struct sockaddr_in6 *pSockAddr = (struct sockaddr_in6 *)CFDataGetBytePtr(selfaddr); + + selfstr = [self hostFromAddress6:pSockAddr]; + CFRelease (selfaddr); + } + + return selfstr; +} + +- (UInt16)localPortFromNativeSocket4:(CFSocketNativeHandle)theNativeSocket +{ + struct sockaddr_in sockaddr4; + socklen_t sockaddr4len = sizeof(sockaddr4); + + if(getsockname(theNativeSocket, (struct sockaddr *)&sockaddr4, &sockaddr4len) < 0) + { + return 0; + } + return [self portFromAddress4:&sockaddr4]; +} + +- (UInt16)localPortFromNativeSocket6:(CFSocketNativeHandle)theNativeSocket +{ + struct sockaddr_in6 sockaddr6; + socklen_t sockaddr6len = sizeof(sockaddr6); + + if(getsockname(theNativeSocket, (struct sockaddr *)&sockaddr6, &sockaddr6len) < 0) + { + return 0; + } + return [self portFromAddress6:&sockaddr6]; +} + +- (UInt16)localPortFromCFSocket4:(CFSocketRef)theSocket +{ + CFDataRef selfaddr; + UInt16 selfport = 0; + + if ((selfaddr = CFSocketCopyAddress(theSocket))) + { + struct sockaddr_in *pSockAddr = (struct sockaddr_in *)CFDataGetBytePtr(selfaddr); + + selfport = [self portFromAddress4:pSockAddr]; + CFRelease (selfaddr); + } + + return selfport; +} + +- (UInt16)localPortFromCFSocket6:(CFSocketRef)theSocket +{ + CFDataRef selfaddr; + UInt16 selfport = 0; + + if ((selfaddr = CFSocketCopyAddress(theSocket))) + { + struct sockaddr_in6 *pSockAddr = (struct sockaddr_in6 *)CFDataGetBytePtr(selfaddr); + + selfport = [self portFromAddress6:pSockAddr]; + CFRelease (selfaddr); + } + + return selfport; +} + +- (NSString *)hostFromAddress4:(struct sockaddr_in *)pSockaddr4 +{ + char addrBuf[INET_ADDRSTRLEN]; + + if(inet_ntop(AF_INET, &pSockaddr4->sin_addr, addrBuf, (socklen_t)sizeof(addrBuf)) == NULL) + { + [NSException raise:NSInternalInconsistencyException format:@"Cannot convert IPv4 address to string."]; + } + + return [NSString stringWithCString:addrBuf encoding:NSASCIIStringEncoding]; +} + +- (NSString *)hostFromAddress6:(struct sockaddr_in6 *)pSockaddr6 +{ + char addrBuf[INET6_ADDRSTRLEN]; + + if(inet_ntop(AF_INET6, &pSockaddr6->sin6_addr, addrBuf, (socklen_t)sizeof(addrBuf)) == NULL) + { + [NSException raise:NSInternalInconsistencyException format:@"Cannot convert IPv6 address to string."]; + } + + return [NSString stringWithCString:addrBuf encoding:NSASCIIStringEncoding]; +} + +- (UInt16)portFromAddress4:(struct sockaddr_in *)pSockaddr4 +{ + return ntohs(pSockaddr4->sin_port); +} + +- (UInt16)portFromAddress6:(struct sockaddr_in6 *)pSockaddr6 +{ + return ntohs(pSockaddr6->sin6_port); +} + +- (NSData *)connectedAddress +{ + // Extract address from CFSocket + + CFSocketRef theSocket; + + if (theSocket4) + theSocket = theSocket4; + else + theSocket = theSocket6; + + if (theSocket) + { + CFDataRef peeraddr = CFSocketCopyPeerAddress(theSocket); + + if (peeraddr == NULL) return nil; + + #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 + NSData *result = [NSData dataWithBytes:CFDataGetBytePtr(peeraddr) length:CFDataGetLength(peeraddr)]; + CFRelease(peeraddr); + return result; + #else + return [(NSData *)NSMakeCollectable(peeraddr) autorelease]; + #endif + } + + // Extract address from CFSocketNativeHandle + + socklen_t sockaddrlen; + CFSocketNativeHandle theNativeSocket = 0; + + if (theNativeSocket4 > 0) + { + theNativeSocket = theNativeSocket4; + sockaddrlen = sizeof(struct sockaddr_in); + } + else + { + theNativeSocket = theNativeSocket6; + sockaddrlen = sizeof(struct sockaddr_in6); + } + + NSData *result = nil; + void *sockaddr = malloc(sockaddrlen); + + if(getpeername(theNativeSocket, (struct sockaddr *)sockaddr, &sockaddrlen) >= 0) + { + result = [NSData dataWithBytesNoCopy:sockaddr length:sockaddrlen freeWhenDone:YES]; + } + else + { + free(sockaddr); + } + + return result; +} + +- (NSData *)localAddress +{ + // Extract address from CFSocket + + CFSocketRef theSocket; + + if (theSocket4) + theSocket = theSocket4; + else + theSocket = theSocket6; + + if (theSocket) + { + CFDataRef selfaddr = CFSocketCopyAddress(theSocket); + + if (selfaddr == NULL) return nil; + + #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 + NSData *result = [NSData dataWithBytes:CFDataGetBytePtr(selfaddr) length:CFDataGetLength(selfaddr)]; + CFRelease(selfaddr); + return result; + #else + return [(NSData *)NSMakeCollectable(selfaddr) autorelease]; + #endif + } + + // Extract address from CFSocketNativeHandle + + socklen_t sockaddrlen; + CFSocketNativeHandle theNativeSocket = 0; + + if (theNativeSocket4 > 0) + { + theNativeSocket = theNativeSocket4; + sockaddrlen = sizeof(struct sockaddr_in); + } + else + { + theNativeSocket = theNativeSocket6; + sockaddrlen = sizeof(struct sockaddr_in6); + } + + NSData *result = nil; + void *sockaddr = malloc(sockaddrlen); + + if(getsockname(theNativeSocket, (struct sockaddr *)sockaddr, &sockaddrlen) >= 0) + { + result = [NSData dataWithBytesNoCopy:sockaddr length:sockaddrlen freeWhenDone:YES]; + } + else + { + free(sockaddr); + } + + return result; +} + +- (BOOL)isIPv4 +{ + return (theNativeSocket4 > 0 || theSocket4 != NULL); +} + +- (BOOL)isIPv6 +{ + return (theNativeSocket6 > 0 || theSocket6 != NULL); +} + +- (BOOL)areStreamsConnected +{ + CFStreamStatus s; + + if (theReadStream != NULL) + { + s = CFReadStreamGetStatus(theReadStream); + if ( !(s == kCFStreamStatusOpen || s == kCFStreamStatusReading || s == kCFStreamStatusError) ) + return NO; + } + else return NO; + + if (theWriteStream != NULL) + { + s = CFWriteStreamGetStatus(theWriteStream); + if ( !(s == kCFStreamStatusOpen || s == kCFStreamStatusWriting || s == kCFStreamStatusError) ) + return NO; + } + else return NO; + + return YES; +} + +- (NSString *)description +{ + static const char *statstr[] = {"not open","opening","open","reading","writing","at end","closed","has error"}; + CFStreamStatus rs = (theReadStream != NULL) ? CFReadStreamGetStatus(theReadStream) : 0; + CFStreamStatus ws = (theWriteStream != NULL) ? CFWriteStreamGetStatus(theWriteStream) : 0; + + NSString *peerstr, *selfstr; + + BOOL is4 = [self isIPv4]; + BOOL is6 = [self isIPv6]; + + if (is4 || is6) + { + if (is4 && is6) + { + peerstr = [NSString stringWithFormat: @"%@/%@ %u", + [self connectedHost4], + [self connectedHost6], + [self connectedPort]]; + } + else if (is4) + { + peerstr = [NSString stringWithFormat: @"%@ %u", + [self connectedHost4], + [self connectedPort4]]; + } + else + { + peerstr = [NSString stringWithFormat: @"%@ %u", + [self connectedHost6], + [self connectedPort6]]; + } + } + else peerstr = @"nowhere"; + + if (is4 || is6) + { + if (is4 && is6) + { + selfstr = [NSString stringWithFormat: @"%@/%@ %u", + [self localHost4], + [self localHost6], + [self localPort]]; + } + else if (is4) + { + selfstr = [NSString stringWithFormat: @"%@ %u", + [self localHost4], + [self localPort4]]; + } + else + { + selfstr = [NSString stringWithFormat: @"%@ %u", + [self localHost6], + [self localPort6]]; + } + } + else selfstr = @"nowhere"; + + NSMutableString *ms = [[NSMutableString alloc] initWithCapacity:150]; + + [ms appendString:[NSString stringWithFormat:@"readLength > 0) + percentDone = (float)theCurrentRead->bytesDone / (float)theCurrentRead->readLength * 100.0F; + else + percentDone = 100.0F; + + [ms appendString: [NSString stringWithFormat:@"currently read %u bytes (%d%% done), ", + (unsigned int)[theCurrentRead->buffer length], + theCurrentRead->bytesDone ? percentDone : 0]]; + } + + if (theCurrentWrite == nil) + [ms appendString: @"no current write, "]; + else + { + int percentDone = (float)theCurrentWrite->bytesDone / (float)[theCurrentWrite->buffer length] * 100.0F; + + [ms appendString: [NSString stringWithFormat:@"currently written %u (%d%%), ", + (unsigned int)[theCurrentWrite->buffer length], + theCurrentWrite->bytesDone ? percentDone : 0]]; + } + + [ms appendString:[NSString stringWithFormat:@"read stream %p %s, ", theReadStream, statstr[rs]]]; + [ms appendString:[NSString stringWithFormat:@"write stream %p %s", theWriteStream, statstr[ws]]]; + + if(theFlags & kDisconnectAfterReads) + { + if(theFlags & kDisconnectAfterWrites) + [ms appendString: @", will disconnect after reads & writes"]; + else + [ms appendString: @", will disconnect after reads"]; + } + else if(theFlags & kDisconnectAfterWrites) + { + [ms appendString: @", will disconnect after writes"]; + } + + if (![self isConnected]) [ms appendString: @", not connected"]; + + [ms appendString:@">"]; + + return [ms autorelease]; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Reading +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +- (void)readDataWithTimeout:(NSTimeInterval)timeout tag:(long)tag +{ + [self readDataWithTimeout:timeout buffer:nil bufferOffset:0 maxLength:0 tag:tag]; +} + +- (void)readDataWithTimeout:(NSTimeInterval)timeout + buffer:(NSMutableData *)buffer + bufferOffset:(NSUInteger)offset + tag:(long)tag +{ + [self readDataWithTimeout:timeout buffer:buffer bufferOffset:offset maxLength:0 tag:tag]; +} + +- (void)readDataWithTimeout:(NSTimeInterval)timeout + buffer:(NSMutableData *)buffer + bufferOffset:(NSUInteger)offset + maxLength:(NSUInteger)length + tag:(long)tag +{ + if (offset > [buffer length]) return; + if (theFlags & kForbidReadsWrites) return; + + AsyncReadPacket *packet = [[AsyncReadPacket alloc] initWithData:buffer + startOffset:offset + maxLength:length + timeout:timeout + readLength:0 + terminator:nil + tag:tag]; + [theReadQueue addObject:packet]; + [self scheduleDequeueRead]; + + [packet release]; +} + +- (void)readDataToLength:(NSUInteger)length withTimeout:(NSTimeInterval)timeout tag:(long)tag +{ + [self readDataToLength:length withTimeout:timeout buffer:nil bufferOffset:0 tag:tag]; +} + +- (void)readDataToLength:(NSUInteger)length + withTimeout:(NSTimeInterval)timeout + buffer:(NSMutableData *)buffer + bufferOffset:(NSUInteger)offset + tag:(long)tag +{ + if (length == 0) return; + if (offset > [buffer length]) return; + if (theFlags & kForbidReadsWrites) return; + + AsyncReadPacket *packet = [[AsyncReadPacket alloc] initWithData:buffer + startOffset:offset + maxLength:0 + timeout:timeout + readLength:length + terminator:nil + tag:tag]; + [theReadQueue addObject:packet]; + [self scheduleDequeueRead]; + + [packet release]; +} + +- (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag +{ + [self readDataToData:data withTimeout:timeout buffer:nil bufferOffset:0 maxLength:0 tag:tag]; +} + +- (void)readDataToData:(NSData *)data + withTimeout:(NSTimeInterval)timeout + buffer:(NSMutableData *)buffer + bufferOffset:(NSUInteger)offset + tag:(long)tag +{ + [self readDataToData:data withTimeout:timeout buffer:buffer bufferOffset:offset maxLength:0 tag:tag]; +} + +- (void)readDataToData:(NSData *)data withTimeout:(NSTimeInterval)timeout maxLength:(NSUInteger)length tag:(long)tag +{ + [self readDataToData:data withTimeout:timeout buffer:nil bufferOffset:0 maxLength:length tag:tag]; +} + +- (void)readDataToData:(NSData *)data + withTimeout:(NSTimeInterval)timeout + buffer:(NSMutableData *)buffer + bufferOffset:(NSUInteger)offset + maxLength:(NSUInteger)length + tag:(long)tag +{ + if (data == nil || [data length] == 0) return; + if (offset > [buffer length]) return; + if (length > 0 && length < [data length]) return; + if (theFlags & kForbidReadsWrites) return; + + AsyncReadPacket *packet = [[AsyncReadPacket alloc] initWithData:buffer + startOffset:offset + maxLength:length + timeout:timeout + readLength:0 + terminator:data + tag:tag]; + [theReadQueue addObject:packet]; + [self scheduleDequeueRead]; + + [packet release]; +} + +/** + * Puts a maybeDequeueRead on the run loop. + * An assumption here is that selectors will be performed consecutively within their priority. +**/ +- (void)scheduleDequeueRead +{ + if((theFlags & kDequeueReadScheduled) == 0) + { + theFlags |= kDequeueReadScheduled; + [self performSelector:@selector(maybeDequeueRead) withObject:nil afterDelay:0 inModes:theRunLoopModes]; + } +} + +/** + * This method starts a new read, if needed. + * It is called when a user requests a read, + * or when a stream opens that may have requested reads sitting in the queue, etc. +**/ +- (void)maybeDequeueRead +{ + // Unset the flag indicating a call to this method is scheduled + theFlags &= ~kDequeueReadScheduled; + + // If we're not currently processing a read AND we have an available read stream + if((theCurrentRead == nil) && (theReadStream != NULL)) + { + if([theReadQueue count] > 0) + { + // Dequeue the next object in the write queue + theCurrentRead = [[theReadQueue objectAtIndex:0] retain]; + [theReadQueue removeObjectAtIndex:0]; + + if([theCurrentRead isKindOfClass:[AsyncSpecialPacket class]]) + { + // Attempt to start TLS + theFlags |= kStartingReadTLS; + + // This method won't do anything unless both kStartingReadTLS and kStartingWriteTLS are set + [self maybeStartTLS]; + } + else + { + // Start time-out timer + if(theCurrentRead->timeout >= 0.0) + { + theReadTimer = [NSTimer timerWithTimeInterval:theCurrentRead->timeout + target:self + selector:@selector(doReadTimeout:) + userInfo:nil + repeats:NO]; + [self runLoopAddTimer:theReadTimer]; + } + + // Immediately read, if possible + [self doBytesAvailable]; + } + } + else if(theFlags & kDisconnectAfterReads) + { + if(theFlags & kDisconnectAfterWrites) + { + if(([theWriteQueue count] == 0) && (theCurrentWrite == nil)) + { + [self disconnect]; + } + } + else + { + [self disconnect]; + } + } + } +} + +/** + * Call this method in doBytesAvailable instead of CFReadStreamHasBytesAvailable(). + * This method supports pre-buffering properly as well as the kSocketHasBytesAvailable flag. +**/ +- (BOOL)hasBytesAvailable +{ + if ((theFlags & kSocketHasBytesAvailable) || ([partialReadBuffer length] > 0)) + { + return YES; + } + else + { + return CFReadStreamHasBytesAvailable(theReadStream); + } +} + +/** + * Call this method in doBytesAvailable instead of CFReadStreamRead(). + * This method support pre-buffering properly. +**/ +- (CFIndex)readIntoBuffer:(void *)buffer maxLength:(NSUInteger)length +{ + if([partialReadBuffer length] > 0) + { + // Determine the maximum amount of data to read + NSUInteger bytesToRead = MIN(length, [partialReadBuffer length]); + + // Copy the bytes from the partial read buffer + memcpy(buffer, [partialReadBuffer bytes], (size_t)bytesToRead); + + // Remove the copied bytes from the partial read buffer + [partialReadBuffer replaceBytesInRange:NSMakeRange(0, bytesToRead) withBytes:NULL length:0]; + + return (CFIndex)bytesToRead; + } + else + { + // Unset the "has-bytes-available" flag + theFlags &= ~kSocketHasBytesAvailable; + + return CFReadStreamRead(theReadStream, (UInt8 *)buffer, length); + } +} + +/** + * This method is called when a new read is taken from the read queue or when new data becomes available on the stream. +**/ +- (void)doBytesAvailable +{ + // If data is available on the stream, but there is no read request, then we don't need to process the data yet. + // Also, if there is a read request but no read stream setup, we can't process any data yet. + if((theCurrentRead == nil) || (theReadStream == NULL)) + { + return; + } + + // Note: This method is not called if theCurrentRead is an AsyncSpecialPacket (startTLS packet) + + NSUInteger totalBytesRead = 0; + + BOOL done = NO; + BOOL socketError = NO; + BOOL maxoutError = NO; + + while(!done && !socketError && !maxoutError && [self hasBytesAvailable]) + { + BOOL didPreBuffer = NO; + BOOL didReadFromPreBuffer = NO; + + // There are 3 types of read packets: + // + // 1) Read all available data. + // 2) Read a specific length of data. + // 3) Read up to a particular terminator. + + NSUInteger bytesToRead; + + if (theCurrentRead->term != nil) + { + // Read type #3 - read up to a terminator + // + // If pre-buffering is enabled we'll read a chunk and search for the terminator. + // If the terminator is found, overflow data will be placed in the partialReadBuffer for the next read. + // + // If pre-buffering is disabled we'll be forced to read only a few bytes. + // Just enough to ensure we don't go past our term or over our max limit. + // + // If we already have data pre-buffered, we can read directly from it. + + if ([partialReadBuffer length] > 0) + { + didReadFromPreBuffer = YES; + bytesToRead = [theCurrentRead readLengthForTermWithPreBuffer:partialReadBuffer found:&done]; + } + else + { + if (theFlags & kEnablePreBuffering) + { + didPreBuffer = YES; + bytesToRead = [theCurrentRead prebufferReadLengthForTerm]; + } + else + { + bytesToRead = [theCurrentRead readLengthForTerm]; + } + } + } + else + { + // Read type #1 or #2 + + bytesToRead = [theCurrentRead readLengthForNonTerm]; + } + + // Make sure we have enough room in the buffer for our read + + NSUInteger buffSize = [theCurrentRead->buffer length]; + NSUInteger buffSpace = buffSize - theCurrentRead->startOffset - theCurrentRead->bytesDone; + + if (bytesToRead > buffSpace) + { + NSUInteger buffInc = bytesToRead - buffSpace; + + [theCurrentRead->buffer increaseLengthBy:buffInc]; + } + + // Read data into packet buffer + + void *buffer = [theCurrentRead->buffer mutableBytes] + theCurrentRead->startOffset; + void *subBuffer = buffer + theCurrentRead->bytesDone; + + CFIndex result = [self readIntoBuffer:subBuffer maxLength:bytesToRead]; + + // Check results + if (result < 0) + { + socketError = YES; + } + else + { + CFIndex bytesRead = result; + + // Update total amount read for the current read + theCurrentRead->bytesDone += bytesRead; + + // Update total amount read in this method invocation + totalBytesRead += bytesRead; + + + // Is packet done? + if (theCurrentRead->readLength > 0) + { + // Read type #2 - read a specific length of data + + done = (theCurrentRead->bytesDone == theCurrentRead->readLength); + } + else if (theCurrentRead->term != nil) + { + // Read type #3 - read up to a terminator + + if (didPreBuffer) + { + // Search for the terminating sequence within the big chunk we just read. + + NSInteger overflow = [theCurrentRead searchForTermAfterPreBuffering:result]; + + if (overflow > 0) + { + // Copy excess data into partialReadBuffer + void *overflowBuffer = buffer + theCurrentRead->bytesDone - overflow; + + [partialReadBuffer appendBytes:overflowBuffer length:overflow]; + + // Update the bytesDone variable. + theCurrentRead->bytesDone -= overflow; + + // Note: The completeCurrentRead method will trim the buffer for us. + } + + done = (overflow >= 0); + } + else if (didReadFromPreBuffer) + { + // Our 'done' variable was updated via the readLengthForTermWithPreBuffer:found: method + } + else + { + // Search for the terminating sequence at the end of the buffer + + NSUInteger termlen = [theCurrentRead->term length]; + + if(theCurrentRead->bytesDone >= termlen) + { + void *bufferEnd = buffer + (theCurrentRead->bytesDone - termlen); + + const void *seq = [theCurrentRead->term bytes]; + + done = (memcmp (bufferEnd, seq, termlen) == 0); + } + } + + if(!done && theCurrentRead->maxLength > 0) + { + // We're not done and there's a set maxLength. + // Have we reached that maxLength yet? + + if(theCurrentRead->bytesDone >= theCurrentRead->maxLength) + { + maxoutError = YES; + } + } + } + else + { + // Read type #1 - read all available data + // + // We're done when: + // - we reach maxLength (if there is a max) + // - all readable is read (see below) + + if (theCurrentRead->maxLength > 0) + { + done = (theCurrentRead->bytesDone >= theCurrentRead->maxLength); + } + } + } + } + + if (theCurrentRead->readLength <= 0 && theCurrentRead->term == nil) + { + // Read type #1 - read all available data + + if (theCurrentRead->bytesDone > 0) + { + // Ran out of bytes, so the "read-all-available-data" type packet is done + done = YES; + } + } + + if (done) + { + [self completeCurrentRead]; + if (!socketError) [self scheduleDequeueRead]; + } + else if (totalBytesRead > 0) + { + // We're not done with the readToLength or readToData yet, but we have read in some bytes + if ([theDelegate respondsToSelector:@selector(onSocket:didReadPartialDataOfLength:tag:)]) + { + [theDelegate onSocket:self didReadPartialDataOfLength:totalBytesRead tag:theCurrentRead->tag]; + } + } + + if(socketError) + { + CFStreamError err = CFReadStreamGetError(theReadStream); + [self closeWithError:[self errorFromCFStreamError:err]]; + return; + } + + if(maxoutError) + { + [self closeWithError:[self getReadMaxedOutError]]; + return; + } +} + +// Ends current read and calls delegate. +- (void)completeCurrentRead +{ + NSAssert(theCurrentRead, @"Trying to complete current read when there is no current read."); + + NSData *result; + + if (theCurrentRead->bufferOwner) + { + // We created the buffer on behalf of the user. + // Trim our buffer to be the proper size. + [theCurrentRead->buffer setLength:theCurrentRead->bytesDone]; + + result = theCurrentRead->buffer; + } + else + { + // We did NOT create the buffer. + // The buffer is owned by the caller. + // Only trim the buffer if we had to increase its size. + + if ([theCurrentRead->buffer length] > theCurrentRead->originalBufferLength) + { + NSUInteger readSize = theCurrentRead->startOffset + theCurrentRead->bytesDone; + NSUInteger origSize = theCurrentRead->originalBufferLength; + + NSUInteger buffSize = MAX(readSize, origSize); + + [theCurrentRead->buffer setLength:buffSize]; + } + + void *buffer = [theCurrentRead->buffer mutableBytes] + theCurrentRead->startOffset; + + result = [NSData dataWithBytesNoCopy:buffer length:theCurrentRead->bytesDone freeWhenDone:NO]; + } + + if([theDelegate respondsToSelector:@selector(onSocket:didReadData:withTag:)]) + { + [theDelegate onSocket:self didReadData:result withTag:theCurrentRead->tag]; + } + + // Caller may have disconnected in the above delegate method + if (theCurrentRead != nil) + { + [self endCurrentRead]; + } +} + +// Ends current read. +- (void)endCurrentRead +{ + NSAssert(theCurrentRead, @"Trying to end current read when there is no current read."); + + [theReadTimer invalidate]; + theReadTimer = nil; + + [theCurrentRead release]; + theCurrentRead = nil; +} + +- (void)doReadTimeout:(NSTimer *)timer +{ + NSTimeInterval timeoutExtension = 0.0; + + if([theDelegate respondsToSelector:@selector(onSocket:shouldTimeoutReadWithTag:elapsed:bytesDone:)]) + { + timeoutExtension = [theDelegate onSocket:self shouldTimeoutReadWithTag:theCurrentRead->tag + elapsed:theCurrentRead->timeout + bytesDone:theCurrentRead->bytesDone]; + } + + if(timeoutExtension > 0.0) + { + theCurrentRead->timeout += timeoutExtension; + + theReadTimer = [NSTimer timerWithTimeInterval:timeoutExtension + target:self + selector:@selector(doReadTimeout:) + userInfo:nil + repeats:NO]; + [self runLoopAddTimer:theReadTimer]; + } + else + { + // Do not call endCurrentRead here. + // We must allow the delegate access to any partial read in the unreadData method. + + [self closeWithError:[self getReadTimeoutError]]; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Writing +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +- (void)writeData:(NSData *)data withTimeout:(NSTimeInterval)timeout tag:(long)tag +{ + if (data == nil || [data length] == 0) return; + if (theFlags & kForbidReadsWrites) return; + + AsyncWritePacket *packet = [[AsyncWritePacket alloc] initWithData:data timeout:timeout tag:tag]; + + [theWriteQueue addObject:packet]; + [self scheduleDequeueWrite]; + + [packet release]; +} + +- (void)scheduleDequeueWrite +{ + if((theFlags & kDequeueWriteScheduled) == 0) + { + theFlags |= kDequeueWriteScheduled; + [self performSelector:@selector(maybeDequeueWrite) withObject:nil afterDelay:0 inModes:theRunLoopModes]; + } +} + +/** + * Conditionally starts a new write. + * + * IF there is not another write in process + * AND there is a write queued + * AND we have a write stream available + * + * This method also handles auto-disconnect post read/write completion. +**/ +- (void)maybeDequeueWrite +{ + // Unset the flag indicating a call to this method is scheduled + theFlags &= ~kDequeueWriteScheduled; + + // If we're not currently processing a write AND we have an available write stream + if((theCurrentWrite == nil) && (theWriteStream != NULL)) + { + if([theWriteQueue count] > 0) + { + // Dequeue the next object in the write queue + theCurrentWrite = [[theWriteQueue objectAtIndex:0] retain]; + [theWriteQueue removeObjectAtIndex:0]; + + if([theCurrentWrite isKindOfClass:[AsyncSpecialPacket class]]) + { + // Attempt to start TLS + theFlags |= kStartingWriteTLS; + + // This method won't do anything unless both kStartingReadTLS and kStartingWriteTLS are set + [self maybeStartTLS]; + } + else + { + // Start time-out timer + if(theCurrentWrite->timeout >= 0.0) + { + theWriteTimer = [NSTimer timerWithTimeInterval:theCurrentWrite->timeout + target:self + selector:@selector(doWriteTimeout:) + userInfo:nil + repeats:NO]; + [self runLoopAddTimer:theWriteTimer]; + } + + // Immediately write, if possible + [self doSendBytes]; + } + } + else if(theFlags & kDisconnectAfterWrites) + { + if(theFlags & kDisconnectAfterReads) + { + if(([theReadQueue count] == 0) && (theCurrentRead == nil)) + { + [self disconnect]; + } + } + else + { + [self disconnect]; + } + } + } +} + +/** + * Call this method in doSendBytes instead of CFWriteStreamCanAcceptBytes(). + * This method supports the kSocketCanAcceptBytes flag. +**/ +- (BOOL)canAcceptBytes +{ + if (theFlags & kSocketCanAcceptBytes) + { + return YES; + } + else + { + return CFWriteStreamCanAcceptBytes(theWriteStream); + } +} + +- (void)doSendBytes +{ + if ((theCurrentWrite == nil) || (theWriteStream == NULL)) + { + return; + } + + // Note: This method is not called if theCurrentWrite is an AsyncSpecialPacket (startTLS packet) + + NSUInteger totalBytesWritten = 0; + + BOOL done = NO; + BOOL error = NO; + + while (!done && !error && [self canAcceptBytes]) + { + // Figure out what to write + NSUInteger bytesRemaining = [theCurrentWrite->buffer length] - theCurrentWrite->bytesDone; + NSUInteger bytesToWrite = (bytesRemaining < WRITE_CHUNKSIZE) ? bytesRemaining : WRITE_CHUNKSIZE; + + UInt8 *writestart = (UInt8 *)([theCurrentWrite->buffer bytes] + theCurrentWrite->bytesDone); + + // Write + CFIndex result = CFWriteStreamWrite(theWriteStream, writestart, bytesToWrite); + + // Unset the "can accept bytes" flag + theFlags &= ~kSocketCanAcceptBytes; + + // Check results + if (result < 0) + { + error = YES; + } + else + { + CFIndex bytesWritten = result; + + // Update total amount read for the current write + theCurrentWrite->bytesDone += bytesWritten; + + // Update total amount written in this method invocation + totalBytesWritten += bytesWritten; + + // Is packet done? + done = ([theCurrentWrite->buffer length] == theCurrentWrite->bytesDone); + } + } + + if(done) + { + [self completeCurrentWrite]; + [self scheduleDequeueWrite]; + } + else if(error) + { + CFStreamError err = CFWriteStreamGetError(theWriteStream); + [self closeWithError:[self errorFromCFStreamError:err]]; + return; + } + else if (totalBytesWritten > 0) + { + // We're not done with the entire write, but we have written some bytes + if ([theDelegate respondsToSelector:@selector(onSocket:didWritePartialDataOfLength:tag:)]) + { + [theDelegate onSocket:self didWritePartialDataOfLength:totalBytesWritten tag:theCurrentWrite->tag]; + } + } +} + +// Ends current write and calls delegate. +- (void)completeCurrentWrite +{ + NSAssert(theCurrentWrite, @"Trying to complete current write when there is no current write."); + + if ([theDelegate respondsToSelector:@selector(onSocket:didWriteDataWithTag:)]) + { + [theDelegate onSocket:self didWriteDataWithTag:theCurrentWrite->tag]; + } + + if (theCurrentWrite != nil) [self endCurrentWrite]; // Caller may have disconnected. +} + +// Ends current write. +- (void)endCurrentWrite +{ + NSAssert(theCurrentWrite, @"Trying to complete current write when there is no current write."); + + [theWriteTimer invalidate]; + theWriteTimer = nil; + + [theCurrentWrite release]; + theCurrentWrite = nil; +} + +- (void)doWriteTimeout:(NSTimer *)timer +{ + NSTimeInterval timeoutExtension = 0.0; + + if([theDelegate respondsToSelector:@selector(onSocket:shouldTimeoutWriteWithTag:elapsed:bytesDone:)]) + { + timeoutExtension = [theDelegate onSocket:self shouldTimeoutWriteWithTag:theCurrentWrite->tag + elapsed:theCurrentWrite->timeout + bytesDone:theCurrentWrite->bytesDone]; + } + + if(timeoutExtension > 0.0) + { + theCurrentWrite->timeout += timeoutExtension; + + theWriteTimer = [NSTimer timerWithTimeInterval:timeoutExtension + target:self + selector:@selector(doWriteTimeout:) + userInfo:nil + repeats:NO]; + [self runLoopAddTimer:theWriteTimer]; + } + else + { + [self closeWithError:[self getWriteTimeoutError]]; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Security +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +- (void)startTLS:(NSDictionary *)tlsSettings +{ + if(tlsSettings == nil) + { + // Passing nil/NULL to CFReadStreamSetProperty will appear to work the same as passing an empty dictionary, + // but causes problems if we later try to fetch the remote host's certificate. + // + // To be exact, it causes the following to return NULL instead of the normal result: + // CFReadStreamCopyProperty(readStream, kCFStreamPropertySSLPeerCertificates) + // + // So we use an empty dictionary instead, which works perfectly. + + tlsSettings = [NSDictionary dictionary]; + } + + AsyncSpecialPacket *packet = [[AsyncSpecialPacket alloc] initWithTLSSettings:tlsSettings]; + + [theReadQueue addObject:packet]; + [self scheduleDequeueRead]; + + [theWriteQueue addObject:packet]; + [self scheduleDequeueWrite]; + + [packet release]; +} + +- (void)maybeStartTLS +{ + // We can't start TLS until: + // - All queued reads prior to the user calling StartTLS are complete + // - All queued writes prior to the user calling StartTLS are complete + // + // We'll know these conditions are met when both kStartingReadTLS and kStartingWriteTLS are set + + if((theFlags & kStartingReadTLS) && (theFlags & kStartingWriteTLS)) + { + AsyncSpecialPacket *tlsPacket = (AsyncSpecialPacket *)theCurrentRead; + + BOOL didStartOnReadStream = CFReadStreamSetProperty(theReadStream, kCFStreamPropertySSLSettings, + (CFDictionaryRef)tlsPacket->tlsSettings); + BOOL didStartOnWriteStream = CFWriteStreamSetProperty(theWriteStream, kCFStreamPropertySSLSettings, + (CFDictionaryRef)tlsPacket->tlsSettings); + + if(!didStartOnReadStream || !didStartOnWriteStream) + { + [self closeWithError:[self getSocketError]]; + } + } +} + +- (void)onTLSHandshakeSuccessful +{ + if((theFlags & kStartingReadTLS) && (theFlags & kStartingWriteTLS)) + { + theFlags &= ~kStartingReadTLS; + theFlags &= ~kStartingWriteTLS; + + if([theDelegate respondsToSelector:@selector(onSocketDidSecure:)]) + { + [theDelegate onSocketDidSecure:self]; + } + + [self endCurrentRead]; + [self endCurrentWrite]; + + [self scheduleDequeueRead]; + [self scheduleDequeueWrite]; + } +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark CF Callbacks +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +- (void)doCFSocketCallback:(CFSocketCallBackType)type + forSocket:(CFSocketRef)sock + withAddress:(NSData *)address + withData:(const void *)pData +{ + NSParameterAssert ((sock == theSocket4) || (sock == theSocket6)); + + switch (type) + { + case kCFSocketConnectCallBack: + // The data argument is either NULL or a pointer to an SInt32 error code, if the connect failed. + if(pData) + [self doSocketOpen:sock withCFSocketError:kCFSocketError]; + else + [self doSocketOpen:sock withCFSocketError:kCFSocketSuccess]; + break; + case kCFSocketAcceptCallBack: + [self doAcceptFromSocket:sock withNewNativeSocket:*((CFSocketNativeHandle *)pData)]; + break; + default: + NSLog(@"AsyncSocket %p received unexpected CFSocketCallBackType %i", self, (int)type); + break; + } +} + +- (void)doCFReadStreamCallback:(CFStreamEventType)type forStream:(CFReadStreamRef)stream +{ + NSParameterAssert(theReadStream != NULL); + + CFStreamError err; + switch (type) + { + case kCFStreamEventOpenCompleted: + theFlags |= kDidCompleteOpenForRead; + [self doStreamOpen]; + break; + case kCFStreamEventHasBytesAvailable: + if(theFlags & kStartingReadTLS) { + [self onTLSHandshakeSuccessful]; + } + else { + theFlags |= kSocketHasBytesAvailable; + [self doBytesAvailable]; + } + break; + case kCFStreamEventErrorOccurred: + case kCFStreamEventEndEncountered: + err = CFReadStreamGetError (theReadStream); + [self closeWithError: [self errorFromCFStreamError:err]]; + break; + default: + NSLog(@"AsyncSocket %p received unexpected CFReadStream callback, CFStreamEventType %i", self, (int)type); + } +} + +- (void)doCFWriteStreamCallback:(CFStreamEventType)type forStream:(CFWriteStreamRef)stream +{ + NSParameterAssert(theWriteStream != NULL); + + CFStreamError err; + switch (type) + { + case kCFStreamEventOpenCompleted: + theFlags |= kDidCompleteOpenForWrite; + [self doStreamOpen]; + break; + case kCFStreamEventCanAcceptBytes: + if(theFlags & kStartingWriteTLS) { + [self onTLSHandshakeSuccessful]; + } + else { + theFlags |= kSocketCanAcceptBytes; + [self doSendBytes]; + } + break; + case kCFStreamEventErrorOccurred: + case kCFStreamEventEndEncountered: + err = CFWriteStreamGetError (theWriteStream); + [self closeWithError: [self errorFromCFStreamError:err]]; + break; + default: + NSLog(@"AsyncSocket %p received unexpected CFWriteStream callback, CFStreamEventType %i", self, (int)type); + } +} + +/** + * This is the callback we setup for CFSocket. + * This method does nothing but forward the call to it's Objective-C counterpart +**/ +static void MyCFSocketCallback (CFSocketRef sref, CFSocketCallBackType type, CFDataRef address, const void *pData, void *pInfo) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + AsyncSocket *theSocket = [[(AsyncSocket *)pInfo retain] autorelease]; + [theSocket doCFSocketCallback:type forSocket:sref withAddress:(NSData *)address withData:pData]; + + [pool release]; +} + +/** + * This is the callback we setup for CFReadStream. + * This method does nothing but forward the call to it's Objective-C counterpart +**/ +static void MyCFReadStreamCallback (CFReadStreamRef stream, CFStreamEventType type, void *pInfo) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + AsyncSocket *theSocket = [[(AsyncSocket *)pInfo retain] autorelease]; + [theSocket doCFReadStreamCallback:type forStream:stream]; + + [pool release]; +} + +/** + * This is the callback we setup for CFWriteStream. + * This method does nothing but forward the call to it's Objective-C counterpart +**/ +static void MyCFWriteStreamCallback (CFWriteStreamRef stream, CFStreamEventType type, void *pInfo) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + AsyncSocket *theSocket = [[(AsyncSocket *)pInfo retain] autorelease]; + [theSocket doCFWriteStreamCallback:type forStream:stream]; + + [pool release]; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#pragma mark Class Methods +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// Return line separators. ++ (NSData *)CRLFData +{ + return [NSData dataWithBytes:"\x0D\x0A" length:2]; +} + ++ (NSData *)CRData +{ + return [NSData dataWithBytes:"\x0D" length:1]; +} + ++ (NSData *)LFData +{ + return [NSData dataWithBytes:"\x0A" length:1]; +} + ++ (NSData *)ZeroData +{ + return [NSData dataWithBytes:"" length:1]; +} + +@end diff --git a/EmailScheduler/MGMHTTP/MGMHTTPAddons.h b/EmailScheduler/MGMHTTP/MGMHTTPAddons.h new file mode 100644 index 0000000..91a99fe --- /dev/null +++ b/EmailScheduler/MGMHTTP/MGMHTTPAddons.h @@ -0,0 +1,38 @@ +// +// MGMHTTPAddons.h +// MGMHTTP +// +// Created by Mr. Gecko on 8/14/13. +// Copyright (c) 2014 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +#import +#import "MGMHTTPDefines.h" + +@interface NSString (MGMHTTPAddons) +- (NSString *)trim; +- (NSString *)trimQuotes; +- (NSString *)replace:(NSString *)targetString with:(NSString *)replaceString; +- (NSString *)urlEncode; +- (NSString *)urlDecode; ++ (NSString *)stringWithInteger:(MGMInteger)theInteger; ++ (NSString *)stringWithDate:(NSDate *)theDate; +@end diff --git a/EmailScheduler/MGMHTTP/MGMHTTPAddons.m b/EmailScheduler/MGMHTTP/MGMHTTPAddons.m new file mode 100644 index 0000000..c11bcc0 --- /dev/null +++ b/EmailScheduler/MGMHTTP/MGMHTTPAddons.m @@ -0,0 +1,89 @@ +// +// MGMHTTPAddons.m +// MGMHTTP +// +// Created by Mr. Gecko on 8/14/13. +// Copyright (c) 2014 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +#import "MGMHTTPAddons.h" + + +@implementation NSString (MGMHTTPAddons) +- (NSString *)trim { + return [self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; +} + +- (NSString *)trimQuotes { + return [self stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"\"'`"]]; +} + +- (NSString *)replace:(NSString *)targetString with:(NSString *)replaceString { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSMutableString *temp = [[NSMutableString alloc] init]; + NSRange replaceRange = NSMakeRange(0, [self length]); + NSRange rangeInOriginalString = replaceRange; + int replaced = 0; + + while (1) { + NSRange rangeToCopy; + NSRange foundRange = [self rangeOfString:targetString options:0 range:rangeInOriginalString]; + if (foundRange.length==0) break; + rangeToCopy = NSMakeRange(rangeInOriginalString.location, foundRange.location - rangeInOriginalString.location); + [temp appendString:[self substringWithRange:rangeToCopy]]; + [temp appendString:replaceString]; + rangeInOriginalString.length -= (NSMaxRange(foundRange)-rangeInOriginalString.location); + rangeInOriginalString.location = NSMaxRange(foundRange); + replaced++; + if ((replaced%100)==0) { + [pool drain]; + pool = [NSAutoreleasePool new]; + } + } + if (rangeInOriginalString.length>0) [temp appendString:[self substringWithRange:rangeInOriginalString]]; + [pool release]; + + return [temp autorelease]; +} + +- (NSString *)urlEncode { + NSString *result = [self stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; + CFStringRef escapedString = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)self, NULL, CFSTR("!*'();:^@&=+$,/?%#[]|"), kCFStringEncodingUTF8); + + if (escapedString!=NULL) + result = [(NSString *)escapedString autorelease]; + return result; +} + +- (NSString *)urlDecode { + return [[self replace:@"+" with:@" "] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; +} + ++ (NSString *)stringWithInteger:(MGMInteger)theInteger { + return [NSString stringWithFormat:@"%ld", theInteger]; +} ++ (NSString *)stringWithDate:(NSDate *)theDate { + NSDateFormatter *formatter = [[NSDateFormatter new] autorelease]; + [formatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT"]]; + [formatter setDateFormat:@"EEE, dd MMM yyyy HH:mm:ss zzz"]; + return [formatter stringFromDate:theDate]; +} +@end diff --git a/EmailScheduler/MGMHTTP/MGMHTTPClient.h b/EmailScheduler/MGMHTTP/MGMHTTPClient.h new file mode 100644 index 0000000..c4ebd13 --- /dev/null +++ b/EmailScheduler/MGMHTTP/MGMHTTPClient.h @@ -0,0 +1,157 @@ +// +// MGMHTTPClient.h +// MGMHTTP +// +// Created by Mr. Gecko on 8/14/13. +// Copyright (c) 2014 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +#import +#import "MGMHTTPDefines.h" + +#if TARGET_OS_IPHONE +#import +#endif + +@class AsyncSocket, MGMHTTPServer, MGMHTTPResponse; + +extern NSString * const MGMClientDisconnectedNotification; + +extern NSString * const MGMRPath; +extern NSString * const MGMREncoding; +extern NSString * const MGMGatewayInterface; +extern NSString * const MGMContentType; +extern NSString * const MGMContentLength; +extern NSString * const MGMServerProtocol; +extern NSString * const MGMRequestMethod; +extern NSString * const MGMRequestURI; +extern NSString * const MGMScriptName; +extern NSString * const MGMRemotePort; +extern NSString * const MGMServerAddress; +extern NSString * const MGMServerPort; +extern NSString * const MGMQueryString; +extern NSString * const MGMCookies; +extern NSString * const MGMPCRemoteAddress; +extern NSString * const MGMRemoteAddress; +extern NSString * const MGMClientIP; +extern NSString * const MGMForwardedFor; +extern NSString * const MGMConnection; +extern NSString * const MGMServerHeader; +extern NSString * const MGMAcceptRanges; +extern NSString * const MGMDate; + +@interface MGMHTTPClient : NSObject { + AsyncSocket *clientSocket; + MGMHTTPServer *server; +#if MGMHTTPThreaded + NSRunLoop *threadRunLoop; + NSThread *thread; +#endif + + CFHTTPMessageRef clientRequest; + NSDictionary *requestHeaders; + int numHeaders; + NSMutableDictionary *headers; + NSDictionary *getInputs; + NSDictionary *postInputs; + NSData *postData; + NSMutableDictionary *cookies; + NSMutableArray *cookiesToPost; + NSDictionary *filesUploaded; + BOOL headersPosted; + + //File Upload + NSString *fBoundary; + char fPutback[1024]; + int fReadPosition; + int fWritePosition; + int fOffset; + BOOL isMultipart; + + NSString *httpVersion; + + MGMHTTPResponse *httpResponse; + BOOL isBufferBased; + NSMutableData *responseBuffer; + BOOL isBufferSending; + + NSMutableArray *ranges; + NSMutableArray *rangesHeaders; + NSString *rangesBoundry; + int rangeIndex; + + MGMInteger requestContentLengthReceived; + + BOOL isKeepAlive; + BOOL clientDisconnected; + BOOL disconnecting; +} +- (AsyncSocket *)clientSocket; +#if MGMHTTPThreaded +- (NSRunLoop *)runLoop; +#endif + ++ (id)clientWithSocket:(AsyncSocket *)theSocket server:(MGMHTTPServer *)theServer; +- (id)initWithSocket:(AsyncSocket *)theSocket server:(MGMHTTPServer *)theServer; + +- (void)setHTTPVersion:(NSString *)theVersion; + +- (void)setHTTPResponse:(MGMHTTPResponse *)theResponse; + +- (void)sendErrorNum:(int)theErrorNum description:(NSString *)theDescription returnHTML:(BOOL)hasHTML; + +- (NSString *)requestHeaderWithName:(NSString *)name; +- (NSDictionary *)requestHeaders; +- (MGMInteger)contentLength; + +- (BOOL)setHeader:(NSString *)header withName:(NSString *)name; +- (BOOL)deleteHeaderWithName:(NSString *)name; +- (NSString *)headerWithName:(NSString *)name; +- (NSDictionary *)headers; + +- (BOOL)setCookie:(NSString *)cookie forName:(NSString *)name expires:(NSDate *)expires domain:(NSString *)domain path:(NSString *)path secure:(BOOL)secure httpOnly:(BOOL)httpOnly; +- (BOOL)deleteCookieWithName:(NSString *)name withDomain:(NSString *)domain withPath:(NSString *)path secure:(BOOL)secure httpOnly:(BOOL)httpOnly; +- (NSString *)cookieWithName:(NSString *)name; +- (NSDictionary *)cookies; + +- (NSString *)getInputWithName:(NSString *)name; +- (NSDictionary *)getInputs; +- (NSString *)postInputWithName:(NSString *)name; +- (NSDictionary *)postInputs; + +- (NSString *)requestWithName:(NSString *)name; +- (NSDictionary *)requests; + +- (NSDictionary *)fileWithName:(NSString *)Name; +- (NSDictionary *)filesUploaded; + +- (NSString *)userIP; + +- (NSArray *)sslCertificates; +- (void)replyToClient; + +- (void)printData:(NSData *)data; +- (void)print:(NSString *)format, ...; +- (void)printError:(NSString *)format, ...; +- (void)flush; + +- (void)disconnect; +@end \ No newline at end of file diff --git a/EmailScheduler/MGMHTTP/MGMHTTPClient.m b/EmailScheduler/MGMHTTP/MGMHTTPClient.m new file mode 100644 index 0000000..586f517 --- /dev/null +++ b/EmailScheduler/MGMHTTP/MGMHTTPClient.m @@ -0,0 +1,1202 @@ +// +// MGMHTTPClient.m +// MGMHTTP +// +// Created by Mr. Gecko on 8/14/13. +// Copyright (c) 2014 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +#import "MGMHTTPClient.h" +#import "MGMHTTPServer.h" +#import "MGMHTTPResponse.h" +#import "MGMHTTPAddons.h" +#import "AsyncSocket.h" + +BOOL MGMDisconnectAfterSent = NO; + +#if TARGET_OS_IPHONE +int MGMReadChunkSize = (1024 * 128); +#else +int MGMReadChunkSize = (1024 * 512); +#endif + +#if TARGET_OS_IPHONE +int MGMPostChunkSize = (1024 * 32); +#else +int MGMPostChunkSize = (1024 * 128); +#endif +int MGMMaxFileSize = (1024 * 1024 * 20); + +int MGMReadTimeOut = -1; +int MGMWriteHeaderTimeOut = 30; +int MGMWriteBodyTimeOut = -1; +int MGMWriteErrorTimeOut = 30; + +int MGMLimitMaxHeaderLineLength = 8190; +int MGMLimitMaxHeaderLines = 100; +int MGMHTTPBufferLimit = 7000; +int MGMPostMaxLength = 1048576; + +enum MGMHTTPTags { + MGMHTTPRequestHeaderTag = 1, + MGMHTTPRequestBodyTag, + MGMHTTPPartialResponseTag, + MGMHTTPPartialResponseHeaderTag, + MGMHTTPPartialResponseBodyTag, + MGMHTTPPartialRangeResponseBodyTag, + MGMHTTPPartialRangesResponseHeaderTag, + MGMHTTPBufferResponseBodyTag, + MGMHTTPBufferResponseBodyFinalTag, + MGMHTTPResponseTag, + MGMHTTPFinalResponseTag +}; + +//Server info +NSString * const MGMHTTPVersion = @"MGMServer/0.1"; +NSString * const MGMTmpFileFolder = @"/tmp/mgm/"; +NSString * const MGMPropertyFile = @"/Library/Preferences/com.MrGeckosMedia.MGM.plist"; + + +//Dictionary Keys +NSString * const MGMNameKey = @"name"; +NSString * const MGMFileNameKey = @"filename"; +NSString * const MGMFileSizeKey = @"filesize"; +NSString * const MGMFileTypeKey = @"filetype"; +NSString * const MGMFilePathKey = @"filepath"; +NSString * const MGMCookieKey = @"cookie"; +NSString * const MGMExpiresKey = @"expires"; +NSString * const MGMDomainKey = @"domain"; +NSString * const MGMPathKey = @"path"; +NSString * const MGMSecureKey = @"secure"; +NSString * const MGMHTTPOnlyKey = @"httpOnly"; + +//Headers +NSString * const MGMRPath = @"PATH"; +NSString * const MGMREncoding = @"__CF_USER_TEXT_ENCODING"; +NSString * const MGMGatewayInterface = @"gateway-interface"; +NSString * const MGMContentType = @"content-type"; +NSString * const MGMContentLength = @"content-length"; +NSString * const MGMServerProtocol = @"server-protocol"; +NSString * const MGMRequestMethod = @"request-method"; +NSString * const MGMRequestURI = @"request-uri"; +NSString * const MGMScriptName = @"script-name"; +NSString * const MGMRemotePort = @"remote-port"; +NSString * const MGMServerAddress = @"server-addr"; +NSString * const MGMServerPort = @"server-port"; +NSString * const MGMQueryString = @"query-string"; +NSString * const MGMCookies = @"cookie"; +NSString * const MGMPCRemoteAddress = @"pc-remote-addr"; +NSString * const MGMRemoteAddress = @"remote-addr"; +NSString * const MGMClientIP = @"client-ip"; +NSString * const MGMForwardedFor = @"x-forwarded-for"; +NSString * const MGMConnection = @"connection"; +NSString * const MGMServerHeader = @"server"; +NSString * const MGMAcceptRanges = @"accept-ranges"; +NSString * const MGMDate = @"date"; + +NSString * const MGMClientDisconnectedNotification = @"MGMClientDisconnectedNotification"; + +#define BAPPEND(ch) \ +{ \ + putc(ch, outf); \ + outLen++; \ +} + +@interface MGMHTTPClient (MGMPrivate) +- (void)sendHTTPResponse; +- (void)cleanConnection:(long)tag; +@end + +@implementation MGMHTTPClient ++ (id)clientWithSocket:(AsyncSocket *)theSocket server:(MGMHTTPServer *)theServer { + return [[[self alloc] initWithSocket:theSocket server:theServer] autorelease]; +} +- (id)initWithSocket:(AsyncSocket *)theSocket server:(MGMHTTPServer *)theServer { + if (self = [super init]) { + [self setHTTPVersion:(NSString *)kCFHTTPVersion1_1]; + headersPosted = NO; + isBufferBased = NO; + + server = [theServer retain]; + clientRequest = CFHTTPMessageCreateEmpty(kCFAllocatorDefault, YES); + headers = [NSMutableDictionary new]; + + clientSocket = [theSocket retain]; + [clientSocket setDelegate:self]; + [clientSocket enablePreBuffering]; + +#if MGMHTTPThreaded + [NSThread detachNewThreadSelector:@selector(startThread) toTarget:self withObject:nil]; + while (thread==nil) { + CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1, YES); + } +#endif + } + return self; +} +- (void)dealloc { +#if MGMHTTPDebug + NSLog(@"Release"); +#endif + [clientSocket release]; + [server release]; + [requestHeaders release]; + [headers release]; + [getInputs release]; + [postInputs release]; + [postData release]; + [cookies release]; + [cookiesToPost release]; + [filesUploaded release]; + [fBoundary release]; + [httpVersion release]; + [httpResponse release]; + [responseBuffer release]; + [ranges release]; + [rangesHeaders release]; + [rangesBoundry release]; + CFRelease(clientRequest); + [super dealloc]; +} + +- (AsyncSocket *)clientSocket { + return clientSocket; +} + +#if MGMHTTPThreaded +- (void)setRunLoop:(NSRunLoop *)theRunLoop { + threadRunLoop = [theRunLoop retain]; +} +- (NSRunLoop *)runLoop { + return threadRunLoop; +} +- (void)setThread:(NSThread *)theThread { + thread = [theThread retain]; +} +- (void)startThread { + NSAutoreleasePool *pool = [NSAutoreleasePool new]; + [self performSelectorOnMainThread:@selector(setRunLoop:) withObject:[NSRunLoop currentRunLoop] waitUntilDone:YES]; + [self performSelectorOnMainThread:@selector(setThread:) withObject:[NSThread currentThread] waitUntilDone:YES]; + while (!clientDisconnected) { + CFRunLoopRunInMode(kCFRunLoopDefaultMode, 1, YES); + [pool drain]; + pool = [NSAutoreleasePool new]; + } + [threadRunLoop release]; + threadRunLoop = nil; + [thread release]; + thread = nil; + [pool drain]; +} +#endif + +- (BOOL)parseRanges:(NSString *)theRanges withResponseLength:(MGMInteger)theResponseLength { + NSRange equalRange = [theRanges rangeOfString:@"="]; + if (equalRange.location==NSNotFound) + return NO; + + NSString *rangeType = [[theRanges substringToIndex:equalRange.location] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + NSString *rangeValue = [[theRanges substringFromIndex:equalRange.location+equalRange.length] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + if (![[rangeType lowercaseString] isEqualToString:@"bytes"]) + return NO; + + NSArray *rangeComponents = [rangeValue componentsSeparatedByString:@","]; + if ([rangeComponents count]==0) + return NO; + + [ranges release]; + ranges = [NSMutableArray new]; + rangeIndex = 0; + for (int i=0; i<[rangeComponents count]; i++) { + NSRange dashRange = [[rangeComponents objectAtIndex:i] rangeOfString:@"-"]; + if (dashRange.location == NSNotFound) { + [ranges addObject:[NSValue valueWithRange:NSMakeRange([[rangeComponents objectAtIndex:i] longValue], 1)]]; + } else { + MGMInteger r1 = strtol([[[rangeComponents objectAtIndex:i] substringToIndex:dashRange.location] UTF8String], NULL, 0); + MGMInteger r2 = strtol([[[rangeComponents objectAtIndex:i] substringFromIndex:dashRange.location+dashRange.length] UTF8String], NULL, 0); + + if (r2==0) + r2 = theResponseLength; + if (r1>r2) + return NO; + + [ranges addObject:[NSValue valueWithRange:NSMakeRange(r1, r2-r1+1)]]; + } + } + + if ([ranges count]==0) + return NO; + + //Check for intercepts + for (int i=0; i<[ranges count]-1; i++) { + NSRange range = [[ranges objectAtIndex:i] rangeValue]; + for (int r=i+1; r<[ranges count]; r++) { + if (NSIntersectionRange(range, [[ranges objectAtIndex:r] rangeValue]).length!=0) + return NO; + } + } + return YES; +} + +- (void)setHTTPVersion:(NSString *)theVersion { + [httpVersion release]; + httpVersion = [theVersion retain]; +} + +- (void)setHTTPResponse:(MGMHTTPResponse *)theResponse { + [httpResponse release]; + httpResponse = [theResponse retain]; +} + +- (BOOL)supportsMethod:(NSString *)theMethod { + return [[theMethod lowercaseString] isEqual:@"put"] || [[theMethod lowercaseString] isEqual:@"get"] || [[theMethod lowercaseString] isEqual:@"post"] || [[theMethod lowercaseString] isEqual:@"head"]; +} + +- (NSString *)getDescriptionForHTTPCode:(int)theCode { + switch (theCode) { + case 100: + return @"Continue"; + break; + case 101: + return @"Switching Protocols"; + break; + case 102: + return @"Processing"; + break; + case 200: + return @"OK"; + break; + case 201: + return @"Created"; + break; + case 202: + return @"Accepted"; + break; + case 203: + return @"Non-Authoritative Information"; + break; + case 204: + return @"No Content"; + break; + case 205: + return @"Reset Content"; + break; + case 206: + return @"Partial Content"; + break; + case 207: + return @"Multi-Status"; + break; + case 208: + return @"Already Reported"; + break; + case 226: + return @"IM Used"; + break; + case 300: + return @"Multiple Choices"; + break; + case 301: + return @"Moved Permanently"; + break; + case 302: + return @"Found"; + break; + case 303: + return @"See Other"; + break; + case 304: + return @"Not Modified"; + break; + case 305: + return @"Use Proxy"; + break; + case 307: + return @"Temporary Redirect"; + break; + case 308: + return @"Permanent Redirect"; + break; + case 400: + return @"Bad Request"; + break; + case 401: + return @"Unauthorized"; + break; + case 402: + return @"Payment Required"; + break; + case 403: + return @"Forbidden"; + break; + case 404: + return @"Not Found"; + break; + case 405: + return @"Method Not Allowed"; + break; + case 406: + return @"Not Acceptable"; + break; + case 407: + return @"Proxy Authentication Required"; + break; + case 408: + return @"Request Timeout"; + break; + case 409: + return @"Conflict"; + break; + case 410: + return @"Gone"; + break; + case 411: + return @"Length Required"; + break; + case 412: + return @"Precondition Failed"; + break; + case 413: + return @"Request Entity Too Large"; + break; + case 414: + return @"Request-URI Too Long"; + break; + case 415: + return @"Unsupported Media Type"; + break; + case 416: + return @"Requested Range Not Satisfiable"; + break; + case 417: + return @"Expectation Failed"; + break; + case 418: + return @"I'm a teapot"; + break; + case 420: + return @"Enhance Your Calm"; + break; + case 422: + return @"Unprocessable Entity"; + break; + case 423: + return @"Locked"; + break; + case 425: + return @"Unordered Collection"; + break; + case 426: + return @"Upgrade Required"; + break; + case 428: + return @"Precondition Required"; + break; + case 429: + return @"Too Many Requests"; + break; + case 431: + return @"Request Header Fields Too Large"; + break; + case 444: + return @"No Response"; + break; + case 451: + return @"Unavailable For Legal Reasons"; + break; + case 499: + return @"Client Closed Request"; + break; + case 500: + return @"Internal Server Error"; + break; + case 501: + return @"Not Implemented"; + break; + case 502: + return @"Bad Gateway"; + break; + case 503: + return @"Service Unavailable"; + break; + case 504: + return @"Gateway Timeout"; + break; + case 505: + return @"HTTP Version Not Supported"; + break; + case 506: + return @"Variant Also Negotiates"; + break; + case 507: + return @"Insufficient Storage"; + break; + case 508: + return @"Loop Detected"; + break; + case 509: + return @"Bandwidth Limit Exceeded"; + break; + case 510: + return @"Not Extended"; + break; + case 511: + return @"Network Authentication Required"; + break; + case 598: + return @"Network read timeout error"; + break; + case 599: + return @"Network connect timeout error"; + break; + default: + return @"Unknown Code"; + break; + } +} + +- (NSMutableData *)getResponseWithCode:(int)theCode description:(NSString *)theDescription { + NSString *description; + if (theDescription!=nil) { + description = theDescription; + } else { + description = [self getDescriptionForHTTPCode:theCode]; + } + + NSMutableData *response = [NSMutableData data]; + [response appendData:[[NSString stringWithFormat:@"%@ %d %@\r\n", httpVersion, theCode, description] dataUsingEncoding:NSUTF8StringEncoding]]; + + if (!headersPosted) { + if ([headers objectForKey:MGMServerHeader]==nil) + [self setHeader:MGMHTTPVersion withName:MGMServerHeader]; + if (MGMDisconnectAfterSent && [headers objectForKey:MGMConnection]==nil) + [self setHeader:@"close" withName:MGMConnection]; + if ([headers objectForKey:MGMAcceptRanges]==nil) + [self setHeader:@"bytes" withName:MGMAcceptRanges]; + if ([headers objectForKey:MGMDate]==nil) + [self setHeader:[NSString stringWithDate:[NSDate date]] withName:MGMDate]; + if ([headers objectForKey:MGMContentType]==nil) + [self setHeader:@"text/html" withName:MGMContentType]; + headersPosted = YES; + } + + NSMutableString *headerString = [NSMutableString string]; + if (cookiesToPost!=nil) { + for (int i=0; i<[cookiesToPost count]; i++) { + NSDictionary *cookie = [cookiesToPost objectAtIndex:i]; + + [headerString appendFormat:@"Set-Cookie: %@=%@", [[cookie objectForKey:MGMNameKey] replace:@" " with:@"+"], [[cookie objectForKey:MGMCookieKey] replace:@" " with:@"+"]]; + if ([cookie objectForKey:MGMExpiresKey]) + [headerString appendFormat:@"; expires=%@", [NSString stringWithDate:[cookie objectForKey:MGMExpiresKey]]]; + if ([cookie objectForKey:MGMDomainKey]) + [headerString appendFormat:@"; domain=%@", [[cookie objectForKey:MGMDomainKey] replace:@" " with:@"+"]]; + if ([cookie objectForKey:MGMPathKey]) + [headerString appendFormat:@"; path=%@", [[cookie objectForKey:MGMPathKey] replace:@" " with:@"+"]]; + if ([[cookie objectForKey:MGMSecureKey] boolValue]) + [headerString appendString:@"; secure"]; + if ([[cookie objectForKey:MGMHTTPOnlyKey] boolValue]) + [headerString appendString:@"; httponly"]; + [headerString appendString:@"\r\n"]; + } + } + + NSArray *keys = [headers allKeys]; + for (int i=0; i<[keys count]; i++) { + NSArray *nameA = [[keys objectAtIndex:i] componentsSeparatedByString:@"-"]; + NSMutableString *name = [NSMutableString string]; + for (int d=0; d<[nameA count]; d++) { + if (d==0) { + [name appendString:[[nameA objectAtIndex:d] capitalizedString]]; + } else { + [name appendFormat:@"-%@", [[nameA objectAtIndex:d] capitalizedString]]; + } + } + [headerString appendFormat:@"%@: %@\r\n", name, [headers objectForKey:[keys objectAtIndex:i]]]; + } + [response appendData:[headerString dataUsingEncoding:NSUTF8StringEncoding]]; + [response appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; + return response; +} + +- (void)sendErrorNum:(int)theErrorNum description:(NSString *)theDescription returnHTML:(BOOL)hasHTML { + NSString *description; + if (theDescription!=nil) { + description = theDescription; + } else { + description = [self getDescriptionForHTTPCode:theErrorNum]; + } +#if MGMHTTPDebug + NSLog(@"Error %d - %@", theErrorNum, description); +#endif + + NSMutableString *htmlString = [NSMutableString string]; + if (hasHTML) { + [htmlString appendString:@""]; + [htmlString appendFormat:@"%d %@", theErrorNum, description]; + [htmlString appendFormat:@"

%@

", description]; + } + [self setHeader:[NSString stringWithInteger:[htmlString length]] withName:@"Content-Length"]; + + NSMutableData *response = [self getResponseWithCode:theErrorNum description:description]; + [response appendData:[htmlString dataUsingEncoding:NSUTF8StringEncoding]]; + [clientSocket writeData:response withTimeout:MGMWriteErrorTimeOut tag:MGMHTTPResponseTag]; +} + +- (NSString *)requestHeaderWithName:(NSString *)name { + return [requestHeaders objectForKey:[name lowercaseString]]; +} +- (NSDictionary *)requestHeaders { + return [NSDictionary dictionaryWithDictionary:requestHeaders]; +} +- (MGMInteger)contentLength { + if ([self requestHeaderWithName:MGMContentLength]==nil) + return 0; + return strtol([[self requestHeaderWithName:MGMContentLength] UTF8String], NULL, 0); +} + +- (BOOL)setHeader:(NSString *)header withName:(NSString *)name { + if (!headersPosted) { + [headers setObject:header forKey:(name==nil ? @"" : [name lowercaseString])]; + return YES; + } else if (isBufferBased) { + [self printError:@"Headers has already been posted."]; + } + return NO; +} +- (BOOL)deleteHeaderWithName:(NSString *)name { + if (!headersPosted) { + if ([headers objectForKey:[name lowercaseString]]!=nil) { + [headers removeObjectForKey:[name lowercaseString]]; + return YES; + } + } else if (isBufferBased) { + [self printError:@"Headers has already been posted."]; + } + return NO; +} +- (NSString *)headerWithName:(NSString *)name { + return [headers objectForKey:[name lowercaseString]]; +} +- (NSDictionary *)headers { + return [NSDictionary dictionaryWithDictionary:headers]; +} + +- (BOOL)setCookie:(NSString *)cookie forName:(NSString *)name expires:(NSDate *)expires domain:(NSString *)domain path:(NSString *)path secure:(BOOL)secure httpOnly:(BOOL)httpOnly { + if (headersPosted) { + if (isBufferBased) { + [self printError:@"Headers has already been posted."]; + } + } else if (name!=nil && ![name isEqualToString:@""]) { + if (cookiesToPost==nil) { + cookiesToPost = [[NSMutableArray new] retain]; + } + for (int i=0; i<[cookiesToPost count]; i++) { + if ([[[cookiesToPost objectAtIndex:i] objectForKey:MGMNameKey] isEqualToString:name]) { + [cookiesToPost removeObjectAtIndex:i]; + } + } + NSMutableDictionary *cookieD = [NSMutableDictionary new]; + [cookieD setObject:name forKey:MGMNameKey]; + if (cookie==nil) { + [cookies setObject:@"" forKey:name]; + [cookieD setObject:@"" forKey:MGMCookieKey]; + } else { + [cookies setObject:cookie forKey:name]; + [cookieD setObject:cookie forKey:MGMCookieKey]; + } + if (expires!=nil) { + [cookieD setObject:expires forKey:MGMExpiresKey]; + } + if (domain!=nil && ![domain isEqualToString:@""]) { + [cookieD setObject:domain forKey:MGMDomainKey]; + } + if (path!=nil && ![path isEqualToString:@""]) { + [cookieD setObject:path forKey:MGMPathKey]; + } + [cookieD setObject:[NSNumber numberWithBool:secure] forKey:MGMSecureKey]; + [cookieD setObject:[NSNumber numberWithBool:httpOnly] forKey:MGMHTTPOnlyKey]; + [cookiesToPost addObject:[NSDictionary dictionaryWithDictionary:cookieD]]; + [cookieD release]; + return YES; + } + return NO; +} +- (BOOL)deleteCookieWithName:(NSString *)name withDomain:(NSString *)domain withPath:(NSString *)path secure:(BOOL)secure httpOnly:(BOOL)httpOnly { + if (name!=nil && ![name isEqualToString:@""]) { + if ([cookies objectForKey:name]!=nil) { + if ([self setCookie:nil forName:name expires:[NSDate date] domain:domain path:path secure:secure httpOnly:httpOnly]) { + [cookies removeObjectForKey:name]; + return YES; + } + } + } + return NO; +} +- (NSString *)cookieWithName:(NSString *)name { + return [cookies objectForKey:name]; +} +- (NSDictionary *)cookies { + return [NSDictionary dictionaryWithDictionary:cookies]; +} + +- (NSString *)getInputWithName:(NSString *)name { + return [getInputs objectForKey:name]; +} +- (NSDictionary *)getInputs { + return getInputs; +} +- (NSString *)postInputWithName:(NSString *)name { + return [postInputs objectForKey:name]; +} +- (NSDictionary *)postInputs { + return postInputs; +} + +- (NSString *)requestWithName:(NSString *)name { + NSString *request = nil; + if ([getInputs objectForKey:name]!=nil) + request = [getInputs objectForKey:name]; + if ([postInputs objectForKey:name]!=nil) + request = [postInputs objectForKey:name]; + if ([cookies objectForKey:name]!=nil) + request = [cookies objectForKey:name]; + return request; +} +- (NSDictionary *)requests { + NSMutableDictionary *requests = [NSMutableDictionary new]; + NSArray *keys; + keys = [getInputs allKeys]; + for (int i=0; i<[keys count]; i++) { + [requests setObject:[getInputs objectForKey:[keys objectAtIndex:i]] forKey:[keys objectAtIndex:i]]; + } + keys = [postInputs allKeys]; + for (int i=0; i<[keys count]; i++) { + [requests setObject:[postInputs objectForKey:[keys objectAtIndex:i]] forKey:[keys objectAtIndex:i]]; + } + keys = [cookies allKeys]; + for (int i=0; i<[keys count]; i++) { + [requests setObject:[cookies objectForKey:[keys objectAtIndex:i]] forKey:[keys objectAtIndex:i]]; + } + NSDictionary *returnRequests = [NSDictionary dictionaryWithDictionary:requests]; + [requests release]; + return returnRequests; +} +- (NSDictionary *)fileWithName:(NSString *)Name { + return [filesUploaded objectForKey:Name]; +} +- (NSDictionary *)filesUploaded { + return [NSDictionary dictionaryWithDictionary:filesUploaded]; +} + +- (NSString *)userIP { + NSString *ip = nil; + if ([self requestHeaderWithName:MGMRemoteAddress]) + ip = [self requestHeaderWithName:MGMRemoteAddress]; + if ([self requestHeaderWithName:MGMPCRemoteAddress]) + ip = [self requestHeaderWithName:MGMPCRemoteAddress]; + if ([self requestHeaderWithName:MGMClientIP]) + ip = [self requestHeaderWithName:MGMClientIP]; + if ([self requestHeaderWithName:MGMForwardedFor]) + ip = [self requestHeaderWithName:MGMForwardedFor]; + return ip; +} + +- (NSArray *)sslCertificates { + return nil; +} + +- (void)replyToClient { + if (isBufferBased) { + if (isBufferSending) { + isBufferSending = NO; + NSData *data = [NSData dataWithData:responseBuffer]; + [clientSocket writeData:data withTimeout:MGMWriteBodyTimeOut tag:MGMHTTPBufferResponseBodyFinalTag]; + [responseBuffer release]; + responseBuffer = nil; + } else { + isBufferBased = NO; + NSData *data = [NSData dataWithData:responseBuffer]; + httpResponse = [[MGMHTTPResponse responseWithData:data] retain]; + [responseBuffer release]; + responseBuffer = nil; + [self sendHTTPResponse]; + } + } else { + [self sendHTTPResponse]; + } +} + +- (void)sendHTTPResponse { + if (httpResponse==nil) { + if ([[server delegate] respondsToSelector:@selector(httpResponseForClient:)]) { + httpResponse = [[[server delegate] httpResponseForClient:self] retain]; + } else { + [self sendErrorNum:500 description:nil returnHTML:YES]; + return; + } + } + + MGMInteger contentLength = httpResponse ? [httpResponse contentLength] : 0; + if (contentLength==0) { + [self sendErrorNum:204 description:nil returnHTML:YES]; + [httpResponse release]; + httpResponse = nil; + return; + } + + NSString *rangeHeader = [self requestHeaderWithName:@"range"]; + BOOL isRangeRequest = NO; + + if (rangeHeader!=nil && [self parseRanges:rangeHeader withResponseLength:contentLength]) { + isRangeRequest = YES; + } + + NSMutableData *response; + if (!isRangeRequest) { + [self setHeader:[NSString stringWithInteger:contentLength] withName:@"Content-Length"]; + response = [self getResponseWithCode:200 description:nil]; + } else { + if ([ranges count]==1) { + NSRange range = [[ranges objectAtIndex:0] rangeValue]; + + [self setHeader:[NSString stringWithInteger:range.length] withName:@"Content-Length"]; + NSString *contentRangeStr = [NSString stringWithFormat:@"bytes %@-%@/%@", [NSString stringWithInteger:range.location], [NSString stringWithInteger:NSMaxRange(range)-1], [NSString stringWithInteger:contentLength]]; + [self setHeader:contentRangeStr withName:@"Content-Range"]; + } else { + rangesHeaders = [NSMutableArray new]; + srandomdev(); + rangesBoundry = [[NSString stringWithFormat:@"MGM%ld", random()%20000] retain]; + + MGMInteger actualContentLength = 0; + + for (int i=0; i < [ranges count]; i++) { + NSRange range = [[ranges objectAtIndex:i] rangeValue]; + + NSData *header = [[NSString stringWithFormat:@"\r\n--%@\r\nContent-Range: bytes %@-%@/%@\r\n\r\n", rangesBoundry, + [NSString stringWithInteger:range.location], [NSString stringWithInteger:NSMaxRange(range)-1], + [NSString stringWithInteger:contentLength]] dataUsingEncoding:NSUTF8StringEncoding]; + [rangesHeaders addObject:header]; + + actualContentLength += [header length]; + actualContentLength += range.length; + } + actualContentLength += 8+[rangesBoundry length]; + + [self setHeader:[NSString stringWithInteger:actualContentLength] withName:@"Content-Length"]; + [self setHeader:[NSString stringWithFormat:@"multipart/byteranges; boundary=%@", rangesBoundry] withName:@"Content-Type"]; + } + response = [self getResponseWithCode:206 description:nil]; + } + + if ([[[self requestHeaderWithName:MGMRequestMethod] lowercaseString] isEqual:@"head"]) { + [clientSocket writeData:response withTimeout:MGMWriteHeaderTimeOut tag:MGMHTTPResponseTag]; + } else { + [clientSocket writeData:response withTimeout:MGMWriteHeaderTimeOut tag:MGMHTTPPartialResponseTag]; + + if (!isRangeRequest) { + NSData *data = [httpResponse readDataOfLength:MGMReadChunkSize]; + [clientSocket writeData:data withTimeout:MGMWriteBodyTimeOut tag:MGMHTTPPartialResponseBodyTag]; + } else { + if ([ranges count]==1) { + NSRange range = [[ranges objectAtIndex:0] rangeValue]; + [httpResponse setOffset:range.location]; + + MGMInteger bytesToRead = range.length=MGMHTTPBufferLimit) { + if (!isBufferSending) { + isBufferSending = YES; + [self postHeaders]; + } + if (![[[self requestHeaderWithName:MGMRequestMethod] lowercaseString] isEqual:@"head"]) { + NSRange range = NSMakeRange(0, MGMHTTPBufferLimit); + NSData *data = [responseBuffer subdataWithRange:range]; + [clientSocket writeData:data withTimeout:MGMWriteBodyTimeOut tag:MGMHTTPBufferResponseBodyTag]; + while (range.length+range.location!=[responseBuffer length]) { + range.location += MGMHTTPBufferLimit; + range.length = ([responseBuffer length]-range.locationError: %@
", info]; + [info release]; +} +- (void)flush { + if (!isBufferSending) { + isBufferSending = YES; + [self postHeaders]; + } + if (![[[self requestHeaderWithName:MGMRequestMethod] lowercaseString] isEqual:@"head"]) { + NSData *data = [NSData dataWithData:responseBuffer]; + [clientSocket writeData:data withTimeout:MGMWriteBodyTimeOut tag:MGMHTTPBufferResponseBodyTag]; + } + [responseBuffer release]; + responseBuffer = [NSMutableData new]; +} + +- (BOOL)onSocketWillConnect:(AsyncSocket *)sock { + NSArray *certificates = [self sslCertificates]; + if (certificates!=nil && [certificates count]>0) { + NSMutableDictionary *settings = [NSMutableDictionary dictionary]; + [settings setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLIsServer]; + [settings setObject:certificates forKey:(NSString *)kCFStreamSSLCertificates]; + [settings setObject:(NSString *)kCFStreamSocketSecurityLevelNegotiatedSSL forKey:(NSString *)kCFStreamSSLLevel]; + + CFReadStreamSetProperty([clientSocket getCFReadStream], kCFStreamPropertySSLSettings, (CFDictionaryRef)settings); + CFWriteStreamSetProperty([clientSocket getCFWriteStream], kCFStreamPropertySSLSettings, (CFDictionaryRef)settings); + } + return YES; +} + +- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port { +#if MGMHTTPDebug + NSLog(@"Connected to %@:%hu", host, port); +#endif + [clientSocket readDataToData:[AsyncSocket CRLFData] withTimeout:MGMReadTimeOut maxLength:MGMLimitMaxHeaderLineLength tag:MGMHTTPRequestHeaderTag]; +} +- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData*)data withTag:(long)tag { + if (tag==MGMHTTPRequestHeaderTag) { + isKeepAlive = NO; + BOOL result = CFHTTPMessageAppendBytes(clientRequest, [data bytes], [data length]); + if (!result) { + [self sendErrorNum:400 description:nil returnHTML:YES]; + } else if (!CFHTTPMessageIsHeaderComplete(clientRequest)) { + numHeaders++; + if (numHeaders>MGMLimitMaxHeaderLines) { + [self disconnect]; + } else { + [clientSocket readDataToData:[AsyncSocket CRLFData] withTimeout:MGMReadTimeOut maxLength:MGMLimitMaxHeaderLineLength tag:MGMHTTPRequestHeaderTag]; + } + } else { + NSString *version = [(NSString *)CFHTTPMessageCopyVersion(clientRequest) autorelease]; + if (version==nil || (![version isEqualToString:(NSString *)kCFHTTPVersion1_1] && ![version isEqualToString:(NSString *)kCFHTTPVersion1_0])) { + [self sendErrorNum:505 description:nil returnHTML:YES]; + return; + } + NSString *method = [(NSString *)CFHTTPMessageCopyRequestMethod(clientRequest) autorelease]; + NSURL *uri = [(NSURL *)CFHTTPMessageCopyRequestURL(clientRequest) autorelease]; + + NSDictionary *requestHeadersDictionary = [(NSDictionary *)CFHTTPMessageCopyAllHeaderFields(clientRequest) autorelease]; + NSArray *requestKeys = [requestHeadersDictionary allKeys]; + NSMutableDictionary *requestDictionary = [NSMutableDictionary dictionary]; + for (int i=0; i<[requestKeys count]; i++) { + [requestDictionary setObject:[requestHeadersDictionary objectForKey:[requestKeys objectAtIndex:i]] forKey:[[requestKeys objectAtIndex:i] lowercaseString]]; + } + [requestDictionary setObject:version forKey:MGMServerProtocol]; + [requestDictionary setObject:method forKey:MGMRequestMethod]; + [requestDictionary setObject:[[uri standardizedURL] path] forKey:MGMScriptName]; + + NSString *path = [[[uri standardizedURL] path] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; + CFStringRef escapedPath = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)[[uri standardizedURL] path], NULL, CFSTR("!*'();:^@&=+$,?%#[]|"), kCFStringEncodingUTF8); + + if (escapedPath!=NULL) + path = [(NSString *)escapedPath autorelease]; + [requestDictionary setObject:[NSString stringWithFormat:@"http://%@%@", [requestDictionary objectForKey:@"host"], path] forKey:MGMRequestURI]; + + [requestDictionary setObject:[clientSocket connectedHost] forKey:MGMRemoteAddress]; + [requestDictionary setObject:[[NSNumber numberWithInt:[clientSocket connectedPort]] stringValue] forKey:MGMRemotePort]; + [requestDictionary setObject:[clientSocket localHost] forKey:MGMServerAddress]; + [requestDictionary setObject:[[NSNumber numberWithInt:[clientSocket localPort]] stringValue] forKey:MGMServerPort]; + if ([uri query]!=nil) { + [requestDictionary setObject:[uri query] forKey:MGMQueryString]; + } + requestHeaders = [[NSDictionary dictionaryWithDictionary:requestDictionary] retain]; +#if MGMHTTPDebug + NSLog(@"%@", requestHeaders); +#endif + + NSArray *cookiesA = [[self requestHeaderWithName:MGMCookies] componentsSeparatedByString:@";"]; + cookies = [NSMutableDictionary new]; + for (int i=0; i<[cookiesA count]; i++) { + NSArray *cookie = [[cookiesA objectAtIndex:i] componentsSeparatedByString:@"="]; + [cookies setObject:([cookie count]==1 ? @"" : [[[cookie objectAtIndex:1] trim] urlDecode]) forKey:[[[cookie objectAtIndex:0] trim] urlDecode]]; + } + + if ([[self requestHeaderWithName:MGMQueryString] length]!=0) { + NSArray *formInputsA = [[self requestHeaderWithName:MGMQueryString] componentsSeparatedByString:@"&"]; + NSMutableDictionary *inputs = [NSMutableDictionary new]; + for (int i=0; i<[formInputsA count]; i++) { + NSArray *input = [[formInputsA objectAtIndex:i] componentsSeparatedByString:@"="]; + [inputs setObject:([input count]==1 ? @"" : [[input objectAtIndex:1] urlDecode]) forKey:[[input objectAtIndex:0] urlDecode]]; + } + getInputs = [[NSDictionary dictionaryWithDictionary:inputs] retain]; + [inputs release]; + } + + if (![self supportsMethod:method]) { + [self sendErrorNum:405 description:nil returnHTML:YES]; + return; + } + + MGMInteger requestContentLength = [self contentLength]; + BOOL expectsUpload = [[[self requestHeaderWithName:MGMRequestMethod] lowercaseString] isEqualToString:@"post"] || [[[self requestHeaderWithName:MGMRequestMethod] lowercaseString] isEqualToString:@"put"]; + if (expectsUpload) { + if(requestContentLength==0) { + [self sendErrorNum:400 description:nil returnHTML:YES]; + return; + } + } else if (requestContentLength!=0) { + [self sendErrorNum:400 description:nil returnHTML:YES]; + return; + } + requestContentLengthReceived = 0; + + if (expectsUpload) { + if ([[[self requestHeaderWithName:MGMRequestMethod] lowercaseString] isEqualToString:@"post"]) { + NSString *contentType = nil; + if ([self requestHeaderWithName:MGMContentType]!=nil) { + NSArray *contentA = [[self requestHeaderWithName:MGMContentType] componentsSeparatedByString:@";"]; + for (int i=0; i<[contentA count]; i++) { + NSArray *content = [[contentA objectAtIndex:i] componentsSeparatedByString:@"="]; + if ([content count]==1) { + contentType = [[[[content objectAtIndex:0] trim] lowercaseString] urlDecode]; + } else { + if ([[[[[content objectAtIndex:0] trim] lowercaseString] urlDecode] isEqualToString:@"boundary"]) { + [fBoundary release]; + fBoundary = [[@"--" stringByAppendingString:[[[content objectAtIndex:1] trim] urlDecode]] retain]; + } + } + + } + } + isMultipart = [contentType isEqualToString:@"multipart/form-data"]; + if (isMultipart) { + MGMInteger bytesToRead = requestContentLengthMGMPostMaxLength) { + [self sendErrorNum:400 description:nil returnHTML:YES]; + return; + } else { + [clientSocket readDataToLength:requestContentLength withTimeout:MGMReadTimeOut tag:MGMHTTPRequestBodyTag]; + } + } + } + } else { + [self replyToClient]; + } + } + } else { + if (isMultipart) { + requestContentLengthReceived += [data length]; + + MGMInteger requestContentLength = [self contentLength]; + if (requestContentLengthReceived0) { + [clientSocket writeData:data withTimeout:MGMWriteBodyTimeOut tag:MGMHTTPPartialResponseBodyTag]; + } else { + [self cleanConnection:tag]; + } + } else if (tag==MGMHTTPPartialRangeResponseBodyTag) { + NSRange range = [[ranges objectAtIndex:0] rangeValue]; + MGMInteger offset = [httpResponse offset]; + MGMInteger bytesRead = offset-range.location; + MGMInteger bytesLeft = range.length-bytesRead; + + if (bytesLeft>0) { + MGMInteger bytesToRead = bytesLeft0) { + MGMInteger bytesToRead = bytesLeft +#import "MGMHTTPDefines.h" + +@interface MGMHTTPResponse : NSObject { + MGMInteger offset; + NSData *data; +} ++ (id)responseWithData:(NSData *)theData; +- (id)initWithData:(NSData *)theData; ++ (id)responseWithString:(NSString *)theString; +- (id)initWithString:(NSString *)theString; + +- (MGMInteger)contentLength; + +- (MGMInteger)offset; +- (void)setOffset:(MGMInteger)theOffset; + +- (NSData *)readDataOfLength:(MGMInteger)theLength; +@end + +@interface MGMHTTPFileResponse : MGMHTTPResponse { + NSString *filePath; + NSFileHandle *fileHandle; +} ++ (id)responseWithFilePath:(NSString *)thePath; +- (id)initWithFilePath:(NSString *)thePath; +@end + +@interface MGMHTTPMIME : NSObject { + +} ++ (NSString *)mimeForExtension:(NSString *)theExtension; +@end \ No newline at end of file diff --git a/EmailScheduler/MGMHTTP/MGMHTTPResponse.m b/EmailScheduler/MGMHTTP/MGMHTTPResponse.m new file mode 100644 index 0000000..f8ab391 --- /dev/null +++ b/EmailScheduler/MGMHTTP/MGMHTTPResponse.m @@ -0,0 +1,131 @@ +// +// MGMHTTPResponse.m +// MGMHTTP +// +// Created by Mr. Gecko on 8/14/13. +// Copyright (c) 2014 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +#import "MGMHTTPResponse.h" + +@implementation MGMHTTPResponse ++ (id)responseWithData:(NSData *)theData { + return [[[self alloc] initWithData:theData] autorelease]; +} +- (id)initWithData:(NSData *)theData { + if (self = [super init]) { + data = [theData retain]; + } + return self; +} ++ (id)responseWithString:(NSString *)theString { + return [[[self alloc] initWithString:theString] autorelease]; +} +- (id)initWithString:(NSString *)theString { + if (self = [super init]) { + data = [[theString dataUsingEncoding:NSUTF8StringEncoding] retain]; + } + return self; +} +- (void)dealloc { + [data release]; + [super dealloc]; +} + +- (MGMInteger)contentLength { + return [data length]; +} + +- (MGMInteger)offset { + return offset; +} +- (void)setOffset:(MGMInteger)theOffset { + offset = theOffset; +} + +- (NSData *)readDataOfLength:(MGMInteger)theLength { + MGMInteger remaining = [data length]-offset; + MGMInteger length = theLength + +#define MGMHTTPDebug 0 +#define MGMHTTPThreaded 0 + +@class AsyncSocket, MGMHTTPClient, MGMHTTPResponse; + +@protocol MGMHTTPServerDelegate +- (Class)httpClientClass; +- (MGMHTTPResponse *)httpResponseForClient:(MGMHTTPClient *)theClient; +- (void)finnishedSendingResponse:(MGMHTTPClient *)theClient; +@end + +@interface MGMHTTPServer : NSObject +#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060) + +#endif +{ + AsyncSocket *httpSocket; + + NSObject *delegate; + Class clientClass; + NSMutableArray *clientConnections; + int port; + + NSNetService *bonjour; + NSString *bonjourDomain; + NSString *bonjourType; + NSString *bonjourName; + BOOL bonjourEnabled; +} ++ (id)serverWithPort:(int)thePort delegate:(id)theDelegate; +- (id)initServerWithPort:(int)thePort delegate:(id)theDelegate; + +- (AsyncSocket *)httpSocket; +- (NSArray *)clientConnections; + +- (id)delegate; +- (void)setDelegate:(id)theDelegate; + +- (int)port; +- (void)setPort:(int)thePort; + +- (NSString *)bonjourDomain; +- (void)setBonjourDomain:(NSString *)theDomain; + +- (NSString *)bonjourType; +- (void)setBonjourType:(NSString *)theType; + +- (NSString *)bonjourName; +- (NSString *)bonjourPublishedName; +- (void)setBonjourName:(NSString *)theName; + +- (BOOL)isBonjourEnabled; +- (void)setBonjourEnabled:(BOOL)isEnabled; + +- (Class)httpClientClass; +- (void)setHTTPClientClass:(Class)theClientClass; + +- (BOOL)start:(NSError **)error; +- (void)stop; +@end \ No newline at end of file diff --git a/EmailScheduler/MGMHTTP/MGMHTTPServer.m b/EmailScheduler/MGMHTTP/MGMHTTPServer.m new file mode 100644 index 0000000..3a8b891 --- /dev/null +++ b/EmailScheduler/MGMHTTP/MGMHTTPServer.m @@ -0,0 +1,207 @@ +// +// MGMHTTPServer.m +// MGMHTTP +// +// Created by Mr. Gecko on 8/14/13. +// Copyright (c) 2014 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +#import "MGMHTTPServer.h" +#import "MGMHTTPClient.h" +#import "AsyncSocket.h" + +@implementation MGMHTTPServer ++ (id)serverWithPort:(int)thePort delegate:(id)theDelegate { + return [[[self alloc] initServerWithPort:thePort delegate:theDelegate] autorelease]; +} +- (id)initServerWithPort:(int)thePort delegate:(id)theDelegate { + if (self = [super init]) { + httpSocket = [[AsyncSocket alloc] initWithDelegate:self]; + port = thePort; + delegate = [theDelegate retain]; + clientClass = [MGMHTTPClient class]; + + [self setBonjourDomain:@"local."]; + [self setBonjourType:@"_http._tcp."]; + [self setBonjourName:@""]; + [self setBonjourEnabled:NO]; + clientConnections = [NSMutableArray new]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(clientDisconected:) name:MGMClientDisconnectedNotification object:nil]; + } + return self; +} +- (void)dealloc { + [httpSocket disconnect]; + [httpSocket release]; + [clientConnections release]; + [bonjour release]; + [bonjourDomain release]; + [bonjourType release]; + [bonjourName release]; + [super dealloc]; +} + +- (AsyncSocket *)httpSocket { + return httpSocket; +} +- (NSArray *)clientConnections { + return clientConnections; +} + +- (id)delegate { + return delegate; +} +- (void)setDelegate:(id)theDelegate { + delegate = theDelegate; +} + +- (int)port { + return port; +} +- (void)setPort:(int)thePort { + port = thePort; +} + +- (NSString *)bonjourDomain { + return bonjourDomain; +} +- (void)setBonjourDomain:(NSString *)theDomain { + [bonjourDomain release]; + bonjourDomain = [theDomain retain]; +} + +- (NSString *)bonjourType { + return bonjourType; +} +- (void)setBonjourType:(NSString *)theType { + [bonjourType release]; + bonjourType = [theType retain]; +} + +- (NSString *)bonjourName { + return bonjourName; +} +- (NSString *)bonjourPublishedName { + return [bonjour name]; +} +- (void)setBonjourName:(NSString *)theName { + [bonjourName release]; + bonjourName = [theName retain]; +} + +- (BOOL)isBonjourEnabled { + return bonjourEnabled; +} +- (void)setBonjourEnabled:(BOOL)isEnabled { + bonjourEnabled = isEnabled; + if (bonjourEnabled) { + if (bonjour==nil && [httpSocket isConnected]) { + bonjour = [[NSNetService alloc] initWithDomain:bonjourDomain type:bonjourType name:bonjourName port:port]; + [bonjour setDelegate:self]; + [bonjour publish]; + } + } else { + if (bonjour!=nil) { + [bonjour stop]; + [bonjour release]; + bonjour = nil; + } + } +} + +- (Class)httpClientClass { + return clientClass; +} +- (void)setHTTPClientClass:(Class)theClientClass { + clientClass = theClientClass; +} + +- (BOOL)start:(NSError **)error { + BOOL success = [httpSocket acceptOnPort:port error:error]; + if (success) { + port = [httpSocket localPort]; +#if MGMHTTPDebug + NSLog(@"Started server on port %d", port); +#endif + if (bonjourEnabled) { + bonjour = [[NSNetService alloc] initWithDomain:bonjourDomain type:bonjourType name:bonjourName port:port]; + [bonjour setDelegate:self]; + [bonjour publish]; + } + } else { + NSLog(@"Failed to start Server: %@", *error); + } + return success; +} +- (void)stop { + if(bonjour!=nil) { + [bonjour stop]; + [bonjour release]; + bonjour = nil; + } + [httpSocket disconnect]; + [clientConnections removeAllObjects]; +} + +- (void)netServiceDidPublish:(NSNetService *)sender { +#if MGMHTTPDebug + NSLog(@"Bonjour Published domain:%@ type:%@ name:%@", [sender domain], [sender type], [sender name]); +#endif +} +- (void)netService:(NSNetService *)sender didNotPublish:(NSDictionary *)errorDict { + NSLog(@"Failed to Publish Bonjour domain:%@ type:%@ name:%@ error:%@", [sender domain], [sender type], [sender name], errorDict); +} + +- (int)clientConnectionCount { + int count; + @synchronized(clientConnections) { + count = (int)[clientConnections count]; + } + return count; +} +#if MGMHTTPThreaded +- (NSRunLoop *)onSocket:(AsyncSocket *)sock wantsRunLoopForNewSocket:(AsyncSocket *)newSocket { + @synchronized(clientConnections) { + for (unsigned int i=0; i<[clientConnections count]; i++) { + if ([[[clientConnections objectAtIndex:i] clientSocket] isEqual:newSocket]) + return [[clientConnections objectAtIndex:i] runLoop]; + } + } + return [NSRunLoop currentRunLoop]; +} +#endif +- (void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket { + if (clientClass==[MGMHTTPClient class]) { + if ([delegate respondsToSelector:@selector(httpClientClass)]) { + clientClass = [delegate httpClientClass]; + } + } + MGMHTTPClient *theClient = [clientClass clientWithSocket:newSocket server:self]; + @synchronized(clientConnections) { + [clientConnections addObject:theClient]; + } +} +- (void)clientDisconected:(NSNotification *)theNotification { + @synchronized(clientConnections) { + [clientConnections removeObject:[theNotification object]]; + } +} +@end \ No newline at end of file diff --git a/EmailScheduler/MGMHTTPClientClass.h b/EmailScheduler/MGMHTTPClientClass.h new file mode 100644 index 0000000..b2c137e --- /dev/null +++ b/EmailScheduler/MGMHTTPClientClass.h @@ -0,0 +1,34 @@ +// +// MGMHTTPClientClass.h +// EmailScheduler +// +// Created by James Coleman on 9/13/14. +// Copyright (c) 2014 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +#import +#import "MGMHTTP/MGMHTTPClient.h" + +@interface MGMHTTPClientClass : MGMHTTPClient { + +} + +@end diff --git a/EmailScheduler/MGMHTTPClientClass.m b/EmailScheduler/MGMHTTPClientClass.m new file mode 100644 index 0000000..14d3145 --- /dev/null +++ b/EmailScheduler/MGMHTTPClientClass.m @@ -0,0 +1,87 @@ +// +// MGMHTTPClientClass.m +// EmailScheduler +// +// Created by James Coleman on 9/13/14. +// Copyright (c) 2014 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +#import "MGMHTTPClientClass.h" +#import "MGMController.h" +#import "MGMJSON.h" +#import "MGMEmail.h" +#import + +@implementation MGMHTTPClientClass +- (void)replyToClient { + MGMController *controller = [MGMController sharedController]; + NSString *user = [self requestWithName:@"user"]; + NSString *fromEmail = [self requestWithName:@"from"]; + NSString *fromName = [self requestWithName:@"from-name"]; + NSString *toEmail = [self requestWithName:@"to"]; + NSString *toName = [self requestWithName:@"to-name"]; + NSString *subject = [self requestWithName:@"subject"]; + NSString *message = [self requestWithName:@"message"]; + NSString *messageHTML = [self requestWithName:@"message-html"]; + NSString *additionalHeadersString = [self requestWithName:@"headers"]; + + if (fromEmail!=nil && ![fromEmail isEqual:@""] && toEmail!=nil && ![toEmail isEqual:@""] && subject!=nil && ![subject isEqual:@""] && message!=nil && ![message isEqual:@""]) { + if ([[controller emailAddresses] objectForKey:(user!=nil && ![user isEqual:@""] ? user : fromEmail)]==nil) { + NSDictionary *response = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO], @"success", [NSString stringWithFormat:@"No handler for email address %@", fromEmail], @"error", nil]; + [self print:[response JSONValue]]; + } else { + MCOMessageBuilder *builder = [[MCOMessageBuilder alloc] init]; + MCOAddress *from = [MCOAddress addressWithDisplayName:fromName mailbox:fromEmail]; + MCOAddress *to = [MCOAddress addressWithDisplayName:toName mailbox:toEmail]; + [[builder header] setFrom:from]; + [[builder header] setTo:@[to]]; + [[builder header] setSubject:subject]; + [[builder header] setUserAgent:@"MGMEmail/0.1"]; + if (messageHTML!=nil && ![messageHTML isEqual:@""]) { + [builder setHTMLBody:messageHTML]; + } + [builder setTextBody:message]; + + NSDictionary *additionalHeaders = (NSDictionary *)[additionalHeadersString parseJSON]; + if (additionalHeaders!=nil && [additionalHeaders isKindOfClass:[NSDictionary class]]) { + NSArray *keys = [additionalHeaders allKeys]; + for (unsigned int i=0; i<[keys count]; i++) { + [[builder header] setExtraHeaderValue:[additionalHeaders objectForKey:[keys objectAtIndex:i]] forName:[keys objectAtIndex:i]]; + } + } + + NSData *rfc822Data = [builder data]; + MGMEmail *email = [[MGMEmail new] autorelease]; + [email setEmailAddress:(user!=nil && ![user isEqual:@""] ? user : fromEmail)]; + [email setRFC822Data:rfc822Data]; + [controller addToQueue:email]; + + NSDictionary *response = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], @"success", nil]; + [self print:[response JSONValue]]; + } + } else { + NSDictionary *response = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO], @"success", @"Invalid input", @"error", nil]; + [self print:[response JSONValue]]; + } + + [super replyToClient]; +} +@end diff --git a/EmailScheduler/main.m b/EmailScheduler/main.m new file mode 100644 index 0000000..d28f23a --- /dev/null +++ b/EmailScheduler/main.m @@ -0,0 +1,38 @@ +// +// main.m +// EmailScheduler +// +// Created by James Coleman on 9/13/14. +// Copyright (c) 2014 Mr. Gecko's Media (James Coleman). http://mrgeckosmedia.com/ +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +#import +#import "MGMController.h" + +int main(int argc, const char * argv[]) { + @autoreleasepool { + MGMController *controller = [[MGMController alloc] init]; + [[NSRunLoop currentRunLoop] run]; + [controller release]; + } + return 0; +} + diff --git a/MailCore.framework/Headers b/MailCore.framework/Headers new file mode 120000 index 0000000..a177d2a --- /dev/null +++ b/MailCore.framework/Headers @@ -0,0 +1 @@ +Versions/Current/Headers \ No newline at end of file diff --git a/MailCore.framework/MailCore b/MailCore.framework/MailCore new file mode 120000 index 0000000..6bc6fda --- /dev/null +++ b/MailCore.framework/MailCore @@ -0,0 +1 @@ +Versions/Current/MailCore \ No newline at end of file diff --git a/MailCore.framework/Resources b/MailCore.framework/Resources new file mode 120000 index 0000000..953ee36 --- /dev/null +++ b/MailCore.framework/Resources @@ -0,0 +1 @@ +Versions/Current/Resources \ No newline at end of file diff --git a/MailCore.framework/Versions/A/Headers/MCAbstract.h b/MailCore.framework/Versions/A/Headers/MCAbstract.h new file mode 100644 index 0000000..03299ec --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCAbstract.h @@ -0,0 +1,13 @@ +#ifndef MAILCORE_MCABSTRACT_H + +#define MAILCORE_MCABSTRACT_H + +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCAbstractMessage.h b/MailCore.framework/Versions/A/Headers/MCAbstractMessage.h new file mode 100644 index 0000000..b03d5f2 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCAbstractMessage.h @@ -0,0 +1,46 @@ +#ifndef MAILCORE_MCABSTRACTMESSAGE_H + +#define MAILCORE_MCABSTRACTMESSAGE_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class AbstractPart; + class MessageHeader; + + class AbstractMessage : public Object { + public: + AbstractMessage(); + virtual ~AbstractMessage(); + + virtual MessageHeader * header(); + virtual void setHeader(MessageHeader * header); + + virtual AbstractPart * partForContentID(String * contentID); + virtual AbstractPart * partForUniqueID(String * uniqueID); + + virtual Array * /* AbstractPart */ attachments(); + virtual Array * /* AbstractPart */ htmlInlineAttachments(); + virtual Array * /* AbstractPart */ requiredPartsForRendering(); + + public: //subclass behavior + AbstractMessage(AbstractMessage * other); + virtual String * description(); + virtual Object * copy(); + virtual HashMap * serializable(); + virtual void importSerializable(HashMap * hashmap); + + private: + MessageHeader * mHeader; + void init(); + + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCAbstractMessagePart.h b/MailCore.framework/Versions/A/Headers/MCAbstractMessagePart.h new file mode 100644 index 0000000..1df6459 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCAbstractMessagePart.h @@ -0,0 +1,45 @@ +#ifndef MAILCORE_MCABSTRACTMESSAGEPART_H + +#define MAILCORE_MCABSTRACTMESSAGEPART_H + +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class MessageHeader; + + class AbstractMessagePart : public AbstractPart { + public: + AbstractMessagePart(); + virtual ~AbstractMessagePart(); + + virtual MessageHeader * header(); + virtual void setHeader(MessageHeader * header); + + virtual AbstractPart * mainPart(); + virtual void setMainPart(AbstractPart * mainPart); + + public: //subclass behavior + AbstractMessagePart(AbstractMessagePart * other); + virtual String * description(); + virtual Object * copy(); + virtual HashMap * serializable(); + virtual void importSerializable(HashMap * serializable); + + virtual AbstractPart * partForContentID(String * contentID); + virtual AbstractPart * partForUniqueID(String * uniqueID); + + private: + AbstractPart * mMainPart; + MessageHeader * mHeader; + void init(); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCAbstractMultipart.h b/MailCore.framework/Versions/A/Headers/MCAbstractMultipart.h new file mode 100644 index 0000000..c2a07be --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCAbstractMultipart.h @@ -0,0 +1,39 @@ +#ifndef MAILCORE_MCABSTRACTMULTIPART_H + +#define MAILCORE_MCABSTRACTMULTIPART_H + +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class AbstractMultipart : public AbstractPart { + public: + AbstractMultipart(); + virtual ~AbstractMultipart(); + + virtual Array * parts(); + virtual void setParts(Array * parts); + + public: //subclass behavior + AbstractMultipart(AbstractMultipart * other); + virtual String * description(); + virtual Object * copy(); + virtual HashMap * serializable(); + virtual void importSerializable(HashMap * serializable); + + virtual AbstractPart * partForContentID(String * contentID); + virtual AbstractPart * partForUniqueID(String * uniqueID); + + private: + Array * mParts; + void init(); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCAbstractPart.h b/MailCore.framework/Versions/A/Headers/MCAbstractPart.h new file mode 100644 index 0000000..7f64120 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCAbstractPart.h @@ -0,0 +1,80 @@ +#ifndef MAILCORE_MCABSTRACTPART_H + +#define MAILCORE_MCABSTRACTPART_H + +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class AbstractMessage; + + class AbstractPart : public Object { + public: + AbstractPart(); + virtual ~AbstractPart(); + + virtual PartType partType(); + virtual void setPartType(PartType type); + + virtual String * filename(); + virtual void setFilename(String * filename); + + virtual String * mimeType(); + virtual void setMimeType(String * mimeType); + + virtual String * charset(); + virtual void setCharset(String * charset); + + virtual String * uniqueID(); + virtual void setUniqueID(String * uniqueID); + + virtual String * contentID(); + virtual void setContentID(String * contentID); + + virtual String * contentLocation(); + virtual void setContentLocation(String * contentLocation); + + virtual String * contentDescription(); + virtual void setContentDescription(String * contentDescription); + + virtual bool isInlineAttachment(); + virtual void setInlineAttachment(bool inlineAttachment); + + virtual AbstractPart * partForContentID(String * contentID); + virtual AbstractPart * partForUniqueID(String * uniqueID); + + virtual String * decodedStringForData(Data * data); + + public: // subclass behavior + AbstractPart(AbstractPart * other); + virtual String * description(); + virtual Object * copy(); + virtual HashMap * serializable(); + virtual void importSerializable(HashMap * serializable); + + public: // private + virtual void importIMAPFields(struct mailimap_body_fields * fields, + struct mailimap_body_ext_1part * extension); + virtual void applyUniquePartID(); + + private: + String * mUniqueID; + String * mFilename; + String * mMimeType; + String * mCharset; + String * mContentID; + String * mContentLocation; + String * mContentDescription; + bool mInlineAttachment; + PartType mPartType; + void init(); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCAddress.h b/MailCore.framework/Versions/A/Headers/MCAddress.h new file mode 100644 index 0000000..c55efe5 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCAddress.h @@ -0,0 +1,65 @@ +#ifndef MAILCORE_MCADDRESS_H + +#define MAILCORE_MCADDRESS_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class Address : public Object { + public: + Address(); + virtual ~Address(); + + static Address * addressWithDisplayName(String * displayName, String * mailbox); + static Address * addressWithMailbox(String * mailbox); + static Address * addressWithRFC822String(String * RFC822String); + static Address * addressWithNonEncodedRFC822String(String * nonEncodedRFC822String); + + static Array * addressesWithRFC822String(String * string); + static Array * addressesWithNonEncodedRFC822String(String * string); + + static String * RFC822StringForAddresses(Array * addresses); + static String * nonEncodedRFC822StringForAddresses(Array * addresses); + + virtual void setDisplayName(String * displayName); + virtual String * displayName(); + + virtual void setMailbox(String * address); + virtual String * mailbox(); + + virtual String * RFC822String(); + virtual String * nonEncodedRFC822String(); + + public: // subclass behavior. + Address(Address * other); + virtual String * description(); + virtual bool isEqual(Object * otherObject); + virtual unsigned int hash(); + virtual Object * copy(); + virtual HashMap * serializable(); + virtual void importSerializable(HashMap * serializable); + + public: // private + // Must be released + virtual struct mailimf_address * createIMFAddress(); + virtual struct mailimf_mailbox * createIMFMailbox(); + + // Additions + static Address * addressWithIMFMailbox(struct mailimf_mailbox * mb); + static Address * addressWithNonEncodedIMFMailbox(struct mailimf_mailbox * mb); + static Address * addressWithIMAPAddress(struct mailimap_address * imap_addr); + + private: + String * mDisplayName; + String * mMailbox; + void init(); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCAddressDisplay.h b/MailCore.framework/Versions/A/Headers/MCAddressDisplay.h new file mode 100644 index 0000000..0282a52 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCAddressDisplay.h @@ -0,0 +1,34 @@ +// +// MCAddressDisplay.h +// testUI +// +// Created by DINH Viêt Hoà on 1/27/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCADDRESSDISPLAY_H + +#define MAILCORE_MCADDRESSDISPLAY_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class AddressDisplay { + public: + static String * displayStringForAddress(Address * address); + static String * shortDisplayStringForAddress(Address * address); + static String * veryShortDisplayStringForAddress(Address * address); + + static String * displayStringForAddresses(Array * /* Address */ addresses); + static String * shortDisplayStringForAddresses(Array * /* Address */ addresses); + static String * veryShortDisplayStringForAddresses(Array * /* Address */ addresses); + }; + +}; + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCArray.h b/MailCore.framework/Versions/A/Headers/MCArray.h new file mode 100644 index 0000000..82e9760 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCArray.h @@ -0,0 +1,58 @@ +#ifndef MAILCORE_MCARRAY_H + +#define MAILCORE_MCARRAY_H + +#include + +#ifdef __cplusplus + +typedef struct carray_s carray; + +namespace mailcore { + + class String; + + class Array : public Object { + public: + Array(); + virtual ~Array(); + + static Array * array(); + static Array * arrayWithObject(Object * obj); + + virtual unsigned int count(); + virtual void addObject(Object * obj); + virtual void removeObjectAtIndex(unsigned int idx); + virtual void removeObject(Object * obj); + virtual int indexOfObject(Object * obj); + virtual Object * objectAtIndex(unsigned int idx); + virtual void replaceObject(unsigned int idx, Object * obj); + virtual void insertObject(unsigned int idx, Object * obj); + virtual void removeAllObjects(); + + virtual void addObjectsFromArray(Array * array); + virtual Object * lastObject(); + virtual void removeLastObject(); + virtual bool containsObject(Object * obj); + + virtual Array * sortedArray(int (* compare)(void * a, void * b, void * context), void * context); + virtual void sortArray(int (* compare)(void * a, void * b, void * context), void * context); + virtual String * componentsJoinedByString(String * delimiter); + + public: // subclass behavior + Array(Array * o); + virtual String * description(); + virtual Object * copy(); + virtual HashMap * serializable(); + virtual void importSerializable(HashMap * serializable); + + private: + carray * mArray; + void init(); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCAssert.h b/MailCore.framework/Versions/A/Headers/MCAssert.h new file mode 100644 index 0000000..4584aa0 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCAssert.h @@ -0,0 +1,15 @@ +#ifndef MAILCORE_MCASSERT_H + +#define MAILCORE_MCASSERT_H + +#define MCAssert(cond) MCAssertInternal(__FILE__, __LINE__, cond, #cond) + +#ifdef __cplusplus +extern "C" { +#endif + void MCAssertInternal(const char * filename, unsigned int line, int cond, const char * condString); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCAsync.h b/MailCore.framework/Versions/A/Headers/MCAsync.h new file mode 100644 index 0000000..90b3e26 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCAsync.h @@ -0,0 +1,18 @@ +// +// MCAsync.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/11/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCASYNC_H + +#define MAILCORE_MCASYNC_H + +#include +#include +#include +#include + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCAsyncIMAP.h b/MailCore.framework/Versions/A/Headers/MCAsyncIMAP.h new file mode 100755 index 0000000..da032c7 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCAsyncIMAP.h @@ -0,0 +1,35 @@ +// +// MCAsyncIMAP.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/12/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCASYNCIMAP_H + +#define MAILCORE_MCASYNCIMAP_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCAsyncNNTP.h b/MailCore.framework/Versions/A/Headers/MCAsyncNNTP.h new file mode 100644 index 0000000..56509ff --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCAsyncNNTP.h @@ -0,0 +1,21 @@ +// +// MCAsyncNNTP.h +// mailcore2 +// +// Created by Robert Widmann on 8/13/14. +// Copyright (c) 2014 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCASYNCNNTP_H + +#define MAILCORE_MCASYNCNNTP_H + +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCAsyncPOP.h b/MailCore.framework/Versions/A/Headers/MCAsyncPOP.h new file mode 100644 index 0000000..7974031 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCAsyncPOP.h @@ -0,0 +1,20 @@ +// +// MCAsyncPOP.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/16/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCASYNCPOP_H + +#define MAILCORE_MCASYNCPOP_H + +#include +#include +#include +#include +#include +#include + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCAsyncSMTP.h b/MailCore.framework/Versions/A/Headers/MCAsyncSMTP.h new file mode 100644 index 0000000..d7bac9d --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCAsyncSMTP.h @@ -0,0 +1,17 @@ +// +// MCAsyncSMTP.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/11/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCASYNCSMTP_H + +#define MAILCORE_MCASYNCSMTP_H + +#include +#include +#include + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCAttachment.h b/MailCore.framework/Versions/A/Headers/MCAttachment.h new file mode 100644 index 0000000..069688f --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCAttachment.h @@ -0,0 +1,63 @@ +#ifndef MAILCORE_MCATTACHMENT_H + +#define MAILCORE_MCATTACHMENT_H + +#include +#include +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class MessagePart; + + class Attachment : public AbstractPart { + public: + static String * mimeTypeForFilename(String * filename); + static Attachment * attachmentWithContentsOfFile(String * filename); + static Attachment * attachmentWithData(String * filename, Data * data); + static Attachment * attachmentWithHTMLString(String * htmlString); + static Attachment * attachmentWithRFC822Message(Data * messageData); + static Attachment * attachmentWithText(String * text); + + Attachment(); + virtual ~Attachment(); + + virtual void setData(Data * data); + virtual Data * data(); + virtual String * decodedString(); + + virtual void setContentTypeParameter(String * name, String * value); + virtual void removeContentTypeParameter(String * name); + virtual String * contentTypeParameterValueForName(String *name); + virtual Array * allContentTypeParametersNames(); + + public: // subclass behavior + Attachment(Attachment * other); + virtual String * description(); + virtual Object * copy(); + + public: // private + static AbstractPart * attachmentsWithMIME(struct mailmime * mime); + + private: + Data * mData; + HashMap * mContentTypeParameters; + HashMap * mlcContentTypeParameters; + void init(); + static void fillMultipartSubAttachments(AbstractMultipart * multipart, struct mailmime * mime); + static AbstractPart * attachmentsWithMIMEWithMain(struct mailmime * mime, bool isMain); + static Attachment * attachmentWithSingleMIME(struct mailmime * mime); + static MessagePart * attachmentWithMessageMIME(struct mailmime * mime); + static Encoding encodingForMIMEEncoding(struct mailmime_mechanism * mechanism, int defaultMimeEncoding); + static HashMap * readMimeTypesFile(String * filename); + void setContentTypeParameters(HashMap * parameters); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCAutoreleasePool.h b/MailCore.framework/Versions/A/Headers/MCAutoreleasePool.h new file mode 100644 index 0000000..f987fd0 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCAutoreleasePool.h @@ -0,0 +1,44 @@ +#ifndef MAILCORE_MCAUTORELEASEPOOL_H + +#define MAILCORE_MCAUTORELEASEPOOL_H + +#include +#include + +#ifdef __cplusplus + +typedef struct carray_s carray; + +namespace mailcore { + + class AutoreleasePool : public Object { + public: + AutoreleasePool(); + virtual ~AutoreleasePool(); + + static void autorelease(Object * obj); + + public: // subclass behavior + virtual String * description(); + + private: + static void init(); + static pthread_key_t autoreleasePoolStackKey; + carray * mPoolObjects; + static carray * createAutoreleasePoolStackIfNeeded(); + static void destroyAutoreleasePoolStack(void *); + static void initAutoreleasePoolStackKey(); + static AutoreleasePool * currentAutoreleasePool(); + virtual void add(Object * obj); +#ifdef __APPLE__ + void * mAppleAutoreleasePool; + static void * createAppleAutoreleasePool(); + static void releaseAppleAutoreleasePool(void * appleAutoreleasePool); +#endif + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCBaseTypes.h b/MailCore.framework/Versions/A/Headers/MCBaseTypes.h new file mode 100644 index 0000000..ce3e115 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCBaseTypes.h @@ -0,0 +1,30 @@ +#ifndef MAILCORE_MCBASETYPES_H + +#define MAILCORE_MCBASETYPES_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCConnectionLogger.h b/MailCore.framework/Versions/A/Headers/MCConnectionLogger.h new file mode 100644 index 0000000..4e2249f --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCConnectionLogger.h @@ -0,0 +1,45 @@ +// +// MCConnectionLogger.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 6/24/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_CONNECTION_LOGGER_H + +#define MAILCORE_CONNECTION_LOGGER_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class Data; + + enum ConnectionLogType { + // Received data + ConnectionLogTypeReceived, + // Sent data + ConnectionLogTypeSent, + // Sent private data + ConnectionLogTypeSentPrivate, + // Parse error + ConnectionLogTypeErrorParse, + // Error while receiving data - log() is called with a NULL buffer. + ConnectionLogTypeErrorReceived, + // Error while sending data - log() is called with a NULL buffer. + ConnectionLogTypeErrorSent, + }; + + class ConnectionLogger { + public: + virtual void log(void * sender, ConnectionLogType logType, Data * buffer) {} + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCCore.h b/MailCore.framework/Versions/A/Headers/MCCore.h new file mode 100644 index 0000000..323bb60 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCCore.h @@ -0,0 +1,23 @@ +// +// Core.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/10/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCCORE_H + +#define MAILCORE_MCCORE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCData.h b/MailCore.framework/Versions/A/Headers/MCData.h new file mode 100644 index 0000000..6ba056e --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCData.h @@ -0,0 +1,68 @@ +#ifndef MAILCORE_MCDATA_H + +#define MAILCORE_MCDATA_H + +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class String; + + class Data : public Object { + public: + Data(); + Data(int capacity); + Data(const char * bytes, unsigned int length); + virtual ~Data(); + + static Data * data(); + static Data * dataWithCapacity(int capacity); + static Data * dataWithContentsOfFile(String * filename); + static Data * dataWithBytes(const char * bytes, unsigned int length); + + virtual char * bytes(); + virtual unsigned int length(); + + virtual void appendData(Data * otherData); + virtual void appendBytes(const char * bytes, unsigned int length); + virtual void setBytes(const char * bytes, unsigned int length); + virtual void setData(Data * otherData); + + // Helpers + virtual String * stringWithDetectedCharset(); + virtual String * stringWithDetectedCharset(String * charset, bool isHTML); + virtual String * stringWithCharset(const char * charset); + virtual Data * decodedDataUsingEncoding(Encoding encoding); + + virtual String * base64String(); + + public: // private + virtual String * charsetWithFilteredHTML(bool filterHTML, String * hintCharset = NULL); + + public: // subclass behavior + Data(Data * otherData); + virtual String * description(); + virtual Object * copy(); + virtual bool isEqual(Object * otherObject); + virtual unsigned int hash(); + virtual HashMap * serializable(); + virtual void importSerializable(HashMap * serializable); + + private: + char * mBytes; + unsigned int mLength; + unsigned int mAllocated; + void allocate(unsigned int length); + void reset(); + String * charsetWithFilteredHTMLWithoutHint(bool filterHTML); + + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCDateFormatter.h b/MailCore.framework/Versions/A/Headers/MCDateFormatter.h new file mode 100644 index 0000000..c4e21c0 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCDateFormatter.h @@ -0,0 +1,75 @@ +// +// MCDateFormatter.h +// testUI +// +// Created by DINH Viêt Hoà on 1/28/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCDATEFORMATTER_H + +#define MAILCORE_MCDATEFORMATTER_H + +#include + +// predeclare UDateFormat +// copied from +typedef void * UDateFormat; + +#ifdef __cplusplus + +namespace mailcore { + + class String; + + // Uses same values as UDateFormatStyle + enum DateFormatStyle { + DateFormatStyleFull = 0 /* UDAT_FULL*/, + DateFormatStyleLong = 1 /* UDAT_LONG */, + DateFormatStyleMedium = 2 /* UDAT_MEDIUM */, + DateFormatStyleShort = 3 /* UDAT_SHORT */, + DateFormatStyleNone = -1 /* UDAT_NONE */, + }; + + class DateFormatter : public Object { + public: + DateFormatter(); + virtual ~DateFormatter(); + + static DateFormatter * dateFormatter(); + + virtual void setDateStyle(DateFormatStyle style); + virtual DateFormatStyle dateStyle(); + + virtual void setTimeStyle(DateFormatStyle style); + virtual DateFormatStyle timeStyle(); + + virtual void setLocale(String * locale); + virtual String * locale(); + + virtual void setTimezone(String * timezone); + virtual String * timezone(); + + virtual void setDateFormat(String * dateFormat); + virtual String * dateFormat(); + + virtual String * stringFromDate(time_t date); + virtual time_t dateFromString(String * dateString); + + private: + UDateFormat * mDateFormatter; + DateFormatStyle mDateStyle; + DateFormatStyle mTimeStyle; + String * mDateFormat; + String * mTimezone; + String * mLocale; + void * mAppleDateFormatter; + + void prepare(); + }; + +} + +#endif + +#endif /* defined(__testUI__MCDateFormatter__) */ diff --git a/MailCore.framework/Versions/A/Headers/MCHTMLRendererCallback.h b/MailCore.framework/Versions/A/Headers/MCHTMLRendererCallback.h new file mode 100644 index 0000000..030b691 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCHTMLRendererCallback.h @@ -0,0 +1,61 @@ +// +// MCHTMLRendererCallback.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 2/2/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCHTMLRENDERERCALLBACK_H + +#define MAILCORE_MCHTMLRENDERERCALLBACK_H + +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class MessageParser; + + class HTMLRendererIMAPCallback { + public: + HTMLRendererIMAPCallback() {} + virtual ~HTMLRendererIMAPCallback() {} + + virtual Data * dataForIMAPPart(String * folder, IMAPPart * part) { return NULL; } + virtual void prefetchAttachmentIMAPPart(String * folder, IMAPPart * part) {} + virtual void prefetchImageIMAPPart(String * folder, IMAPPart * part) {} + }; + + class HTMLRendererTemplateCallback { + public: + virtual bool canPreviewPart(AbstractPart * part); + virtual bool shouldShowPart(AbstractPart * part); + + virtual HashMap * templateValuesForHeader(MessageHeader * header); + virtual HashMap * templateValuesForPart(AbstractPart * part); + + virtual String * templateForMainHeader(MessageHeader * header); + virtual String * templateForImage(AbstractPart * part); + virtual String * templateForAttachment(AbstractPart * part); + virtual String * templateForMessage(AbstractMessage * message); + virtual String * templateForEmbeddedMessage(AbstractMessagePart * part); + virtual String * templateForEmbeddedMessageHeader(MessageHeader * header); + virtual String * templateForAttachmentSeparator(); + + virtual String * cleanHTMLForPart(String * html); + + // Can be used to filter some HTML tags. + virtual String * filterHTMLForPart(String * html); + + // Can be used to hide quoted text. + virtual String * filterHTMLForMessage(String * html); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCHash.h b/MailCore.framework/Versions/A/Headers/MCHash.h new file mode 100644 index 0000000..5ef0c29 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCHash.h @@ -0,0 +1,15 @@ +#ifndef MAILCORE_MCHASH_H + +#define MAILCORE_MCHASH_H + +#ifdef __cplusplus + +namespace mailcore { + + unsigned int hashCompute(const char * key, unsigned int len); + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCHashMap.h b/MailCore.framework/Versions/A/Headers/MCHashMap.h new file mode 100644 index 0000000..ea533df --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCHashMap.h @@ -0,0 +1,52 @@ +#ifndef MAILCORE_MCHASHMAP_H + +#define MAILCORE_MCHASHMAP_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class String; + class Array; + struct HashMapCell; + typedef HashMapCell HashMapIter; + + class HashMap : public Object { + public: + HashMap(); + virtual ~HashMap(); + + static HashMap * hashMap(); + + virtual unsigned int count(); + virtual void setObjectForKey(Object * key, Object * value); + virtual void removeObjectForKey(Object * key); + virtual Object * objectForKey(Object * key); + virtual Array * allKeys(); + virtual Array * allValues(); + virtual void removeAllObjects(); + + public: // subclass behavior + HashMap(HashMap * o); + virtual String * description(); + virtual Object * copy(); + virtual HashMap * serializable(); + virtual void importSerializable(HashMap * serializable); + + private: + unsigned int mAllocated; + unsigned int mCount; + void ** mCells; + HashMapIter * iteratorBegin(); + HashMapIter * iteratorNext(HashMapIter * iter); + void allocate(unsigned int size); + void init(); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCICUTypes.h b/MailCore.framework/Versions/A/Headers/MCICUTypes.h new file mode 100644 index 0000000..5b43c5d --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCICUTypes.h @@ -0,0 +1,19 @@ +// +// MCICUTypes.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 4/18/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCICUTYPES_H + +#define MAILCORE_MCICUTYPES_H + +#if defined(__CHAR16_TYPE__) +typedef __CHAR16_TYPE__ UChar; +#else +typedef uint16_t UChar; +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCIMAP.h b/MailCore.framework/Versions/A/Headers/MCIMAP.h new file mode 100644 index 0000000..6e80995 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIMAP.h @@ -0,0 +1,19 @@ +#ifndef MAILCORE_MCIMAP_H + +#define MAILCORE_MCIMAP_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCIMAPAppendMessageOperation.h b/MailCore.framework/Versions/A/Headers/MCIMAPAppendMessageOperation.h new file mode 100644 index 0000000..463d65d --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIMAPAppendMessageOperation.h @@ -0,0 +1,55 @@ +// +// MCIMAPAppendMessageOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/12/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCIMAPAPPENDMESSAGEOPERATION_H + +#define MAILCORE_MCIMAPAPPENDMESSAGEOPERATION_H + +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class IMAPAppendMessageOperation : public IMAPOperation { + public: + IMAPAppendMessageOperation(); + virtual ~IMAPAppendMessageOperation(); + + virtual void setMessageData(Data * messageData); + virtual Data * messageData(); + + virtual void setFlags(MessageFlag flags); + virtual MessageFlag flags(); + + virtual void setCustomFlags(Array * customFlags); + virtual Array * customFlags(); + + virtual void setDate(time_t date); + virtual time_t date(); + + virtual uint32_t createdUID(); + + public: // subclass behavior + virtual void main(); + + private: + Data * mMessageData; + MessageFlag mFlags; + Array * mCustomFlags; + time_t mDate; + uint32_t mCreatedUID; + + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCIMAPAsyncSession.h b/MailCore.framework/Versions/A/Headers/MCIMAPAsyncSession.h new file mode 100755 index 0000000..333783b --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIMAPAsyncSession.h @@ -0,0 +1,206 @@ +// +// MCIMAPAccount.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/17/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCIMAPACCOUNT_H + +#define MAILCORE_MCIMAPACCOUNT_H + +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class IMAPOperation; + class IMAPFetchFoldersOperation; + class IMAPAppendMessageOperation; + class IMAPCopyMessagesOperation; + class IMAPFetchMessagesOperation; + class IMAPFetchContentOperation; + class IMAPIdleOperation; + class IMAPFolderInfoOperation; + class IMAPFolderStatusOperation; + class IMAPNamespace; + class IMAPSearchOperation; + class IMAPSearchExpression; + class IMAPFetchNamespaceOperation; + class IMAPIdentityOperation; + class IMAPAsyncConnection; + class IMAPCapabilityOperation; + class IMAPQuotaOperation; + class IMAPMessageRenderingOperation; + class IMAPMessage; + class IMAPSession; + class IMAPIdentity; + class OperationQueueCallback; + + class IMAPAsyncSession : public Object { + public: + IMAPAsyncSession(); + virtual ~IMAPAsyncSession(); + + virtual void setHostname(String * hostname); + virtual String * hostname(); + + virtual void setPort(unsigned int port); + virtual unsigned int port(); + + virtual void setUsername(String * username); + virtual String * username(); + + virtual void setPassword(String * password); + virtual String * password(); + + // To authenticate using OAuth2, username and oauth2token should be set. + // auth type to use is AuthTypeOAuth2. + virtual void setOAuth2Token(String * token); + virtual String * OAuth2Token(); + + virtual void setAuthType(AuthType authType); + virtual AuthType authType(); + + virtual void setConnectionType(ConnectionType connectionType); + virtual ConnectionType connectionType(); + + virtual void setTimeout(time_t timeout); + virtual time_t timeout(); + + virtual void setCheckCertificateEnabled(bool enabled); + virtual bool isCheckCertificateEnabled(); + + virtual void setVoIPEnabled(bool enabled); + virtual bool isVoIPEnabled(); + + virtual void setDefaultNamespace(IMAPNamespace * ns); + virtual IMAPNamespace * defaultNamespace(); + + virtual void setAllowsFolderConcurrentAccessEnabled(bool enabled); + virtual bool allowsFolderConcurrentAccessEnabled(); + + virtual void setMaximumConnections(unsigned int maxConnections); + virtual unsigned int maximumConnections(); + + virtual void setConnectionLogger(ConnectionLogger * logger); + virtual ConnectionLogger * connectionLogger(); + +#ifdef __APPLE__ + virtual void setDispatchQueue(dispatch_queue_t dispatchQueue); + virtual dispatch_queue_t dispatchQueue(); +#endif + + virtual void setOperationQueueCallback(OperationQueueCallback * callback); + virtual OperationQueueCallback * operationQueueCallback(); + virtual bool isOperationQueueRunning(); + virtual void cancelAllOperations(); + + virtual IMAPIdentity * serverIdentity(); + virtual IMAPIdentity * clientIdentity(); + virtual String * gmailUserDisplayName(); + + virtual IMAPFolderInfoOperation * folderInfoOperation(String * folder); + virtual IMAPFolderStatusOperation * folderStatusOperation(String * folder); + + virtual IMAPFetchFoldersOperation * fetchSubscribedFoldersOperation(); + virtual IMAPFetchFoldersOperation * fetchAllFoldersOperation(); + + virtual IMAPOperation * renameFolderOperation(String * folder, String * otherName); + virtual IMAPOperation * deleteFolderOperation(String * folder); + virtual IMAPOperation * createFolderOperation(String * folder); + + virtual IMAPOperation * subscribeFolderOperation(String * folder); + virtual IMAPOperation * unsubscribeFolderOperation(String * folder); + + virtual IMAPAppendMessageOperation * appendMessageOperation(String * folder, Data * messageData, MessageFlag flags, Array * customFlags = NULL); + + virtual IMAPCopyMessagesOperation * copyMessagesOperation(String * folder, IndexSet * uids, String * destFolder); + + virtual IMAPOperation * expungeOperation(String * folder); + + virtual IMAPFetchMessagesOperation * fetchMessagesByUIDOperation(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * indexes); + virtual IMAPFetchMessagesOperation * fetchMessagesByNumberOperation(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * indexes); + virtual IMAPFetchMessagesOperation * syncMessagesByUID(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * indexes, uint64_t modSeq); + + virtual IMAPFetchContentOperation * fetchMessageByUIDOperation(String * folder, uint32_t uid, bool urgent = false); + virtual IMAPFetchContentOperation * fetchMessageAttachmentByUIDOperation(String * folder, uint32_t uid, String * partID, + Encoding encoding, bool urgent = false); + + virtual IMAPOperation * storeFlagsOperation(String * folder, IndexSet * uids, IMAPStoreFlagsRequestKind kind, MessageFlag flags, Array * customFlags = NULL); + virtual IMAPOperation * storeLabelsOperation(String * folder, IndexSet * uids, IMAPStoreFlagsRequestKind kind, Array * labels); + + virtual IMAPSearchOperation * searchOperation(String * folder, IMAPSearchKind kind, String * searchString); + virtual IMAPSearchOperation * searchOperation(String * folder, IMAPSearchExpression * expression); + + virtual IMAPIdleOperation * idleOperation(String * folder, uint32_t lastKnownUID); + + virtual IMAPFetchNamespaceOperation * fetchNamespaceOperation(); + + virtual IMAPIdentityOperation * identityOperation(IMAPIdentity * identity); + + virtual IMAPOperation * connectOperation(); + virtual IMAPOperation * checkAccountOperation(); + virtual IMAPOperation * disconnectOperation(); + + virtual IMAPCapabilityOperation * capabilityOperation(); + virtual IMAPQuotaOperation * quotaOperation(); + + virtual IMAPOperation * noopOperation(); + + virtual IMAPMessageRenderingOperation * htmlRenderingOperation(IMAPMessage * message, String * folder); + virtual IMAPMessageRenderingOperation * htmlBodyRenderingOperation(IMAPMessage * message, String * folder); + virtual IMAPMessageRenderingOperation * plainTextRenderingOperation(IMAPMessage * message, String * folder); + virtual IMAPMessageRenderingOperation * plainTextBodyRenderingOperation(IMAPMessage * message, String * folder, bool stripWhitespace); + + public: // private + virtual void automaticConfigurationDone(IMAPSession * session); + virtual void operationRunningStateChanged(); + virtual IMAPAsyncConnection * sessionForFolder(String * folder, bool urgent = false); + + private: + Array * mSessions; + + String * mHostname; + unsigned int mPort; + String * mUsername; + String * mPassword; + String * mOAuth2Token; + AuthType mAuthType; + ConnectionType mConnectionType; + bool mCheckCertificateEnabled; + bool mVoIPEnabled; + IMAPNamespace * mDefaultNamespace; + time_t mTimeout; + bool mAllowsFolderConcurrentAccessEnabled; + unsigned int mMaximumConnections; + ConnectionLogger * mConnectionLogger; + bool mAutomaticConfigurationDone; + IMAPIdentity * mServerIdentity; + IMAPIdentity * mClientIdentity; + bool mQueueRunning; + OperationQueueCallback * mOperationQueueCallback; +#if __APPLE__ + dispatch_queue_t mDispatchQueue; +#endif + String * mGmailUserDisplayName; + + virtual IMAPAsyncConnection * session(); + virtual IMAPAsyncConnection * matchingSessionForFolder(String * folder); + virtual IMAPAsyncConnection * availableSession(); + virtual IMAPMessageRenderingOperation * renderingOperation(IMAPMessage * message, + String * folder, + IMAPMessageRenderingType type); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCIMAPCapabilityOperation.h b/MailCore.framework/Versions/A/Headers/MCIMAPCapabilityOperation.h new file mode 100644 index 0000000..b205bd8 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIMAPCapabilityOperation.h @@ -0,0 +1,38 @@ +// +// MCIMAPCapabilityOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/4/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCIMAPCAPABILITYOPERATION_H + +#define MAILCORE_MCIMAPCAPABILITYOPERATION_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class IMAPCapabilityOperation : public IMAPOperation { + public: + IMAPCapabilityOperation(); + virtual ~IMAPCapabilityOperation(); + + // Result. + virtual IndexSet * capabilities(); + + public: // subclass behavior + virtual void main(); + + private: + IndexSet * mCapabilities; + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCIMAPConnectOperation.h b/MailCore.framework/Versions/A/Headers/MCIMAPConnectOperation.h new file mode 100644 index 0000000..f48247e --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIMAPConnectOperation.h @@ -0,0 +1,28 @@ +// +// MCIMAPConnectOperation.h +// mailcore2 +// +// Created by Ryan Walklin on 6/09/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCIMAPCONNECTOPERATION_H + +#define MAILCORE_MCIMAPCONNECTOPERATION_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class IMAPConnectOperation : public IMAPOperation { + public: // subclass behavior + virtual void main(); + }; + +} + +#endif + +#endif /* defined(__MAILCORE_MCIMAPCONNECTOPERATION_H_) */ diff --git a/MailCore.framework/Versions/A/Headers/MCIMAPCopyMessagesOperation.h b/MailCore.framework/Versions/A/Headers/MCIMAPCopyMessagesOperation.h new file mode 100644 index 0000000..a4b5d54 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIMAPCopyMessagesOperation.h @@ -0,0 +1,46 @@ +// +// MCIMAPCopyMessagesOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/12/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCIMAPCOPYMESSAGESOPERATION_H + +#define MAILCORE_MCIMAPCOPYMESSAGESOPERATION_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class IMAPCopyMessagesOperation : public IMAPOperation { + public: + IMAPCopyMessagesOperation(); + virtual ~IMAPCopyMessagesOperation(); + + virtual void setDestFolder(String * destFolder); + virtual String * destFolder(); + + virtual void setUids(IndexSet * uids); + virtual IndexSet * uids(); + + // Result. + virtual HashMap * uidMapping(); + + public: // subclass behavior + virtual void main(); + + private: + IndexSet * mUids; + String * mDestFolder; + HashMap * mUidMapping; + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCIMAPFetchContentOperation.h b/MailCore.framework/Versions/A/Headers/MCIMAPFetchContentOperation.h new file mode 100644 index 0000000..3d4dd17 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIMAPFetchContentOperation.h @@ -0,0 +1,51 @@ +// +// IMAPFetchContentOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/12/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_IMAPFETCHCONTENTOPERATION_H + +#define MAILCORE_IMAPFETCHCONTENTOPERATION_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class IMAPFetchContentOperation : public IMAPOperation { + public: + IMAPFetchContentOperation(); + virtual ~IMAPFetchContentOperation(); + + virtual void setUid(uint32_t uid); + virtual uint32_t uid(); + + virtual void setPartID(String * partID); + virtual String * partID(); + + virtual void setEncoding(Encoding encoding); + virtual Encoding encoding(); + + // Result. + virtual Data * data(); + + public: // subclass behavior + virtual void main(); + + private: + uint32_t mUid; + String * mPartID; + Encoding mEncoding; + Data * mData; + + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCIMAPFetchFoldersOperation.h b/MailCore.framework/Versions/A/Headers/MCIMAPFetchFoldersOperation.h new file mode 100644 index 0000000..8335154 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIMAPFetchFoldersOperation.h @@ -0,0 +1,44 @@ +// +// MCIMAPFetchFoldersOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/12/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCIMAPFETCHFOLDERSOPERATION_H + +#define MAILCORE_MCIMAPFETCHFOLDERSOPERATION_H + +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class IMAPFetchFoldersOperation : public IMAPOperation { + public: + IMAPFetchFoldersOperation(); + virtual ~IMAPFetchFoldersOperation(); + + virtual void setFetchSubscribedEnabled(bool enabled); + virtual bool isFetchSubscribedEnabled(); + + // Result. + virtual Array * /* IMAPFolder */ folders(); + + public: // subclass behavior + virtual void main(); + + private: + bool mFetchSubscribedEnabled; + Array * mFolders; + + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCIMAPFetchMessagesOperation.h b/MailCore.framework/Versions/A/Headers/MCIMAPFetchMessagesOperation.h new file mode 100644 index 0000000..3183508 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIMAPFetchMessagesOperation.h @@ -0,0 +1,61 @@ +// +// IMAPFetchMessagesOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/12/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCIMAPFETCHMESSAGESOPERATION_H + +#define MAILCORE_MCIMAPFETCHMESSAGESOPERATION_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class IMAPFetchMessagesOperation : public IMAPOperation { + public: + IMAPFetchMessagesOperation(); + virtual ~IMAPFetchMessagesOperation(); + + virtual void setFetchByUidEnabled(bool enabled); + virtual bool isFetchByUidEnabled(); + + virtual void setIndexes(IndexSet * indexes); + virtual IndexSet * indexes(); + + virtual void setModSequenceValue(uint64_t modseq); + virtual uint64_t modSequenceValue(); + + virtual void setKind(IMAPMessagesRequestKind kind); + virtual IMAPMessagesRequestKind kind(); + + virtual void setExtraHeaders(Array * extraHeaders); + virtual Array * extraHeaders(); + + // Result. + virtual Array * /* IMAPMessage */ messages(); + virtual IndexSet * vanishedMessages(); + + public: // subclass behavior + virtual void main(); + + private: + bool mFetchByUidEnabled; + IndexSet * mIndexes; + IMAPMessagesRequestKind mKind; + Array * /* String */ mExtraHeaders; + Array * /* IMAPMessage */ mMessages; + IndexSet * mVanishedMessages; + uint64_t mModSequenceValue; + + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCIMAPFetchNamespaceOperation.h b/MailCore.framework/Versions/A/Headers/MCIMAPFetchNamespaceOperation.h new file mode 100644 index 0000000..ae85d9d --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIMAPFetchNamespaceOperation.h @@ -0,0 +1,39 @@ +// +// IMAPFetchNamespaceOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/12/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCIMAPFETCHNAMESPACEOPERATION_H + +#define MAILCORE_MCIMAPFETCHNAMESPACEOPERATION_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class IMAPFetchNamespaceOperation : public IMAPOperation { + public: + IMAPFetchNamespaceOperation(); + virtual ~IMAPFetchNamespaceOperation(); + + // Result. + virtual HashMap * namespaces(); + + public: // subclass behavior + virtual void main(); + + private: + HashMap * mNamespaces; + + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCIMAPFolder.h b/MailCore.framework/Versions/A/Headers/MCIMAPFolder.h new file mode 100644 index 0000000..3bc2058 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIMAPFolder.h @@ -0,0 +1,42 @@ +#ifndef MAILCORE_MCIMAPFOLDER_H + +#define MAILCORE_MCIMAPFOLDER_H + +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class IMAPFolder : public Object { + public: + IMAPFolder(); + virtual ~IMAPFolder(); + + virtual void setPath(String * path); + virtual String * path(); + + virtual void setDelimiter(char delimiter); + virtual char delimiter(); + + virtual void setFlags(IMAPFolderFlag flags); + virtual IMAPFolderFlag flags(); + + public: // subclass behavior + IMAPFolder(IMAPFolder * other); + virtual Object * copy(); + virtual String * description(); + + private: + String * mPath; + char mDelimiter; + IMAPFolderFlag mFlags; + void init(); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCIMAPFolderInfoOperation.h b/MailCore.framework/Versions/A/Headers/MCIMAPFolderInfoOperation.h new file mode 100644 index 0000000..b53be2c --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIMAPFolderInfoOperation.h @@ -0,0 +1,49 @@ +// +// MCIMAPFolderInfoOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/13/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCIMAPFOLDERINFOOPERATION_H + +#define MAILCORE_MCIMAPFOLDERINFOOPERATION_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class IMAPFolderInfoOperation : public IMAPOperation { + public: + IMAPFolderInfoOperation(); + virtual ~IMAPFolderInfoOperation(); + + virtual uint32_t uidNext(); + virtual uint32_t uidValidity(); + virtual uint64_t modSequenceValue(); + virtual int messageCount(); + virtual uint32_t firstUnseenUid(); + virtual bool allowsNewPermanentFlags(); + + public: // subclass behavior + virtual void main(); + + private: + + uint32_t mUidNext; + uint32_t mUidValidity; + uint64_t mModSequenceValue; + int mMessageCount; + uint32_t mFirstUnseenUid; + bool mAllowsNewPermanentFlags; + + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCIMAPFolderStatus.h b/MailCore.framework/Versions/A/Headers/MCIMAPFolderStatus.h new file mode 100644 index 0000000..db3243f --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIMAPFolderStatus.h @@ -0,0 +1,64 @@ +// +// MCIMAPFolderStatus.h +// mailcore2 +// +// Created by Sebastian on 6/11/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCIMAPFOLDERSTATUS_H + +#define MAILCORE_MCIMAPFOLDERSTATUS_H + +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class IMAPFolderStatus : public Object { + public: + IMAPFolderStatus(); + virtual ~IMAPFolderStatus(); + + virtual void setUnseenCount(uint32_t unseen); + virtual uint32_t unseenCount(); + + virtual void setMessageCount(uint32_t messages); + virtual uint32_t messageCount(); + + virtual void setRecentCount(uint32_t recent); + virtual uint32_t recentCount(); + + virtual void setUidNext(uint32_t uidNext); + virtual uint32_t uidNext(); + + virtual void setUidValidity(uint32_t uidValidity); + virtual uint32_t uidValidity(); + + virtual void setHighestModSeqValue(uint64_t highestModSeqValue); + virtual uint64_t highestModSeqValue(); + + public: // subclass behavior + IMAPFolderStatus(IMAPFolderStatus * other); + virtual Object * copy(); + virtual String * description(); + + private: + uint32_t mUnseenCount; + uint32_t mMessageCount; + uint32_t mRecentCount; + uint32_t mUidNext; + uint32_t mUidValidity; + uint64_t mHighestModSeqValue; + + void init(); + }; + +} + +#endif + +#endif + diff --git a/MailCore.framework/Versions/A/Headers/MCIMAPFolderStatusOperation.h b/MailCore.framework/Versions/A/Headers/MCIMAPFolderStatusOperation.h new file mode 100644 index 0000000..c1d7024 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIMAPFolderStatusOperation.h @@ -0,0 +1,41 @@ +// +// MCIMAPFolderStatusOperation.h +// mailcore2 +// +// Created by Sebastian on 6/5/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + + +#ifndef MAILCORE_MCIMAPFOLDERSTATUSOPERATION_H + +#define MAILCORE_MCIMAPFOLDERSTATUSOPERATION_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class IMAPFolderStatus; + + class IMAPFolderStatusOperation : public IMAPOperation { + public: + IMAPFolderStatusOperation(); + virtual ~IMAPFolderStatusOperation(); + + // Results. + virtual IMAPFolderStatus * status(); + + public: // subclass behavior + virtual void main(); + + private: + IMAPFolderStatus * mStatus; + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCIMAPIdentity.h b/MailCore.framework/Versions/A/Headers/MCIMAPIdentity.h new file mode 100644 index 0000000..ab96abb --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIMAPIdentity.h @@ -0,0 +1,54 @@ +// +// MCIMAPIdentity.h +// mailcore2 +// +// Created by Hoa V. DINH on 8/24/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCIMAPIDENTITY_H + +#define MAILCORE_MCIMAPIDENTITY_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class IMAPIdentity : public Object { + public: + + IMAPIdentity(); + virtual ~IMAPIdentity(); + + virtual void setVendor(String * vendor); + virtual String * vendor(); + + virtual void setName(String * name); + virtual String * name(); + + virtual void setVersion(String * version); + virtual String * version(); + + virtual Array * allInfoKeys(); + virtual String * infoForKey(String * key); + virtual void setInfoForKey(String * key, String * value); + + public: // subclass behavior + IMAPIdentity(IMAPIdentity * identity); + virtual Object * copy(); + virtual String * description(); + + private: + HashMap * mValues; + + void init(); + }; + +} + +#endif + +#endif + diff --git a/MailCore.framework/Versions/A/Headers/MCIMAPIdentityOperation.h b/MailCore.framework/Versions/A/Headers/MCIMAPIdentityOperation.h new file mode 100644 index 0000000..6caef88 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIMAPIdentityOperation.h @@ -0,0 +1,45 @@ +// +// IMAPIdentityOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/12/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCIMAPIDENTITYOPERATION_H + +#define MAILCORE_MCIMAPIDENTITYOPERATION_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class IMAPIdentity; + + class IMAPIdentityOperation : public IMAPOperation { + public: + IMAPIdentityOperation(); + virtual ~IMAPIdentityOperation(); + + virtual void setClientIdentity(IMAPIdentity * identity); + virtual IMAPIdentity * clientIdentity(); + + // Result. + virtual IMAPIdentity * serverIdentity(); + + public: // subclass behavior + virtual void main(); + + private: + IMAPIdentity * mClientIdentity; + IMAPIdentity * mServerIdentity; + + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCIMAPIdleOperation.h b/MailCore.framework/Versions/A/Headers/MCIMAPIdleOperation.h new file mode 100644 index 0000000..f7491d1 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIMAPIdleOperation.h @@ -0,0 +1,46 @@ +// +// IMAPIdleOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/12/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCIMAPIDLEOPERATION_H + +#define MAILCORE_MCIMAPIDLEOPERATION_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class IMAPIdleOperation : public IMAPOperation { + public: + IMAPIdleOperation(); + virtual ~IMAPIdleOperation(); + + virtual void setLastKnownUID(uint32_t uid); + virtual uint32_t lastKnownUID(); + + virtual void interruptIdle(); + + public: // subclass behavior + virtual void main(); + + private: + uint32_t mLastKnownUid; + bool mSetupSuccess; + bool mInterrupted; + pthread_mutex_t mLock; + void prepare(); + void unprepare(); + bool isInterrupted(); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCIMAPMessage.h b/MailCore.framework/Versions/A/Headers/MCIMAPMessage.h new file mode 100644 index 0000000..a78a04d --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIMAPMessage.h @@ -0,0 +1,88 @@ +#ifndef MAILCORE_IMAP_MESSAGE_H + +#define MAILCORE_IMAP_MESSAGE_H + +#include +#include +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class IMAPPart; + class HTMLRendererIMAPCallback; + class HTMLRendererTemplateCallback; + + class IMAPMessage : public AbstractMessage { + public: + IMAPMessage(); + virtual ~IMAPMessage(); + + virtual uint32_t uid(); + virtual void setUid(uint32_t uid); + + virtual uint32_t size(); + virtual void setSize(uint32_t size); + + virtual void setFlags(MessageFlag flags); + virtual MessageFlag flags(); + + virtual void setOriginalFlags(MessageFlag flags); + virtual MessageFlag originalFlags(); + + virtual void setCustomFlags(Array * customFlags); + virtual Array * customFlags(); + + virtual uint64_t modSeqValue(); + virtual void setModSeqValue(uint64_t uid); + + virtual void setMainPart(AbstractPart * mainPart); + virtual AbstractPart * mainPart(); + + virtual void setGmailLabels(Array * /* String */ labels); + virtual Array * /* String */ gmailLabels(); + + virtual void setGmailMessageID(uint64_t msgID); + virtual uint64_t gmailMessageID(); + + virtual void setGmailThreadID(uint64_t threadID); + virtual uint64_t gmailThreadID(); + + virtual AbstractPart * partForPartID(String * partID); + + virtual AbstractPart * partForContentID(String * contentID); + virtual AbstractPart * partForUniqueID(String * uniqueID); + + virtual String * htmlRendering(String * folder, + HTMLRendererIMAPCallback * dataCallback, + HTMLRendererTemplateCallback * htmlCallback = NULL); + + public: // subclass behavior + IMAPMessage(IMAPMessage * other); + virtual Object * copy(); + virtual String * description(); + virtual HashMap * serializable(); + virtual void importSerializable(HashMap * serializable); + + private: + uint64_t mModSeqValue; + uint32_t mUid; + uint32_t mSize; + + MessageFlag mFlags; + MessageFlag mOriginalFlags; + Array * /* String */ mCustomFlags; + AbstractPart * mMainPart; + Array * /* String */ mGmailLabels; + uint64_t mGmailMessageID; + uint64_t mGmailThreadID; + void init(); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCIMAPMessagePart.h b/MailCore.framework/Versions/A/Headers/MCIMAPMessagePart.h new file mode 100644 index 0000000..0a65284 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIMAPMessagePart.h @@ -0,0 +1,34 @@ +#ifndef MAILCORE_IMAPMESSAGEPART_H + +#define MAILCORE_IMAPMESSAGEPART_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class IMAPMessagePart : public AbstractMessagePart { + public: + IMAPMessagePart(); + virtual ~IMAPMessagePart(); + + virtual void setPartID(String * partID); + virtual String * partID(); + + public: // subclass behavior + IMAPMessagePart(IMAPMessagePart * other); + virtual Object * copy(); + virtual HashMap * serializable(); + virtual void importSerializable(HashMap * serializable); + + private: + String * mPartID; + void init(); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCIMAPMessageRenderingOperation.h b/MailCore.framework/Versions/A/Headers/MCIMAPMessageRenderingOperation.h new file mode 100644 index 0000000..81e1f26 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIMAPMessageRenderingOperation.h @@ -0,0 +1,48 @@ +// +// MCIMAPMessageRenderingOperation.h +// mailcore2 +// +// Created by Paul Young on 27/06/2013. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCIMAPMessageRenderingOperation_H + +#define MAILCORE_MCIMAPMessageRenderingOperation_H + +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class IMAPMessageRenderingOperation : public IMAPOperation { + public: + IMAPMessageRenderingOperation(); + virtual ~IMAPMessageRenderingOperation(); + + virtual void setRenderingType(IMAPMessageRenderingType type); + virtual IMAPMessageRenderingType renderingType(); + + virtual void setMessage(IMAPMessage * message); + virtual IMAPMessage * message(); + + // Result. + virtual String * result(); + + public: // subclass behavior + virtual void main(); + + private: + IMAPMessageRenderingType mRenderingType; + String * mResult; + IMAPMessage * mMessage; + + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCIMAPMultipart.h b/MailCore.framework/Versions/A/Headers/MCIMAPMultipart.h new file mode 100644 index 0000000..e420b22 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIMAPMultipart.h @@ -0,0 +1,34 @@ +#ifndef MAILCORE_MCIMAPMULTIPART_H + +#define MAILCORE_MCIMAPMULTIPART_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class IMAPMultipart : public AbstractMultipart { + public: + IMAPMultipart(); + virtual ~IMAPMultipart(); + + virtual void setPartID(String * partID); + virtual String * partID(); + + public: // subclass behavior + IMAPMultipart(IMAPMultipart * other); + virtual Object * copy(); + virtual HashMap * serializable(); + virtual void importSerializable(HashMap * serializable); + + private: + String * mPartID; + void init(); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCIMAPNamespace.h b/MailCore.framework/Versions/A/Headers/MCIMAPNamespace.h new file mode 100644 index 0000000..0c7ac6a --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIMAPNamespace.h @@ -0,0 +1,51 @@ +#ifndef MAILCORE_MCIMAPNAMESPACE_H + +#define MAILCORE_MCIMAPNAMESPACE_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class IMAPNamespaceItem; + + class IMAPNamespace : public Object { + public: + IMAPNamespace(); + virtual ~IMAPNamespace(); + + virtual String * mainPrefix(); + virtual char mainDelimiter(); + + virtual Array * /* String */ prefixes(); + + virtual String * pathForComponents(Array * components); + virtual String * pathForComponentsAndPrefix(Array * components, String * prefix); + + virtual Array * /* String */ componentsFromPath(String * path); + + virtual bool containsFolderPath(String * path); + + static IMAPNamespace * namespaceWithPrefix(String * prefix, char delimiter); + + public: // subclass behavior + IMAPNamespace(IMAPNamespace * other); + virtual String * description(); + virtual Object * copy(); + + private: + Array * /* String */ mItems; + void init(); + IMAPNamespaceItem * mainItem(); + IMAPNamespaceItem * itemForPath(String * path); + + public: // private + virtual void importIMAPNamespace(struct mailimap_namespace_item * item); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCIMAPNamespaceItem.h b/MailCore.framework/Versions/A/Headers/MCIMAPNamespaceItem.h new file mode 100644 index 0000000..a78d691 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIMAPNamespaceItem.h @@ -0,0 +1,46 @@ +#ifndef MAILCORE_MCIMAPNAMESPACEITEM_H + +#define MAILCORE_MCIMAPNAMESPACEITEM_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class IMAPNamespaceItem : public Object { + public: + IMAPNamespaceItem(); + virtual ~IMAPNamespaceItem(); + + virtual void setPrefix(String * prefix); + virtual String * prefix(); + + virtual void setDelimiter(char delimiter); + virtual char delimiter(); + + virtual String * pathForComponents(Array * components); + virtual Array * /* String */ componentsForPath(String * path); + + virtual bool containsFolder(String * folder); + + public: // subclass behavior + IMAPNamespaceItem(IMAPNamespaceItem * other); + virtual String * description(); + virtual Object * copy(); + + private: + char mDelimiter; + String * mPrefix; + void init(); + + public: // private + virtual void importIMAPNamespaceInfo(struct mailimap_namespace_info * info); + + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCIMAPNoopOperation.h b/MailCore.framework/Versions/A/Headers/MCIMAPNoopOperation.h new file mode 100644 index 0000000..8ff3fda --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIMAPNoopOperation.h @@ -0,0 +1,32 @@ +// +// MCIMAPNoopOperation.h +// mailcore2 +// +// Created by Robert Widmann on 9/24/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCIMAPNOOPOPERATION_H + +#define MAILCORE_MCIMAPNOOPOPERATION_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class IMAPNoopOperation : public IMAPOperation { + public: + IMAPNoopOperation(); + virtual ~IMAPNoopOperation(); + + public: // subclass behavior + virtual void main(); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCIMAPOperation.h b/MailCore.framework/Versions/A/Headers/MCIMAPOperation.h new file mode 100644 index 0000000..ed5bc56 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIMAPOperation.h @@ -0,0 +1,73 @@ +// +// MCIMAPOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/12/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCIMAPOPERATION_H + +#define MAILCORE_MCIMAPOPERATION_H + +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class IMAPAsyncConnection; + class IMAPAsyncSession; + class IMAPOperationCallback; + + class IMAPOperation : public Operation, public IMAPProgressCallback { + public: + IMAPOperation(); + virtual ~IMAPOperation(); + + virtual void setMainSession(IMAPAsyncSession * session); + virtual IMAPAsyncSession * mainSession(); + + virtual void setSession(IMAPAsyncConnection * session); + virtual IMAPAsyncConnection * session(); + + virtual void setFolder(String * folder); + virtual String * folder(); + + virtual void setUrgent(bool urgent); + virtual bool isUrgent(); + + virtual void setImapCallback(IMAPOperationCallback * callback); + virtual IMAPOperationCallback * imapCallback(); + + virtual void beforeMain(); + virtual void afterMain(); + + virtual void start(); + + // Result. + virtual void setError(ErrorCode error); + virtual ErrorCode error(); + + private: + IMAPAsyncSession * mMainSession; + IMAPAsyncConnection * mSession; + String * mFolder; + IMAPOperationCallback * mImapCallback; + ErrorCode mError; + bool mUrgent; + + private: + virtual void bodyProgress(IMAPSession * session, unsigned int current, unsigned int maximum); + virtual void bodyProgressOnMainThread(void * context); + virtual void itemsProgress(IMAPSession * session, unsigned int current, unsigned int maximum); + virtual void itemsProgressOnMainThread(void * context); + + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCIMAPOperationCallback.h b/MailCore.framework/Versions/A/Headers/MCIMAPOperationCallback.h new file mode 100644 index 0000000..cae7ef9 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIMAPOperationCallback.h @@ -0,0 +1,29 @@ +// +// MCIMAPOperationCallback.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/12/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCIMAPOPERATIONCALLBACK_H + +#define MAILCORE_MCIMAPOPERATIONCALLBACK_H + +#ifdef __cplusplus + +namespace mailcore { + + class IMAPOperation; + + class IMAPOperationCallback { + public: + virtual void bodyProgress(IMAPOperation * session, unsigned int current, unsigned int maximum) {}; + virtual void itemProgress(IMAPOperation * session, unsigned int current, unsigned int maximum) {}; + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCIMAPPart.h b/MailCore.framework/Versions/A/Headers/MCIMAPPart.h new file mode 100644 index 0000000..f04bb90 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIMAPPart.h @@ -0,0 +1,66 @@ +#ifndef MAILCORE_MCIMAPPART_H + +#define MAILCORE_MCIMAPPART_H + +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class IMAPMessagePart; + class IMAPMultipart; + + class IMAPPart : public AbstractPart { + public: + IMAPPart(); + virtual ~IMAPPart(); + + virtual void setPartID(String * partID); + virtual String * partID(); + + virtual void setSize(unsigned int size); + virtual unsigned int size(); + + virtual unsigned int decodedSize(); + + virtual void setEncoding(Encoding encoding); + virtual Encoding encoding(); + + public: // subclass behavior + IMAPPart(IMAPPart * other); + virtual Object * copy(); + virtual HashMap * serializable(); + virtual void importSerializable(HashMap * serializable); + + public: // private + static AbstractPart * attachmentWithIMAPBody(struct mailimap_body * body); + + virtual void importIMAPFields(struct mailimap_body_fields * fields, + struct mailimap_body_ext_1part * extension); + + private: + String * mPartID; + Encoding mEncoding; + unsigned int mSize; + void init(); + static AbstractPart * attachmentWithIMAPBodyInternal(struct mailimap_body * body, String * partID); + static AbstractPart * attachmentWithIMAPBody1Part(struct mailimap_body_type_1part * body_1part, + String * partID); + static IMAPMessagePart * attachmentWithIMAPBody1PartMessage(struct mailimap_body_type_msg * message, + struct mailimap_body_ext_1part * extension, + String * partID); + static IMAPPart * attachmentWithIMAPBody1PartBasic(struct mailimap_body_type_basic * basic, + struct mailimap_body_ext_1part * extension); + static IMAPPart * attachmentWithIMAPBody1PartText(struct mailimap_body_type_text * text, + struct mailimap_body_ext_1part * extension); + static IMAPMultipart * attachmentWithIMAPBodyMultipart(struct mailimap_body_type_mpart * body_mpart, + String * partID); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCIMAPProgressCallback.h b/MailCore.framework/Versions/A/Headers/MCIMAPProgressCallback.h new file mode 100644 index 0000000..2df4815 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIMAPProgressCallback.h @@ -0,0 +1,21 @@ +#ifndef MAILCORE_MCIMAPPROGRESSCALLBACK_H + +#define MAILCORE_MCIMAPPROGRESSCALLBACK_H + +#ifdef __cplusplus + +namespace mailcore { + + class IMAPSession; + + class IMAPProgressCallback { + public: + virtual void bodyProgress(IMAPSession * session, unsigned int current, unsigned int maximum) {}; + virtual void itemsProgress(IMAPSession * session, unsigned int current, unsigned int maximum) {}; + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCIMAPQuotaOperation.h b/MailCore.framework/Versions/A/Headers/MCIMAPQuotaOperation.h new file mode 100644 index 0000000..bff3095 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIMAPQuotaOperation.h @@ -0,0 +1,40 @@ +// +// MCIMAPQuotaOperation.h +// mailcore2 +// +// Created by Petro Korenev on 8/2/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCIMAPQuotaOperation_H + +#define MAILCORE_MCIMAPQuotaOperation_H + +#include "MCIMAPOperation.h" + +#ifdef __cplusplus + +namespace mailcore { + + class IMAPQuotaOperation : public IMAPOperation { + public: + IMAPQuotaOperation(); + virtual ~IMAPQuotaOperation(); + + // Result. + virtual uint32_t limit(); + virtual uint32_t usage(); + + public: // subclass behavior + virtual void main(); + + private: + uint32_t mLimit; + uint32_t mUsage; + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCIMAPSearchExpression.h b/MailCore.framework/Versions/A/Headers/MCIMAPSearchExpression.h new file mode 100644 index 0000000..a6e4833 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIMAPSearchExpression.h @@ -0,0 +1,85 @@ +#ifndef MAILCORE_MCIMAPSEARCHEXPRESSION_H + +#define MAILCORE_MCIMAPSEARCHEXPRESSION_H + +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class IMAPSearchExpression : public Object { + public: + IMAPSearchExpression(); + virtual ~IMAPSearchExpression(); + + virtual IMAPSearchKind kind(); + virtual String * header(); + virtual String * value(); + virtual uint64_t longNumber(); + virtual time_t date(); + virtual IndexSet * uids(); + + + virtual IMAPSearchExpression * leftExpression(); + virtual IMAPSearchExpression * rightExpression(); + + static IMAPSearchExpression * searchAll(); + static IMAPSearchExpression * searchFrom(String * value); + static IMAPSearchExpression * searchTo(String *value); + static IMAPSearchExpression * searchCc(String *value); + static IMAPSearchExpression * searchBcc(String *value); + static IMAPSearchExpression * searchRecipient(String * value); + static IMAPSearchExpression * searchSubject(String * value); + static IMAPSearchExpression * searchContent(String * value); + static IMAPSearchExpression * searchBody(String * value); + static IMAPSearchExpression * searchHeader(String * header, String * value); + static IMAPSearchExpression * searchUIDs(IndexSet * uids); + static IMAPSearchExpression * searchRead(); + static IMAPSearchExpression * searchUnread(); + static IMAPSearchExpression * searchFlagged(); + static IMAPSearchExpression * searchUnflagged(); + static IMAPSearchExpression * searchAnswered(); + static IMAPSearchExpression * searchUnanswered(); + static IMAPSearchExpression * searchDraft(); + static IMAPSearchExpression * searchUndraft(); + static IMAPSearchExpression * searchDeleted(); + static IMAPSearchExpression * searchSpam(); + static IMAPSearchExpression * searchBeforeDate(time_t date); + static IMAPSearchExpression * searchOnDate(time_t date); + static IMAPSearchExpression * searchSinceDate(time_t date); + static IMAPSearchExpression * searchBeforeReceivedDate(time_t date); + static IMAPSearchExpression * searchOnReceivedDate(time_t date); + static IMAPSearchExpression * searchSinceReceivedDate(time_t date); + static IMAPSearchExpression * searchSizeLarger(uint32_t size); + static IMAPSearchExpression * searchSizeSmaller(uint32_t size); + static IMAPSearchExpression * searchGmailThreadID(uint64_t number); + static IMAPSearchExpression * searchGmailMessageID(uint64_t number); + static IMAPSearchExpression * searchGmailRaw(String * expr); + static IMAPSearchExpression * searchAnd(IMAPSearchExpression * left, IMAPSearchExpression * right); + static IMAPSearchExpression * searchOr(IMAPSearchExpression * left, IMAPSearchExpression * right); + static IMAPSearchExpression * searchNot(IMAPSearchExpression * notExpr); + + + public: // subclass behavior + IMAPSearchExpression(IMAPSearchExpression * other); + virtual String * description(); + virtual Object * copy(); + + private: + IMAPSearchKind mKind; + String * mHeader; + String * mValue; + uint64_t mLongNumber; + IndexSet * mUids; + IMAPSearchExpression * mLeftExpression; + IMAPSearchExpression * mRightExpression; + void init(); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCIMAPSearchOperation.h b/MailCore.framework/Versions/A/Headers/MCIMAPSearchOperation.h new file mode 100644 index 0000000..60355ca --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIMAPSearchOperation.h @@ -0,0 +1,54 @@ +// +// IMAPSearchOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/12/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCIMAPSEARCHOPERATION_H + +#define MAILCORE_MCIMAPSEARCHOPERATION_H + +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class IMAPSearchExpression; + + class IMAPSearchOperation : public IMAPOperation { + public: + IMAPSearchOperation(); + virtual ~IMAPSearchOperation(); + + virtual void setSearchKind(IMAPSearchKind kind); + virtual IMAPSearchKind searchKind(); + + virtual void setSearchString(String * searchString); + virtual String * searchString(); + + virtual void setSearchExpression(IMAPSearchExpression * expression); + virtual IMAPSearchExpression * searchExpression(); + + // Result. + virtual IndexSet * uids(); + + public: // subclass behavior + virtual void main(); + + private: + IMAPSearchKind mKind; + String * mSearchString; + IMAPSearchExpression * mExpression; + IndexSet * mUids; + + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCIMAPSession.h b/MailCore.framework/Versions/A/Headers/MCIMAPSession.h new file mode 100755 index 0000000..6426fce --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIMAPSession.h @@ -0,0 +1,279 @@ +#ifndef MAILCORE_MCIMAPSESSION_H + +#define MAILCORE_MCIMAPSESSION_H + +#include +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + extern String * IMAPNamespacePersonal; + extern String * IMAPNamespaceOther; + extern String * IMAPNamespaceShared; + + class IMAPNamespace; + class IMAPSearchExpression; + class IMAPFolder; + class IMAPProgressCallback; + class IMAPSyncResult; + class IMAPFolderStatus; + class IMAPIdentity; + + class IMAPSession : public Object { + public: + IMAPSession(); + virtual ~IMAPSession(); + + virtual void setHostname(String * hostname); + virtual String * hostname(); + + virtual void setPort(unsigned int port); + virtual unsigned int port(); + + virtual void setUsername(String * username); + virtual String * username(); + + virtual void setPassword(String * password); + virtual String * password(); + + // To authenticate using OAuth2, username and oauth2token should be set. + // auth type to use is AuthTypeOAuth2. + virtual void setOAuth2Token(String * token); + virtual String * OAuth2Token(); + + virtual void setAuthType(AuthType authType); + virtual AuthType authType(); + + virtual void setConnectionType(ConnectionType connectionType); + virtual ConnectionType connectionType(); + + virtual void setTimeout(time_t timeout); + virtual time_t timeout(); + + virtual void setCheckCertificateEnabled(bool enabled); + virtual bool isCheckCertificateEnabled(); + + virtual void setVoIPEnabled(bool enabled); + virtual bool isVoIPEnabled(); + + // Needed for fetchSubscribedFolders() and fetchAllFolders(). + virtual void setDefaultNamespace(IMAPNamespace * ns); + virtual IMAPNamespace * defaultNamespace(); + + virtual IMAPIdentity * serverIdentity(); + virtual IMAPIdentity * clientIdentity(); + + virtual void select(String * folder, ErrorCode * pError); + virtual IMAPFolderStatus * folderStatus(String * folder, ErrorCode * pError); + + virtual Array * /* IMAPFolder */ fetchSubscribedFolders(ErrorCode * pError); + virtual Array * /* IMAPFolder */ fetchAllFolders(ErrorCode * pError); // will use xlist if available + + virtual void renameFolder(String * folder, String * otherName, ErrorCode * pError); + virtual void deleteFolder(String * folder, ErrorCode * pError); + virtual void createFolder(String * folder, ErrorCode * pError); + + virtual void subscribeFolder(String * folder, ErrorCode * pError); + virtual void unsubscribeFolder(String * folder, ErrorCode * pError); + + virtual void appendMessage(String * folder, Data * messageData, MessageFlag flags, + IMAPProgressCallback * progressCallback, uint32_t * createdUID, ErrorCode * pError); + virtual void appendMessageWithCustomFlags(String * folder, Data * messageData, MessageFlag flags, Array * customFlags, + IMAPProgressCallback * progressCallback, uint32_t * createdUID, ErrorCode * pError); + virtual void appendMessageWithCustomFlagsAndDate(String * folder, Data * messageData, MessageFlag flags, Array * customFlags, time_t date, + IMAPProgressCallback * progressCallback, uint32_t * createdUID, ErrorCode * pError); + + void copyMessages(String * folder, IndexSet * uidSet, String * destFolder, + HashMap ** pUidMapping, ErrorCode * pError); + + virtual void expunge(String * folder, ErrorCode * pError); + + virtual Array * /* IMAPMessage */ fetchMessagesByUID(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * uids, IMAPProgressCallback * progressCallback, + ErrorCode * pError); + virtual Array * /* IMAPMessage */ fetchMessagesByUIDWithExtraHeaders(String * folder, + IMAPMessagesRequestKind requestKind, + IndexSet * uids, + IMAPProgressCallback * progressCallback, + Array * extraHeaders, ErrorCode * pError); + virtual Array * /* IMAPMessage */ fetchMessagesByNumber(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * numbers, IMAPProgressCallback * progressCallback, + ErrorCode * pError); + virtual Array * /* IMAPMessage */ fetchMessagesByNumberWithExtraHeaders(String * folder, + IMAPMessagesRequestKind requestKind, + IndexSet * numbers, + IMAPProgressCallback * progressCallback, + Array * extraHeaders, ErrorCode * pError); + + virtual Data * fetchMessageByUID(String * folder, uint32_t uid, + IMAPProgressCallback * progressCallback, ErrorCode * pError); + virtual Data * fetchMessageAttachmentByUID(String * folder, uint32_t uid, String * partID, + Encoding encoding, IMAPProgressCallback * progressCallback, ErrorCode * pError); + virtual HashMap * fetchMessageNumberUIDMapping(String * folder, uint32_t fromUID, uint32_t toUID, + ErrorCode * pError); + + /* When CONDSTORE or QRESYNC is available */ + virtual IMAPSyncResult * syncMessagesByUID(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * uids, uint64_t modseq, + IMAPProgressCallback * progressCallback, ErrorCode * pError); + /* Same as syncMessagesByUID, allows for extra headers */ + virtual IMAPSyncResult * syncMessagesByUIDWithExtraHeaders(String * folder, IMAPMessagesRequestKind requestKind, + IndexSet * uids, uint64_t modseq, + IMAPProgressCallback * progressCallback, + Array * extraHeaders, ErrorCode * pError); + + virtual void storeFlags(String * folder, IndexSet * uids, IMAPStoreFlagsRequestKind kind, MessageFlag flags, ErrorCode * pError); + virtual void storeFlagsAndCustomFlags(String * folder, IndexSet * uids, IMAPStoreFlagsRequestKind kind, MessageFlag flags, Array * customFlags, ErrorCode * pError); + virtual void storeLabels(String * folder, IndexSet * uids, IMAPStoreFlagsRequestKind kind, Array * labels, ErrorCode * pError); + + virtual IndexSet * search(String * folder, IMAPSearchKind kind, String * searchString, ErrorCode * pError); + virtual IndexSet * search(String * folder, IMAPSearchExpression * expression, ErrorCode * pError); + virtual void getQuota(uint32_t *usage, uint32_t *limit, ErrorCode * pError); + + virtual bool setupIdle(); + virtual void idle(String * folder, uint32_t lastKnownUID, ErrorCode * pError); + virtual void interruptIdle(); + virtual void unsetupIdle(); + + virtual void connect(ErrorCode * pError); + virtual void disconnect(); + + virtual void noop(ErrorCode * pError); + + virtual HashMap * fetchNamespace(ErrorCode * pError); + + virtual void login(ErrorCode * pError); + + IMAPIdentity * identity(IMAPIdentity * clientIdentity, ErrorCode * pError); + + virtual IndexSet * capability(ErrorCode * pError); + + virtual void enableCompression(ErrorCode * pError); + + virtual uint32_t uidValidity(); + virtual uint32_t uidNext(); + virtual uint64_t modSequenceValue(); + virtual unsigned int lastFolderMessageCount(); + virtual uint32_t firstUnseenUid(); + + virtual bool isIdleEnabled(); + virtual bool isXListEnabled(); + virtual bool isCondstoreEnabled(); + virtual bool isQResyncEnabled(); + virtual bool isIdentityEnabled(); + virtual bool isXOAuthEnabled(); + virtual bool isNamespaceEnabled(); + virtual bool isCompressionEnabled(); + virtual bool allowsNewPermanentFlags(); + + virtual String * gmailUserDisplayName(); + + virtual void setConnectionLogger(ConnectionLogger * logger); + virtual ConnectionLogger * connectionLogger(); + + /** HTML rendering of the body of the message to be displayed in a web view.*/ + virtual String * htmlRendering(IMAPMessage * message, String * folder, ErrorCode * pError); + + /** HTML rendering of the body of the message.*/ + virtual String * htmlBodyRendering(IMAPMessage * message, String * folder, ErrorCode * pError); + + /** Text rendering of the message.*/ + virtual String * plainTextRendering(IMAPMessage * message, String * folder, ErrorCode * pError); + + /** Text rendering of the body of the message. All end of line will be removed and white spaces cleaned up if requested. + This method can be used to generate the summary of the message.*/ + virtual String * plainTextBodyRendering(IMAPMessage * message, String * folder, bool stripWhitespace, ErrorCode * pError); + + /** Enable automatic query of the capabilities of the IMAP server when set to true. */ + virtual void setAutomaticConfigurationEnabled(bool enabled); + + /** Check if the automatic query of the capabilities of the IMAP server is enabled. */ + virtual bool isAutomaticConfigurationEnabled(); + + public: // private + virtual void loginIfNeeded(ErrorCode * pError); + virtual void connectIfNeeded(ErrorCode * pError); + virtual void selectIfNeeded(String * folder, ErrorCode * pError); + virtual bool isDisconnected(); + virtual bool isAutomaticConfigurationDone(); + virtual void resetAutomaticConfigurationDone(); + virtual void applyCapabilities(IndexSet * capabilities); + + private: + String * mHostname; + unsigned int mPort; + String * mUsername; + String * mPassword; + String * mOAuth2Token; + AuthType mAuthType; + ConnectionType mConnectionType; + bool mCheckCertificateEnabled; + bool mVoIPEnabled; + char mDelimiter; + IMAPNamespace * mDefaultNamespace; + IMAPIdentity * mServerIdentity; + IMAPIdentity * mClientIdentity; + time_t mTimeout; + + bool mBodyProgressEnabled; + bool mIdleEnabled; + bool mXListEnabled; + bool mCondstoreEnabled; + bool mQResyncEnabled; + bool mIdentityEnabled; + bool mXOauth2Enabled; + bool mNamespaceEnabled; + bool mCompressionEnabled; + bool mIsGmail; + bool mAllowsNewPermanentFlags; + String * mWelcomeString; + bool mNeedsMboxMailWorkaround; + uint32_t mUIDValidity; + uint32_t mUIDNext; + uint64_t mModSequenceValue; + unsigned int mFolderMsgCount; + uint32_t mFirstUnseenUid; + bool mYahooServer; + + unsigned int mLastFetchedSequenceNumber; + String * mCurrentFolder; + pthread_mutex_t mIdleLock; + bool mCanIdle; + int mState; + mailimap * mImap; + IMAPProgressCallback * mProgressCallback; + unsigned int mProgressItemsCount; + ConnectionLogger * mConnectionLogger; + bool mAutomaticConfigurationEnabled; + bool mAutomaticConfigurationDone; + bool mShouldDisconnect; + + String * mLoginResponse; + String * mGmailUserDisplayName; + + void init(); + void bodyProgress(unsigned int current, unsigned int maximum); + void itemsProgress(unsigned int current, unsigned int maximum); + bool checkCertificate(); + static void body_progress(size_t current, size_t maximum, void * context); + static void items_progress(size_t current, size_t maximum, void * context); + void setup(); + void unsetup(); + char fetchDelimiterIfNeeded(char defaultDelimiter, ErrorCode * pError); + IMAPSyncResult * fetchMessages(String * folder, IMAPMessagesRequestKind requestKind, + bool fetchByUID, struct mailimap_set * imapset, uint64_t modseq, + HashMap * mapping, uint32_t startUid, IMAPProgressCallback * progressCallback, + Array * extraHeaders, ErrorCode * pError); + void capabilitySetWithSessionState(IndexSet * capabilities); + bool enableFeature(String * feature); + void enableFeatures(); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCIMAPSyncResult.h b/MailCore.framework/Versions/A/Headers/MCIMAPSyncResult.h new file mode 100644 index 0000000..ad1b16a --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIMAPSyncResult.h @@ -0,0 +1,39 @@ +// +// MCIMAPSyncResult.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/3/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCIMAPSYNCRESULT_H + +#define MAILCORE_MCIMAPSYNCRESULT_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class IMAPSyncResult : public Object { + public: + IMAPSyncResult(); + virtual ~IMAPSyncResult(); + + virtual void setModifiedOrAddedMessages(Array * /* IMAPMessage */ messages); + virtual Array * /* IMAPMessage */ modifiedOrAddedMessages(); + + virtual void setVanishedMessages(IndexSet * vanishedMessages); + virtual IndexSet * vanishedMessages(); + + private: + Array * /* IMAPMessage */ mModifiedOrAddedMessages; + IndexSet * mVanishedMessages; + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCIndexSet.h b/MailCore.framework/Versions/A/Headers/MCIndexSet.h new file mode 100644 index 0000000..525cdda --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIndexSet.h @@ -0,0 +1,75 @@ +// +// MCIndexSet.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/4/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCINDEXSET_H + +#define MAILCORE_MCINDEXSET_H + +#include +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class IndexSet : public Object { + public: + IndexSet(); + IndexSet(IndexSet * o); + + static IndexSet * indexSet(); + static IndexSet * indexSetWithRange(Range range); + static IndexSet * indexSetWithIndex(uint64_t idx); + + virtual unsigned int count(); + virtual void addIndex(uint64_t idx); + virtual void removeIndex(uint64_t idx); + virtual bool containsIndex(uint64_t idx); + + virtual void addRange(Range range); + virtual void removeRange(Range range); + virtual void intersectsRange(Range range); + + virtual void addIndexSet(IndexSet * indexSet); + virtual void removeIndexSet(IndexSet * indexSet); + virtual void intersectsIndexSet(IndexSet * indexSet); + + virtual Range * allRanges(); + virtual unsigned int rangesCount(); + virtual void removeAllIndexes(); + + public: // subclass behavior + virtual ~IndexSet(); + virtual String * description(); + virtual Object * copy(); + virtual HashMap * serializable(); + virtual void importSerializable(HashMap * serializable); + + private: + Range * mRanges; + unsigned int mCount; + unsigned int mAllocated; + void init(); + int rangeIndexForIndex(uint64_t idx); + int rangeIndexForIndexWithBounds(uint64_t idx, unsigned int left, unsigned int right); + void addRangeIndex(unsigned int rangeIndex); + void removeRangeIndex(unsigned int rangeIndex, unsigned int count); + int rightRangeIndexForIndex(uint64_t idx); + int rightRangeIndexForIndexWithBounds(uint64_t idx, unsigned int left, unsigned int right); + int leftRangeIndexForIndex(uint64_t idx); + int leftRangeIndexForIndexWithBounds(uint64_t idx, unsigned int left, unsigned int right); + void mergeRanges(unsigned int rangeIndex); + void tryToMergeAdjacentRanges(unsigned int rangeIndex); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCIterator.h b/MailCore.framework/Versions/A/Headers/MCIterator.h new file mode 100644 index 0000000..c8b23fa --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCIterator.h @@ -0,0 +1,186 @@ +// +// MCIterator.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 4/18/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_ITERATOR_H + +#define MAILCORE_ITERATOR_H + +#include +#include +#include +#include +#include + +#ifdef __cplusplus + +#define mc_foreacharray(type, __variable, __array) \ +type * __variable; \ +mailcore::ArrayIterator __variable##__iterator = mailcore::ArrayIteratorInit(__array); \ +for (; NULL != (__variable = (type *) mailcore::ArrayIteratorNext(&__variable##__iterator)); ) + +#define mc_foreacharrayIndex(__index, type, __variable, __array) \ +type * __variable; \ +mailcore::ArrayIterator __variable##__iterator = mailcore::ArrayIteratorInit(__array); \ +for (unsigned int __index = 0; NULL != (__variable = (type *) mailcore::ArrayIteratorNext(&__variable##__iterator)); __index++) + +#define mc_foreachhashmapKey(keyType, __key, __hashmap) \ +keyType * __key; \ +HashMapIterator __key##__iterator = HashMapIteratorInit(__hashmap, true, false); \ +while (HashMapIteratorRun(&__key##__iterator)) \ +while (HashMapIteratorNext(&__key##__iterator, &__key, NULL)) + +#define mc_foreachhashmapValue(valueType, __value, __hashmap) \ +valueType * __value; \ +HashMapIterator __value##__iterator = HashMapIteratorInit(__hashmap, false, true); \ +while (HashMapIteratorRun(&__value##__iterator)) \ +while (HashMapIteratorNext(&__value##__iterator, NULL, (Object **) &__value)) + +#define mc_foreachhashmapKeyAndValue(keyType, __key, valueType, __value, __hashmap) \ +keyType * __key; \ +valueType * __value; \ +HashMapIterator __key##__value##__iterator = HashMapIteratorInit(__hashmap, true, true); \ +while (HashMapIteratorRun(&__key##__value##__iterator)) \ +while (HashMapIteratorNext(&__key##__value##__iterator, (Object **) &__key, (Object **) &__value)) + +#define mc_foreachindexset(__variable, __indexset) \ +int64_t __variable; \ +mailcore::IndexSetIterator __variable##__iterator = mailcore::IndexSetIteratorInit(__indexset); \ +for (; (__variable = IndexSetIteratorValue(&__variable##__iterator)), IndexSetIteratorIsValid(&__variable##__iterator) ; mailcore::IndexSetIteratorNext(&__variable##__iterator)) + +namespace mailcore { + + struct IndexSetIterator { + unsigned int rangeIndex; + unsigned int index; + Range * currentRange; + IndexSet * indexSet; + }; + + static inline IndexSetIterator IndexSetIteratorInit(IndexSet * indexSet) + { + IndexSetIterator iterator = { 0, 0, NULL, indexSet }; + if (indexSet->rangesCount() >= 1) { + iterator.currentRange = &indexSet->allRanges()[0]; + } + return iterator; + } + + static inline bool IndexSetIteratorIsValid(IndexSetIterator * iterator) + { + return iterator->currentRange != NULL; + } + + static inline int64_t IndexSetIteratorValue(IndexSetIterator * iterator) + { + return iterator->currentRange == NULL ? -1 : iterator->currentRange->location + iterator->index; + } + + static inline bool IndexSetIteratorNext(IndexSetIterator * iterator) + { + iterator->index ++; + if (iterator->index > iterator->currentRange->length) { + // switch to an other range + iterator->index = 0; + iterator->rangeIndex ++; + if (iterator->rangeIndex >= iterator->indexSet->rangesCount()) { + iterator->currentRange = NULL; + return false; + } + else { + iterator->currentRange = &iterator->indexSet->allRanges()[iterator->rangeIndex]; + return true; + } + } + else { + return true; + } + } + + struct ArrayIterator { + unsigned index; + unsigned count; + Array * array; + }; + + static inline ArrayIterator ArrayIteratorInit(Array * array) + { + ArrayIterator iterator = { 0, array != NULL ? array->count() : 0, array }; + return iterator; + } + + static inline Object * ArrayIteratorNext(ArrayIterator * iterator) + { + if (iterator->index >= iterator->count) { + return NULL; + } + + Object * result = iterator->array->objectAtIndex(iterator->index); + ++ iterator->index; + return result; + } + + + struct HashMapIterator { + bool cleanup; + unsigned index; + unsigned count; + Array * keys; + Array * values; + }; + + static inline HashMapIterator HashMapIteratorInit(HashMap * hashmap, bool useKeys, bool useValues) + { + AutoreleasePool * pool = new AutoreleasePool(); + Array * keys = useKeys ? (hashmap != NULL ? hashmap->allKeys() : NULL) : NULL; + Array * values = useValues ? (hashmap != NULL ? hashmap->allValues() : NULL) : NULL; + if (keys != NULL) { + keys->retain(); + } + if (values != NULL) { + values->retain(); + } + HashMapIterator iterator = { false, 0, hashmap != NULL ? hashmap->count() : 0, keys, values }; + pool->release(); + + return iterator; + } + + static inline bool HashMapIteratorNext(HashMapIterator * iterator, Object ** keyp, Object ** valuep) + { + if (iterator->index >= iterator->count) { + return false; + } + + if (keyp != NULL) { + * keyp = iterator->keys->objectAtIndex(iterator->index); + } + if (valuep != NULL) { + * valuep = iterator->values->objectAtIndex(iterator->index); + } + iterator->index ++; + return true; + } + + + static inline bool HashMapIteratorRun(HashMapIterator * iterator) + { + if (!iterator->cleanup) { + iterator->cleanup = true; + return true; + } else { + MC_SAFE_RELEASE(iterator->keys); + MC_SAFE_RELEASE(iterator->values); + return false; + } + } + +}; + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCJSON.h b/MailCore.framework/Versions/A/Headers/MCJSON.h new file mode 100644 index 0000000..d10f7d7 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCJSON.h @@ -0,0 +1,38 @@ +// +// MCJSON.h +// hermes +// +// Created by DINH Viêt Hoà on 4/8/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCJSON_H + +#define MAILCORE_MCJSON_H + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class Null; + + class JSON { + public: + static String * objectToJSONString(Object * object); + static Data * objectToJSONData(Object * object); + static Object * objectFromJSONString(String * json); + static Object * objectFromJSONData(Data * json); + }; + +} + +#endif + +#endif /* defined(__hermes__MCJSON__) */ diff --git a/MailCore.framework/Versions/A/Headers/MCLibetpanTypes.h b/MailCore.framework/Versions/A/Headers/MCLibetpanTypes.h new file mode 100644 index 0000000..fcb8e70 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCLibetpanTypes.h @@ -0,0 +1,46 @@ +// +// MCLibetpanTypes.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 4/7/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCLIBETPANTYPES_H + +#define MAILCORE_MCLIBETPANTYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + struct mailimap_body_fields; + struct mailimap_body_ext_1part; + struct mailimf_address; + struct mailimf_mailbox; + struct mailimap_address; + struct mailmime; + struct mailmime_mechanism; + struct mailimap_namespace_item; + struct mailimap_namespace_info; + struct mailimap_body; + struct mailimap_body_fields; + struct mailimap_body_ext_1part; + struct mailimap_body_type_1part; + struct mailimap_body_type_basic; + struct mailimap_body_type_text; + struct mailimap_body_type_mpart; + struct mailimap_body_type_msg; + typedef struct mailimap mailimap; + struct mailimap_set; + struct mailimap_date_time; + struct mailimf_fields; + struct mailimap_envelope; + typedef struct mailpop3 mailpop3; + typedef struct mailsmtp mailsmtp; + typedef struct newsnntp newsnntp; + struct mailsem; +#ifdef __cplusplus +} +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCLog.h b/MailCore.framework/Versions/A/Headers/MCLog.h new file mode 100644 index 0000000..95e227e --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCLog.h @@ -0,0 +1,28 @@ +#ifndef MAILCORE_MCLOG_H + +#define MAILCORE_MCLOG_H + +#include + +#define MCLog(...) MCLogInternal(NULL, __FILE__, __LINE__, 0, __VA_ARGS__) +#define MCLogStack(...) MCLogInternal(NULL, __FILE__, __LINE__, 1, __VA_ARGS__) + +extern int MCLogEnabled; + +#ifndef __printflike +#define __printflike(a,b) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void MCLogInternal(const char * user, + const char * filename, + unsigned int line, + int dumpStack, + const char * format, ...) __printflike(5, 6); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCMD5.h b/MailCore.framework/Versions/A/Headers/MCMD5.h new file mode 100644 index 0000000..a752231 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCMD5.h @@ -0,0 +1,25 @@ +// +// MCMD5.h +// hermes +// +// Created by DINH Viêt Hoà on 4/11/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCMD5_H + +#define MAILCORE_MCMD5_H + +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + Data * md5Data(Data * data); + String * md5String(Data * data); +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCMailProvider.h b/MailCore.framework/Versions/A/Headers/MCMailProvider.h new file mode 100644 index 0000000..bb46bc7 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCMailProvider.h @@ -0,0 +1,75 @@ +// +// MCMailProvider.h +// mailcore2 +// +// Created by Robert Widmann on 4/28/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCMAILPROVIDER_H + +#define MAILCORE_MCMAILPROVIDER_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class NetService; + + class MailProvider : public Object { + public: + static MailProvider * providerWithInfo(HashMap * info); + + MailProvider(); + virtual ~MailProvider(); + + virtual String * identifier(); + + virtual Array * /* NetService */ imapServices(); + virtual Array * /* NetService */ smtpServices(); + virtual Array * /* NetService */ popServices(); + + virtual bool matchEmail(String * email); + virtual bool matchMX(String * hostname); + + virtual String * sentMailFolderPath(); + virtual String * starredFolderPath(); + virtual String * allMailFolderPath(); + virtual String * trashFolderPath(); + virtual String * draftsFolderPath(); + virtual String * spamFolderPath(); + virtual String * importantFolderPath(); + + // Returns true if one of the folders above matches the given one. + virtual bool isMainFolder(String * folderPath, String * prefix); + + public: // subclass behavior + MailProvider(MailProvider * other); + virtual String * description(); + virtual Object * copy(); + + public: // private + virtual void setIdentifier(String * identifier); + virtual void fillWithInfo(HashMap * info); + + private: + String * mIdentifier; + Array * /* String */ mDomainMatch; + Array * /* String */ mDomainExclude; + Array * /* String */ mMxMatch; + Array * /* NetService */ mImapServices; + Array * /* NetService */ mSmtpServices; + Array * /* NetService */ mPopServices; + HashMap * mMailboxPaths; + + virtual bool matchDomain(String * match, String * domain); + void init(); + }; + +}; + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCMailProvidersManager.h b/MailCore.framework/Versions/A/Headers/MCMailProvidersManager.h new file mode 100644 index 0000000..8babaae --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCMailProvidersManager.h @@ -0,0 +1,43 @@ +// +// MCMailProvidersManager.h +// mailcore2 +// +// Created by Robert Widmann on 4/28/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCMAILPROVIDERSMANAGER_H + +#define MAILCORE_MCMAILPROVIDERSMANAGER_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class MailProvider; + + class MailProvidersManager : public Object { + public: + static MailProvidersManager * sharedManager(); + + virtual MailProvider * providerForEmail(String * email); + virtual MailProvider * providerForMX(String * hostname); + virtual MailProvider * providerForIdentifier(String * identifier); + + virtual void registerProvidersWithFilename(String * filename); + + private: + MailProvidersManager(); + void registerProviders(HashMap * providers); + + HashMap * mProviders; + + void init(); + }; +} + +#endif + +#endif \ No newline at end of file diff --git a/MailCore.framework/Versions/A/Headers/MCMainThread.h b/MailCore.framework/Versions/A/Headers/MCMainThread.h new file mode 100644 index 0000000..df24666 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCMainThread.h @@ -0,0 +1,20 @@ +#ifndef MAILCORE_MCMAINTHREAD_H + +#define MAILCORE_MCMAINTHREAD_H + +#ifdef __cplusplus + +namespace mailcore { + void callOnMainThread(void (*)(void *), void * context); + void callOnMainThreadAndWait(void (*)(void *), void * context); + + // Returns a "call" object. + void * callAfterDelay(void (*)(void *), void * context, double time); + + // Pass the pointer returns by callAfterDelay() to cancel a delayed call. + void cancelDelayedCall(void * call); +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCMessageBuilder.h b/MailCore.framework/Versions/A/Headers/MCMessageBuilder.h new file mode 100644 index 0000000..413d1a4 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCMessageBuilder.h @@ -0,0 +1,68 @@ +#ifndef MAILCORE_MCMESSAGEBUILDER_H + +#define MAILCORE_MCMESSAGEBUILDER_H + +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class Attachment; + class HTMLRendererTemplateCallback; + + class MessageBuilder : public AbstractMessage { + public: + MessageBuilder(); + virtual ~MessageBuilder(); + + virtual void setHTMLBody(String * htmlBody); + virtual String * htmlBody(); + + virtual void setTextBody(String * textBody); + virtual String * textBody(); + + virtual void setAttachments(Array * /* Attachment */ attachments); + virtual Array * /* Attachment */ attachments(); + virtual void addAttachment(Attachment * attachment); + + // attachments (usually images) that are included in HTML. + // a Content-ID should be assigned to these part to be able to reference + // them in the HTML using a cid: URL. + virtual void setRelatedAttachments(Array * /* Attachment */ attachments); + virtual Array * /* Attachment */ relatedAttachments(); + virtual void addRelatedAttachment(Attachment * attachment); + + // When boundary needs to be prefixed (to go through spam filters). + virtual void setBoundaryPrefix(String * boundaryPrefix); + virtual String * boundaryPrefix(); + + virtual Data * data(); + + virtual String * htmlRendering(HTMLRendererTemplateCallback * htmlCallback = NULL); + virtual String * htmlBodyRendering(); + + virtual String * plainTextRendering(); + virtual String * plainTextBodyRendering(bool stripWhitespace); + + public: // subclass behavior + MessageBuilder(MessageBuilder * other); + virtual String * description(); + virtual Object * copy(); + + private: + String * mHTMLBody; + String * mTextBody; + Array * /* Attachment */ mAttachments; + Array * /* Attachment */ mRelatedAttachments; + String * mBoundaryPrefix; + void init(); + Data * dataAndFilterBcc(bool filterBcc); + }; + +}; + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCMessageConstants.h b/MailCore.framework/Versions/A/Headers/MCMessageConstants.h new file mode 100644 index 0000000..145d991 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCMessageConstants.h @@ -0,0 +1,275 @@ +#ifndef MAILCORE_MCMESSAGECONSTANTS_H + +#define MAILCORE_MCMESSAGECONSTANTS_H + +#ifdef __cplusplus + +namespace mailcore { + + enum ConnectionType { + ConnectionTypeClear = 1 << 0, + ConnectionTypeStartTLS = 1 << 1, + ConnectionTypeTLS = 1 << 2, + }; + + enum AuthType { + AuthTypeSASLNone = 0, + AuthTypeSASLCRAMMD5 = 1 << 0, + AuthTypeSASLPlain = 1 << 1, + AuthTypeSASLGSSAPI = 1 << 2, + AuthTypeSASLDIGESTMD5 = 1 << 3, + AuthTypeSASLLogin = 1 << 4, + AuthTypeSASLSRP = 1 << 5, + AuthTypeSASLNTLM = 1 << 6, + AuthTypeSASLKerberosV4 = 1 << 7, + AuthTypeXOAuth2 = 1 << 8, + AuthTypeXOAuth2Outlook = 1 << 9, + }; + + enum IMAPFolderFlag { + IMAPFolderFlagNone = 0, + IMAPFolderFlagMarked = 1 << 0, + IMAPFolderFlagUnmarked = 1 << 1, + IMAPFolderFlagNoSelect = 1 << 2, + IMAPFolderFlagNoInferiors = 1 << 3, + IMAPFolderFlagInbox = 1 << 4, + IMAPFolderFlagSentMail = 1 << 5, + IMAPFolderFlagStarred = 1 << 6, + IMAPFolderFlagAllMail = 1 << 7, + IMAPFolderFlagTrash = 1 << 8, + IMAPFolderFlagDrafts = 1 << 9, + IMAPFolderFlagSpam = 1 << 10, + IMAPFolderFlagImportant = 1 << 11, + IMAPFolderFlagArchive = 1 << 12, + IMAPFolderFlagAll = IMAPFolderFlagAllMail, + IMAPFolderFlagJunk = IMAPFolderFlagSpam, + IMAPFolderFlagFlagged = IMAPFolderFlagStarred, + IMAPFolderFlagFolderTypeMask = IMAPFolderFlagInbox | IMAPFolderFlagSentMail | IMAPFolderFlagStarred | IMAPFolderFlagAllMail | + IMAPFolderFlagTrash| IMAPFolderFlagDrafts | IMAPFolderFlagSpam | IMAPFolderFlagImportant | IMAPFolderFlagArchive, + }; + + enum MessageFlag { + MessageFlagNone = 0, + MessageFlagSeen = 1 << 0, + MessageFlagAnswered = 1 << 1, + MessageFlagFlagged = 1 << 2, + MessageFlagDeleted = 1 << 3, + MessageFlagDraft = 1 << 4, + MessageFlagMDNSent = 1 << 5, + MessageFlagForwarded = 1 << 6, + MessageFlagSubmitPending = 1 << 7, + MessageFlagSubmitted = 1 << 8, + MessageFlagMaskAll = MessageFlagSeen | MessageFlagAnswered | MessageFlagFlagged | + MessageFlagDeleted | MessageFlagDraft | MessageFlagMDNSent | MessageFlagForwarded | + MessageFlagSubmitPending | MessageFlagSubmitted, + } ; + + enum IMAPMessagesRequestKind { + IMAPMessagesRequestKindUid = 0, // This is the default and it's always fetched + IMAPMessagesRequestKindFlags = 1 << 0, + IMAPMessagesRequestKindHeaders = 1 << 1, + IMAPMessagesRequestKindStructure = 1 << 2, + IMAPMessagesRequestKindInternalDate = 1 << 3, + IMAPMessagesRequestKindFullHeaders = 1 << 4, + IMAPMessagesRequestKindHeaderSubject = 1 << 5, + IMAPMessagesRequestKindGmailLabels = 1 << 6, + IMAPMessagesRequestKindGmailMessageID = 1 << 7, + IMAPMessagesRequestKindGmailThreadID = 1 << 8, + IMAPMessagesRequestKindExtraHeaders = 1 << 9, + IMAPMessagesRequestKindSize = 1 << 10, + }; + + enum IMAPFetchRequestType { + IMAPFetchRequestTypeUID = 0, + IMAPFetchRequestTypeSequence = 1 + }; + + enum IMAPStoreFlagsRequestKind { + IMAPStoreFlagsRequestKindAdd, + IMAPStoreFlagsRequestKindRemove, + IMAPStoreFlagsRequestKindSet, + }; + + enum IMAPWorkaround { + IMAPWorkaroundGmail = 1 << 0, + IMAPWorkaroundYahoo = 1 << 1, + IMAPWorkaroundExchange2003 = 1 << 2, + }; + + enum IMAPCapability { + IMAPCapabilityACL, + IMAPCapabilityBinary, + IMAPCapabilityCatenate, + IMAPCapabilityChildren, + IMAPCapabilityCompressDeflate, + IMAPCapabilityCondstore, + IMAPCapabilityEnable, + IMAPCapabilityIdle, + IMAPCapabilityId, + IMAPCapabilityLiteralPlus, + IMAPCapabilityMultiAppend, + IMAPCapabilityNamespace, + IMAPCapabilityQResync, + IMAPCapabilityQuota, + IMAPCapabilitySort, + IMAPCapabilityStartTLS, + IMAPCapabilityThreadOrderedSubject, + IMAPCapabilityThreadReferences, + IMAPCapabilityUIDPlus, + IMAPCapabilityUnselect, + IMAPCapabilityXList, + IMAPCapabilityAuthAnonymous, + IMAPCapabilityAuthCRAMMD5, + IMAPCapabilityAuthDigestMD5, + IMAPCapabilityAuthExternal, + IMAPCapabilityAuthGSSAPI, + IMAPCapabilityAuthKerberosV4, + IMAPCapabilityAuthLogin, + IMAPCapabilityAuthNTLM, + IMAPCapabilityAuthOTP, + IMAPCapabilityAuthPlain, + IMAPCapabilityAuthSKey, + IMAPCapabilityAuthSRP, + IMAPCapabilityXOAuth2, + IMAPCapabilityGmail, + }; + + enum POPCapability { + POPCapabilityNone, + POPCapabilityStartTLS, + POPCapabilityTop, + POPCapabilityUser, + POPCapabilityRespCodes, + POPCapabilityPipelining, + POPCapabilityUIDL, + POPCapabilitySASL, + POPCapabilityAuthAnonymous, + POPCapabilityAuthCRAMMD5, + POPCapabilityAuthDigestMD5, + POPCapabilityAuthExternal, + POPCapabilityAuthGSSAPI, + POPCapabilityAuthKerberosV4, + POPCapabilityAuthLogin, + POPCapabilityAuthNTLM, + POPCapabilityAuthOTP, + POPCapabilityAuthPlain, + POPCapabilityAuthSKey, + POPCapabilityAuthSRP, + }; + + enum Encoding { + Encoding7Bit = 0, // should match MAILIMAP_BODY_FLD_ENC_7BIT + Encoding8Bit = 1, // should match MAILIMAP_BODY_FLD_ENC_8BIT + EncodingBinary = 2, // should match MAILIMAP_BODY_FLD_ENC_BINARY + EncodingBase64 = 3, // should match MAILIMAP_BODY_FLD_ENC_BASE64 + EncodingQuotedPrintable = 4, // should match MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE + EncodingOther = 5, // should match MAILIMAP_BODY_FLD_ENC_OTHER + // negative values should be used for other encoding + EncodingUUEncode = -1 + }; + + enum IMAPSearchKind { + IMAPSearchKindAll, + IMAPSearchKindNone, + IMAPSearchKindFrom, + IMAPSearchKindTo, + IMAPSearchKindCc, + IMAPSearchKindBcc, + IMAPSearchKindRecipient, // Recipient is the combination of To, Cc and Bcc + IMAPSearchKindSubject, + IMAPSearchKindContent, + IMAPSearchKindBody, + IMAPSearchKindUIDs, + IMAPSearchKindHeader, + IMAPSearchKindRead, + IMAPSearchKindUnread, + IMAPSearchKindFlagged, + IMAPSearchKindUnflagged, + IMAPSearchKindAnswered, + IMAPSearchKindUnanswered, + IMAPSearchKindDraft, + IMAPSearchKindUndraft, + IMAPSearchKindDeleted, + IMAPSearchKindSpam, + IMAPSearchKindBeforeDate, + IMAPSearchKindOnDate, + IMAPSearchKindSinceDate, + IMAPSearchKindBeforeReceivedDate, + IMAPSearchKindOnReceivedDate, + IMAPSearchKindSinceReceivedDate, + IMAPSearchKindSizeLarger, + IMAPSearchKindSizeSmaller, + IMAPSearchKindGmailThreadID, + IMAPSearchKindGmailMessageID, + IMAPSearchKindGmailRaw, + IMAPSearchKindOr, + IMAPSearchKindAnd, + IMAPSearchKindNot, + }; + + enum ErrorCode { + ErrorNone, + ErrorConnection, + ErrorTLSNotAvailable, + ErrorParse, + ErrorCertificate, + ErrorAuthentication, + ErrorGmailIMAPNotEnabled, + ErrorGmailExceededBandwidthLimit, + ErrorGmailTooManySimultaneousConnections, + ErrorMobileMeMoved, + ErrorYahooUnavailable, + ErrorNonExistantFolder, + ErrorRename, + ErrorDelete, + ErrorCreate, + ErrorSubscribe, + ErrorAppend, + ErrorCopy, + ErrorExpunge, + ErrorFetch, + ErrorIdle, + ErrorIdentity, + ErrorNamespace, + ErrorStore, + ErrorCapability, + ErrorStartTLSNotAvailable, + ErrorSendMessageIllegalAttachment, + ErrorStorageLimit, + ErrorSendMessageNotAllowed, + ErrorNeedsConnectToWebmail, + ErrorSendMessage, + ErrorAuthenticationRequired, + ErrorFetchMessageList, + ErrorDeleteMessage, + ErrorInvalidAccount, + ErrorFile, + ErrorCompression, + ErrorNoSender, + ErrorNoRecipient, + ErrorNoop, + }; + + enum PartType { + PartTypeSingle, + PartTypeMessage, + PartTypeMultipartMixed, + PartTypeMultipartRelated, + PartTypeMultipartAlternative, + PartTypeMultipartSigned, + }; + + // Private type - It should not be used directly. + enum IMAPMessageRenderingType { + IMAPMessageRenderingTypeHTML, + IMAPMessageRenderingTypeHTMLBody, + IMAPMessageRenderingTypePlainText, + IMAPMessageRenderingTypePlainTextBody, + IMAPMessageRenderingTypePlainTextBodyAndStripWhitespace, + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCMessageHeader.h b/MailCore.framework/Versions/A/Headers/MCMessageHeader.h new file mode 100644 index 0000000..51b1e2f --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCMessageHeader.h @@ -0,0 +1,112 @@ +#ifndef MAILCORE_MCMESSAGEHEADER_H + +#define MAILCORE_MCMESSAGEHEADER_H + +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class Address; + + class MessageHeader : public Object { + public: + MessageHeader(); + virtual ~MessageHeader(); + + virtual void setMessageID(String * messageID); + virtual String * messageID(); + + virtual bool isMessageIDAutoGenerated(); + + virtual void setReferences(Array * /* String */ references); + virtual Array * /* String */ references(); + + virtual void setInReplyTo(Array * /* String */ inReplyTo); + virtual Array * /* String */ inReplyTo(); + + virtual void setDate(time_t date); + virtual time_t date(); + + virtual void setReceivedDate(time_t date); + virtual time_t receivedDate(); + + virtual void setSender(Address * sender); + virtual Address * sender(); + + virtual void setFrom(Address * from); + virtual Address * from(); + + virtual void setTo(Array * /* Address */ to); + virtual Array * /* Address */ to(); + + virtual void setCc(Array * /* Address */ cc); + virtual Array * /* Address */ cc(); + + virtual void setBcc(Array * /* Address */ bcc); + virtual Array * /* Address */ bcc(); + + virtual void setReplyTo(Array * /* Address */ replyTo); + virtual Array * /* Address */ replyTo(); + + virtual void setSubject(String * subject); + virtual String * subject(); + + virtual void setUserAgent(String * userAgent); + virtual String * userAgent(); + + virtual void setExtraHeader(String *name, String * value); + virtual void removeExtraHeader(String *name); + virtual String * extraHeaderValueForName(String *name); + virtual Array * allExtraHeadersNames(); + + String * extractedSubject(); + virtual String * partialExtractedSubject(); + virtual void importHeadersData(Data * data); + + virtual MessageHeader * replyHeader(bool replyAll, Array * addressesExcludedFromRecipient); + virtual MessageHeader * forwardHeader(); + + public: // subclass behavior + MessageHeader(MessageHeader * other); + virtual String * description(); + virtual Object * copy(); + virtual HashMap * serializable(); + virtual void importSerializable(HashMap * serializable); + + public: // private + virtual void importIMAPEnvelope(struct mailimap_envelope * env); + virtual void importIMAPReferences(Data * data); + virtual void importIMAPInternalDate(struct mailimap_date_time * date); + + virtual struct mailimf_fields * createIMFFieldsAndFilterBcc(bool filterBcc); + virtual void importIMFFields(struct mailimf_fields * fields); + + private: + String * mMessageID; + bool mMessageIDAutoGenerated; + Array * /* String */ mReferences; + Array * /* String */ mInReplyTo; + Address * mSender; + Address * mFrom; + Array * /* Address */ mTo; + Array * /* Address */ mCc; + Array * /* Address */ mBcc; + Array * /* Address */ mReplyTo; + String * mSubject; + time_t mDate; + time_t mReceivedDate; + HashMap * mExtraHeaders; + HashMap * mlcExtraHeaders; + void init(bool generateDate, bool generateMessageID); + void setExtraHeaders(HashMap *headers); + Array * recipientWithReplyAll(bool replyAll, bool includeTo, bool includeCc, Array * senderEmails); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCMessageParser.h b/MailCore.framework/Versions/A/Headers/MCMessageParser.h new file mode 100644 index 0000000..11de9b5 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCMessageParser.h @@ -0,0 +1,51 @@ +#ifndef MAILCORE_MCPARSEDMESSAGE_H + +#define MAILCORE_MCPARSEDMESSAGE_H + +#include +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class HTMLRendererTemplateCallback; + + class MessageParser : public AbstractMessage { + public: + static MessageParser * messageParserWithData(Data * data); + static MessageParser * messageParserWithContentsOfFile(String * filename); + + MessageParser(Data * data); + virtual ~MessageParser(); + + virtual AbstractPart * mainPart(); + virtual Data * data(); + + virtual String * htmlRendering(HTMLRendererTemplateCallback * htmlCallback = NULL); + virtual String * htmlBodyRendering(); + + virtual String * plainTextRendering(); + virtual String * plainTextBodyRendering(bool stripWhitespace); + + public: // subclass behavior + MessageParser(MessageParser * other); + virtual String * description(); + virtual Object * copy(); + + virtual AbstractPart * partForContentID(String * contentID); + virtual AbstractPart * partForUniqueID(String * uniqueID); + + private: + Data * mData; + AbstractPart * mMainPart; + void init(); + + }; + +}; + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCMessagePart.h b/MailCore.framework/Versions/A/Headers/MCMessagePart.h new file mode 100644 index 0000000..4b9de96 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCMessagePart.h @@ -0,0 +1,26 @@ +#ifndef MAILCORE_MCMESSAGEPART_H + +#define MAILCORE_MCMESSAGEPART_H + +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class MessagePart : public AbstractMessagePart { + public: + MessagePart(); + virtual ~MessagePart(); + + public: // subclass behavior + MessagePart(MessagePart * other); + virtual Object * copy(); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCMultipart.h b/MailCore.framework/Versions/A/Headers/MCMultipart.h new file mode 100644 index 0000000..6b00c08 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCMultipart.h @@ -0,0 +1,26 @@ +#ifndef MAILCORE_MCMULTIPART_H + +#define MAILCORE_MCMULTIPART_H + +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class Multipart : public AbstractMultipart { + public: + Multipart(); + virtual ~Multipart(); + + public: // subclass behavior + Multipart(Multipart * other); + virtual Object * copy(); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCNNTP.h b/MailCore.framework/Versions/A/Headers/MCNNTP.h new file mode 100644 index 0000000..c2da3a6 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCNNTP.h @@ -0,0 +1,9 @@ +#ifndef MAILCORE_MCNNTP_H + +#define MAILCORE_MCNNTP_H + +#include +#include +#include + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCNNTPAsyncSession.h b/MailCore.framework/Versions/A/Headers/MCNNTPAsyncSession.h new file mode 100644 index 0000000..66f0cc0 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCNNTPAsyncSession.h @@ -0,0 +1,85 @@ +#ifndef MAILCORE_MCNNTPASYNCSESSION_H + +#define MAILCORE_MCNNTPASYNCSESSION_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class NNTPOperation; + class NNTPSession; + class NNTPFetchHeaderOperation; + class NNTPFetchArticleOperation; + class MCNNTPFetchArticlesOperation; + class NNTPListNewsgroupsOperation; + class NNTPOperationQueueCallback; + class NNTPConnectionLogger; + + class NNTPAsyncSession : public Object { + public: + NNTPAsyncSession(); + virtual ~NNTPAsyncSession(); + + virtual void setHostname(String * hostname); + virtual String * hostname(); + + virtual void setPort(unsigned int port); + virtual unsigned int port(); + + virtual void setUsername(String * login); + virtual String * username(); + + virtual void setPassword(String * password); + virtual String * password(); + + virtual void setConnectionType(ConnectionType connectionType); + virtual ConnectionType connectionType(); + + virtual void setTimeout(time_t timeout); + virtual time_t timeout(); + + virtual void setCheckCertificateEnabled(bool enabled); + virtual bool isCheckCertificateEnabled(); + + virtual void setConnectionLogger(ConnectionLogger * logger); + virtual ConnectionLogger * connectionLogger(); + +#ifdef __APPLE__ + virtual void setDispatchQueue(dispatch_queue_t dispatchQueue); + virtual dispatch_queue_t dispatchQueue(); +#endif + + virtual MCNNTPFetchArticlesOperation * fetchArticlesOperation(String * group); + + virtual NNTPFetchHeaderOperation * fetchHeaderOperation(String * groupName, unsigned int index); + + virtual NNTPFetchArticleOperation * fetchArticleOperation(String *groupName, unsigned int index); + + virtual NNTPListNewsgroupsOperation * listAllNewsgroupsOperation(); + virtual NNTPListNewsgroupsOperation * listSubscribedNewsgroupsOperation(); + + virtual NNTPOperation * disconnectOperation(); + + virtual NNTPOperation * checkAccountOperation(); + + private: + NNTPSession * mSession; + OperationQueue * mQueue; + NNTPOperationQueueCallback * mQueueCallback; + ConnectionLogger * mConnectionLogger; + pthread_mutex_t mConnectionLoggerLock; + NNTPConnectionLogger * mInternalLogger; + + public: // private + virtual void runOperation(NNTPOperation * operation); + virtual NNTPSession * session(); + virtual void logConnection(ConnectionLogType logType, Data * buffer); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCNNTPCheckAccountOperation.h b/MailCore.framework/Versions/A/Headers/MCNNTPCheckAccountOperation.h new file mode 100644 index 0000000..28db9c5 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCNNTPCheckAccountOperation.h @@ -0,0 +1,32 @@ +// +// MCNNTPCheckAccountOperation.h +// mailcore2 +// +// Created by Robert Widmann on 8/13/14. +// Copyright (c) 2014 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCNNTPCHECKACCOUNTOPERATION_H + +#define MAILCORE_MCNNTPCHECKACCOUNTOPERATION_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class NNTPCheckAccountOperation : public NNTPOperation { + public: + NNTPCheckAccountOperation(); + virtual ~NNTPCheckAccountOperation(); + + public: // subclass behavior + virtual void main(); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCNNTPFetchArticleOperation.h b/MailCore.framework/Versions/A/Headers/MCNNTPFetchArticleOperation.h new file mode 100644 index 0000000..4f607c4 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCNNTPFetchArticleOperation.h @@ -0,0 +1,45 @@ +// +// MCMCNNTPFetchArticlesOperation.h +// mailcore2 +// +// Created by Robert Widmann on 8/13/14. +// Copyright (c) 2014 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCNNTPFETCHARTICLEOPERATION_H + +#define MAILCORE_MCNNTPFETCHARTICLEOPERATION_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + class NNTPFetchArticleOperation : public NNTPOperation { + public: + NNTPFetchArticleOperation(); + virtual ~NNTPFetchArticleOperation(); + + virtual void setGroupName(String * groupName); + virtual String * groupName(); + + virtual void setMessageIndex(unsigned int messageIndex); + virtual unsigned int messageIndex(); + + virtual Data * data(); + + public: // subclass behavior + virtual void main(); + + private: + String * mGroupName; + unsigned int mMessageIndex; + Data * mData; + + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCNNTPFetchArticlesOperation.h b/MailCore.framework/Versions/A/Headers/MCNNTPFetchArticlesOperation.h new file mode 100644 index 0000000..fa0037c --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCNNTPFetchArticlesOperation.h @@ -0,0 +1,41 @@ +// +// MCMCNNTPFetchArticlesOperation.h +// mailcore2 +// +// Created by Robert Widmann on 8/13/14. +// Copyright (c) 2014 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCNNTPFETCHARTICLESOPERATION_H + +#define MAILCORE_MCNNTPFETCHARTICLESOPERATION_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class MCNNTPFetchArticlesOperation : public NNTPOperation { + public: + MCNNTPFetchArticlesOperation(); + virtual ~MCNNTPFetchArticlesOperation(); + + virtual void setGroupName(String * groupName); + virtual String * groupName(); + + virtual IndexSet * articles(); + + public: // subclass behavior + virtual void main(); + + private: + String * mGroupName; + IndexSet * mArticles; + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCNNTPFetchHeaderOperation.h b/MailCore.framework/Versions/A/Headers/MCNNTPFetchHeaderOperation.h new file mode 100644 index 0000000..97b12b0 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCNNTPFetchHeaderOperation.h @@ -0,0 +1,48 @@ +// +// MCNNTPFetchHeaderOperation.h +// mailcore2 +// +// Created by Robert Widmann on 8/13/14. +// Copyright (c) 2014 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCNNTPFETCHHEADEROPERATION_H + +#define MAILCORE_MCNNTPFETCHHEADEROPERATION_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class MessageHeader; + + class NNTPFetchHeaderOperation : public NNTPOperation { + public: + NNTPFetchHeaderOperation(); + virtual ~NNTPFetchHeaderOperation(); + + virtual void setGroupName(String * groupName); + virtual String * groupName(); + + virtual void setMessageIndex(unsigned int messageIndex); + virtual unsigned int messageIndex(); + + virtual MessageHeader * header(); + + public: // subclass behavior + virtual void main(); + + private: + String * mGroupName; + unsigned int mMessageIndex; + MessageHeader * mHeader; + + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCNNTPGroupInfo.h b/MailCore.framework/Versions/A/Headers/MCNNTPGroupInfo.h new file mode 100644 index 0000000..aeab58c --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCNNTPGroupInfo.h @@ -0,0 +1,38 @@ +#ifndef MAILCORE_MCNNTPGROUPINFO_H + +#define MAILCORE_MCNNTPGROUPINFO_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class NNTPGroupInfo : public Object { + public: + NNTPGroupInfo(); + virtual ~NNTPGroupInfo(); + + virtual void setName(String * uid); + virtual String * name(); + + virtual void setMessageCount(uint32_t messages); + virtual uint32_t messageCount(); + + public: // subclass behavior + NNTPGroupInfo(NNTPGroupInfo * other); + virtual String * description(); + virtual Object * copy(); + + private: + String * mName; + uint32_t mMessageCount; + + void init(); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCNNTPListNewsgroupsOperation.h b/MailCore.framework/Versions/A/Headers/MCNNTPListNewsgroupsOperation.h new file mode 100644 index 0000000..5415601 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCNNTPListNewsgroupsOperation.h @@ -0,0 +1,41 @@ +// +// MCNNTPListNewsgroupsMessagesOperation.h +// mailcore2 +// +// Created by Robert Widmann on 8/13/14. +// Copyright (c) 2014 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCNNTPLISTNEWSGROUPSOPERATION_H + +#define MAILCORE_MCNNTPLISTNEWSGROUPSOPERATION_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class NNTPListNewsgroupsOperation : public NNTPOperation { + public: + NNTPListNewsgroupsOperation(); + virtual ~NNTPListNewsgroupsOperation(); + + virtual void setListsSubscribed(bool listsSubscribed); + virtual bool listsSubscribed(); + + virtual Array * groups(); + + public: // subclass behavior + virtual void main(); + + private: + bool mListsSuscribed; + Array * /* NNTPGroupInfo */ mGroups; + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCNNTPOperation.h b/MailCore.framework/Versions/A/Headers/MCNNTPOperation.h new file mode 100644 index 0000000..fb40e9d --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCNNTPOperation.h @@ -0,0 +1,53 @@ +// +// MCNNTPOperation.h +// mailcore2 +// +// Created by Robert Widmann on 8/13/14. +// Copyright (c) 2014 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCNNTPOPERATION_H + +#define MAILCORE_MCNNTPOPERATION_H + +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class NNTPAsyncSession; + class NNTPOperationCallback; + + class NNTPOperation : public Operation, public NNTPProgressCallback { + public: + NNTPOperation(); + virtual ~NNTPOperation(); + + virtual void setSession(NNTPAsyncSession * session); + virtual NNTPAsyncSession * session(); + + virtual void setNNTPCallback(NNTPOperationCallback * callback); + virtual NNTPOperationCallback * nntpCallback(); + + virtual void setError(ErrorCode error); + virtual ErrorCode error(); + + virtual void start(); + + private: + NNTPAsyncSession * mSession; + NNTPOperationCallback * mPopCallback; + ErrorCode mError; + private: + virtual void bodyProgress(NNTPSession * session, unsigned int current, unsigned int maximum); + virtual void bodyProgressOnMainThread(void * context); + + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCNNTPOperationCallback.h b/MailCore.framework/Versions/A/Headers/MCNNTPOperationCallback.h new file mode 100644 index 0000000..f616661 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCNNTPOperationCallback.h @@ -0,0 +1,28 @@ +// +// MCNNTPOperationCallback.h +// mailcore2 +// +// Created by Robert Widmann on 8/13/14. +// Copyright (c) 2014 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCNNTPOPERATIONCALLBACK_H + +#define MAILCORE_MCNNTPOPERATIONCALLBACK_H + +#ifdef __cplusplus + +namespace mailcore { + + class NNTPOperation; + + class NNTPOperationCallback { + public: + virtual void bodyProgress(NNTPOperation * session, unsigned int current, unsigned int maximum) {}; + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCNNTPProgressCallback.h b/MailCore.framework/Versions/A/Headers/MCNNTPProgressCallback.h new file mode 100644 index 0000000..f863cc0 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCNNTPProgressCallback.h @@ -0,0 +1,20 @@ +#ifndef MAILCORE_MCNNTPPROGRESSCALLBACK_H + +#define MAILCORE_MCNNTPPROGRESSCALLBACK_H + +#ifdef __cplusplus + +namespace mailcore { + + class NNTPSession; + + class NNTPProgressCallback { + public: + virtual void bodyProgress(NNTPSession * session, unsigned int current, unsigned int maximum) {}; + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCNNTPSession.h b/MailCore.framework/Versions/A/Headers/MCNNTPSession.h new file mode 100644 index 0000000..a6fb511 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCNNTPSession.h @@ -0,0 +1,88 @@ +#ifndef MAILCORE_MCNNTPSESSION_H +#define MAILCORE_MCNNTPSESSION_H + +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class NNTPProgressCallback; + class MessageHeader; + + class NNTPSession : public Object { + public: + NNTPSession(); + virtual ~NNTPSession(); + + virtual void setHostname(String * hostname); + virtual String * hostname(); + + virtual void setPort(unsigned int port); + virtual unsigned int port(); + + virtual void setUsername(String * username); + virtual String * username(); + + virtual void setPassword(String * password); + virtual String * password(); + + virtual void setConnectionType(ConnectionType connectionType); + virtual ConnectionType connectionType(); + + virtual void setTimeout(time_t timeout); + virtual time_t timeout(); + + virtual void setCheckCertificateEnabled(bool enabled); + virtual bool isCheckCertificateEnabled(); + + virtual void connect(ErrorCode * pError); + virtual void disconnect(); + + virtual void login(ErrorCode * pError); + + virtual void checkAccount(ErrorCode * pError); + + virtual Array * /* NNTPGroupInfo */ listAllNewsgroups(ErrorCode * pError); + virtual Array * listSubscribedNewsgroups(ErrorCode * pError); + + virtual MessageHeader * fetchHeader(String *groupName, unsigned int index, ErrorCode * pError); + + virtual IndexSet * fetchArticles(String * groupname, ErrorCode * pError); + + Data * fetchArticle(String *groupName, unsigned int index, NNTPProgressCallback * callback, ErrorCode * pError); + + virtual void setConnectionLogger(ConnectionLogger * logger); + virtual ConnectionLogger * connectionLogger(); + + private: + String * mHostname; + unsigned int mPort; + String * mUsername; + String * mPassword; + ConnectionType mConnectionType; + bool mCheckCertificateEnabled; + time_t mTimeout; + + newsnntp * mNNTP; + int mState; + + ConnectionLogger * mConnectionLogger; + + void init(); + bool checkCertificate(); + void setup(); + void unsetup(); + void connectIfNeeded(ErrorCode * pError); + void loginIfNeeded(ErrorCode * pError); + void readerIfNeeded(ErrorCode * pError); + void listIfNeeded(ErrorCode * pError); + void selectGroup(String * folder, ErrorCode * pError); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCNetService.h b/MailCore.framework/Versions/A/Headers/MCNetService.h new file mode 100644 index 0000000..aeb0c0f --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCNetService.h @@ -0,0 +1,59 @@ +// +// MCNetService.h +// mailcore2 +// +// Created by Robert Widmann on 4/28/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCNETSERVICE_H + +#define MAILCORE_MCNETSERVICE_H + +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class NetService : public Object { + + public: + NetService(); + virtual ~NetService(); + + virtual void setHostname(String * hostname); + virtual String * hostname(); + + virtual void setPort(unsigned int port); + virtual unsigned int port(); + + virtual void setConnectionType(ConnectionType connectionType); + virtual ConnectionType connectionType(); + + virtual String * normalizedHostnameWithEmail(String * email); + + public: // serialization + static NetService * serviceWithInfo(HashMap * info); + virtual HashMap * info(); + + public: //subclass behavior + NetService(NetService * other); + virtual String * description(); + virtual Object * copy(); + + private: + String * mHostname; + unsigned int mPort; + ConnectionType mConnectionType; + + void init(); + void fillWithInfo(HashMap * info); + }; + +} + +#endif + +#endif \ No newline at end of file diff --git a/MailCore.framework/Versions/A/Headers/MCNull.h b/MailCore.framework/Versions/A/Headers/MCNull.h new file mode 100644 index 0000000..d17eb10 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCNull.h @@ -0,0 +1,28 @@ +// +// MCNull.h +// hermes +// +// Created by DINH Viêt Hoà on 4/9/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCNULL_H + +#define MAILCORE_MCNULL_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class Null : public Object { + public: + static Null * null(); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOAbstract.h b/MailCore.framework/Versions/A/Headers/MCOAbstract.h new file mode 100644 index 0000000..e174b81 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOAbstract.h @@ -0,0 +1,23 @@ +// +// MCOAbstract.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/10/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOABSTRACT_H + +#define MAILCORE_MCOABSTRACT_H + +#import +#import +#import +#import +#import +#import +#import +#import +#import + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOAbstractMessage.h b/MailCore.framework/Versions/A/Headers/MCOAbstractMessage.h new file mode 100644 index 0000000..d917d82 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOAbstractMessage.h @@ -0,0 +1,49 @@ +// +// MCOAbstractMessage.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/10/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOABSTRACTMESSAGE_H + +#define MAILCORE_MCOABSTRACTMESSAGE_H + +#import + +@class MCOMessageHeader; +@class MCOAbstractPart; + +@interface MCOAbstractMessage : NSObject + +/** Header of the message. */ +@property (nonatomic, strong) MCOMessageHeader * header; + +/** Returns the part with the given Content-ID.*/ +- (MCOAbstractPart *) partForContentID:(NSString *)contentID; + +/** Returns the part with the given unique identifier.*/ +- (MCOAbstractPart *) partForUniqueID:(NSString *)uniqueID; + +/** All attachments in the message. + It will return an array of MCOIMAPPart for MCOIMAPMessage. + It will return an array of MCOAttachment for MCOMessageParser. + It will return an array of MCOAttachment for MCOMessageBuilder. */ +- (NSArray * /* MCOAbstractPart */) attachments; + +/** All image attachments included inline in the message through cid: URLs. + It will return an array of MCOIMAPPart for MCOIMAPMessage. + It will return an array of MCOAttachment for MCOMessageParser. + It will return an array of MCOAttachment for MCOMessageBuilder. */ +- (NSArray * /* MCOAbstractPart */) htmlInlineAttachments; + +/** + Returns parts required to render the message as plain text or html. + This does not include inline images and attachments, but only the text content + */ +- (NSArray *) requiredPartsForRendering; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOAbstractMessagePart.h b/MailCore.framework/Versions/A/Headers/MCOAbstractMessagePart.h new file mode 100644 index 0000000..b511748 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOAbstractMessagePart.h @@ -0,0 +1,30 @@ +// +// MCOAbstractMessagePart.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/10/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOABSTRACTMESSAGEPART_H + +#define MAILCORE_MCOABSTRACTMESSAGEPART_H + +#import +#import + +@class MCOMessageHeader; + +@interface MCOAbstractMessagePart : MCOAbstractPart + +// Returns the header of the embedded message. +@property (nonatomic, strong) MCOMessageHeader * header; + +// Returns the main part of the embedded message. It can be MCOAbstractPart, MCOAbstractMultipart +// or a MCOAbstractMessagePart. +@property (nonatomic, strong) MCOAbstractPart * mainPart; + +@end + +#endif + diff --git a/MailCore.framework/Versions/A/Headers/MCOAbstractMultipart.h b/MailCore.framework/Versions/A/Headers/MCOAbstractMultipart.h new file mode 100644 index 0000000..4502319 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOAbstractMultipart.h @@ -0,0 +1,23 @@ +// +// MCOAbstractMultipart.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/10/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOABSTRACTMULTIPART_H + +#define MAILCORE_MCOABSTRACTMULTIPART_H + +#import +#import + +@interface MCOAbstractMultipart : MCOAbstractPart + +/** Returns the subparts of that multipart.*/ +@property (nonatomic, copy) NSArray * /* MCOAbstractPart */ parts; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOAbstractPart.h b/MailCore.framework/Versions/A/Headers/MCOAbstractPart.h new file mode 100644 index 0000000..e30f09b --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOAbstractPart.h @@ -0,0 +1,87 @@ +// +// MCOAbstractPart.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/10/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOABSTRACTPART_H + +#define MAILCORE_MCOABSTRACTPART_H + +#import + +@class MCOAbstractMessage; + +typedef NS_ENUM(NSInteger, MCOPartType) { + // Used for a single part. + // The part will be a MCOAbstractPart. + MCOPartTypeSingle, + + // Used for a message part (MIME type: message/rfc822). + // The part will be a MCOAbstractMessagePart. + // It's when a message is sent as attachment of an other message. + MCOPartTypeMessage, + + // Used for a multipart, multipart/mixed. + // The part will be a MCOAbstractMultipart. + MCOPartTypeMultipartMixed, + + // Used for a multipart, multipart/related. + // The part will be a MCOAbstractMultipart. + MCOPartTypeMultipartRelated, + + // Used for a multipart, multipart/alternative. + // The part will be a MCOAbstractMultipart. + MCOPartTypeMultipartAlternative, + + // Used for a signed message, multipart/signed. + // The part will be a MCOAbstractMultipart. + MCOPartTypeMultipartSigned, +}; + +@interface MCOAbstractPart : NSObject + +/** Returns type of the part (single / message part / multipart/mixed, + multipart/related, multipart/alternative). See MCOPartType.*/ +@property (nonatomic, assign) MCOPartType partType; + +/** Returns filename of the part.*/ +@property (nonatomic, copy) NSString * filename; + +/** Returns MIME type of the part. For example application/data.*/ +@property (nonatomic, copy) NSString * mimeType; + +/** Returns charset of the part in case it's a text single part.*/ +@property (nonatomic, copy) NSString * charset; + +/** Returns the unique ID generated for this part. + It's a unique identifier that's created when the object is created manually + or created by the parser.*/ +@property (nonatomic, copy) NSString * uniqueID; + +/** Returns the value of the Content-ID field of the part.*/ +@property (nonatomic, copy) NSString * contentID; + +/** Returns the value of the Content-Location field of the part.*/ +@property (nonatomic, copy) NSString * contentLocation; + +/** Returns the value of the Content-Description field of the part.*/ +@property (nonatomic, copy) NSString * contentDescription; + +/** Returns whether the part is an explicit inline attachment.*/ +@property (nonatomic, assign, getter=isInlineAttachment) BOOL inlineAttachment; + +/** Returns the part with the given Content-ID among this part and its subparts.*/ +- (MCOAbstractPart *) partForContentID:(NSString *)contentID; + +/** Returns the part with the given unique identifier among this part and its subparts.*/ +- (MCOAbstractPart *) partForUniqueID:(NSString *)uniqueID; + +/** Returns a string representation of the data according to charset.*/ +- (NSString *) decodedStringForData:(NSData *)data; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOAddress.h b/MailCore.framework/Versions/A/Headers/MCOAddress.h new file mode 100644 index 0000000..6c3284e --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOAddress.h @@ -0,0 +1,81 @@ +// +// MCOAddress.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/10/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOADDRESS_H + +#define MAILCORE_MCOADDRESS_H + +#import + +@interface MCOAddress : NSObject + +/** Creates an address with a display name and a mailbox. + + Example: [MCOAddress addressWithDisplayName:@"DINH Viêt Hoà" mailbox:@"hoa@etpan.org"] */ ++ (MCOAddress *) addressWithDisplayName:(NSString *)displayName + mailbox:(NSString *)mailbox; + +/** Creates an address with only a mailbox. + + Example: [MCOAddress addressWithMailbox:@"hoa@etpan.org"]*/ ++ (MCOAddress *) addressWithMailbox:(NSString *)mailbox; + +/** Creates an address with a RFC822 string. + + Example: [MCOAddress addressWithRFC822String:@"DINH Vi=C3=AAt Ho=C3=A0 "]*/ ++ (MCOAddress *) addressWithRFC822String:(NSString *)RFC822String; + +/** Creates an address with a non-MIME-encoded RFC822 string. + + Example: [MCOAddress addressWithNonEncodedRFC822String:@"DINH Viêt Hoà "]*/ ++ (MCOAddress *) addressWithNonEncodedRFC822String:(NSString *)nonEncodedRFC822String; + +/** + Returns an NSArray of MCOAddress objects that contain the parsed + forms of the RFC822 encoded addresses. + + For example: @[ @"DINH Vi=C3=AAt Ho=C3=A0 " ]*/ ++ (NSArray *) addressesWithRFC822String:(NSString *)string; + +/** + Returns an NSArray of MCOAddress objects that contain the parsed + forms of non-encoded RFC822 addresses. + + For example: @[ "DINH Viêt Hoà " ]*/ ++ (NSArray *) addressesWithNonEncodedRFC822String:(NSString *)string; + + +/** Returns the display name of the address.*/ +@property (nonatomic, copy) NSString * displayName; + +/** Returns the mailbox of the address.*/ +@property (nonatomic, copy) NSString * mailbox; + +/** Returns the RFC822 encoding of the address. + + For example: "DINH Vi=C3=AAt Ho=C3=A0 "*/ +- (NSString *) RFC822String; + +/** Returns the non-MIME-encoded RFC822 encoding of the address. + + For example: "DINH Viêt Hoà "*/ +- (NSString *) nonEncodedRFC822String; + +@end + +@interface NSArray (MCOAddress) + +/** Returns the RFC822 encoding of the addresses.*/ +- (NSString *) mco_RFC822StringForAddresses; + +/** Returns the non-MIME-encoded RFC822 of the addresses.*/ +- (NSString *) mco_nonEncodedRFC822StringForAddresses; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOAttachment.h b/MailCore.framework/Versions/A/Headers/MCOAttachment.h new file mode 100644 index 0000000..954a825 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOAttachment.h @@ -0,0 +1,59 @@ +// +// MCOAttachment.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/22/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOATTACHMENT_H + +#define MAILCORE_MCOATTACHMENT_H + +#import + +/** This is a single part. + + It can either parsed from RFC 822 message data or created to build a message.*/ + +@interface MCOAttachment : MCOAbstractPart + +/** Returns a MIME type for a filename.*/ ++ (NSString *) mimeTypeForFilename:(NSString *)filename; + +/** Returns a file attachment with the content of the given file.*/ ++ (MCOAttachment *) attachmentWithContentsOfFile:(NSString *)filename; + +/** Returns a file attachment with the given data and filename.*/ ++ (MCOAttachment *) attachmentWithData:(NSData *)data filename:(NSString *)filename; + +/** Returns a part with an HTML content.*/ ++ (MCOAttachment *) attachmentWithHTMLString:(NSString *)htmlString; + +/** Returns a part with a RFC 822 messsage attachment.*/ ++ (MCOAttachment *) attachmentWithRFC822Message:(NSData *)messageData; + +/** Returns a part with an plain text content.*/ ++ (MCOAttachment *) attachmentWithText:(NSString *)text; + +/** Decoded data of the part.*/ +@property (nonatomic, strong) NSData * data; + +/** Returns string representation according to charset*/ +- (NSString *) decodedString; + +/** Adds a content type parameter.*/ +- (void) setContentTypeParameterValue:(NSString *)value forName:(NSString *)name; + +/** Remove a given content type parameter.*/ +- (void) removeContentTypeParameterForName:(NSString *)name; + +/** Returns the value of a given content type parameter.*/ +- (NSString *) contentTypeParameterValueForName:(NSString *)name; + +/** Returns an array with the names of all content type parameters.*/ +- (NSArray * /* NSString */) allContentTypeParametersNames; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOConstants.h b/MailCore.framework/Versions/A/Headers/MCOConstants.h new file mode 100644 index 0000000..85c9241 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOConstants.h @@ -0,0 +1,438 @@ +#ifndef MAILCORE_MCOCONSTANTS_H + +#define MAILCORE_MCOCONSTANTS_H + +/** It's the connection type.*/ +typedef NS_OPTIONS(NSInteger, MCOConnectionType) { + /** Clear-text connection for the protocol.*/ + MCOConnectionTypeClear = 1 << 0, + /** Clear-text connection at the beginning, then switch to encrypted connection using TLS/SSL*/ + /** on the same TCP connection.*/ + MCOConnectionTypeStartTLS = 1 << 1, + /** Encrypted connection using TLS/SSL.*/ + MCOConnectionTypeTLS = 1 << 2, +}; + +/** It's the authentication type.*/ +typedef NS_OPTIONS(NSInteger, MCOAuthType) { + /** Default authentication scheme of the protocol.*/ + MCOAuthTypeSASLNone = 0, + /** CRAM-MD5 authentication RFC 2195.*/ + MCOAuthTypeSASLCRAMMD5 = 1 << 0, + /** PLAIN authentication RFC 4616.*/ + MCOAuthTypeSASLPlain = 1 << 1, + /** GSSAPI authentication.*/ + MCOAuthTypeSASLGSSAPI = 1 << 2, + /** DIGEST-MD5 authentication RFC 2831.*/ + MCOAuthTypeSASLDIGESTMD5 = 1 << 3, + /** LOGIN authentication http://tools.ietf.org/id/draft-murchison-sasl-login-00.txt*/ + MCOAuthTypeSASLLogin = 1 << 4, + /** Secure Remote Password Authentication http://tools.ietf.org/html/draft-burdis-cat-srp-sasl-08*/ + MCOAuthTypeSASLSRP = 1 << 5, + /** NTLM authentication.*/ + MCOAuthTypeSASLNTLM = 1 << 6, + /** Kerberos 4 authentication.*/ + MCOAuthTypeSASLKerberosV4 = 1 << 7, + /** OAuth2 authentication.*/ + MCOAuthTypeXOAuth2 = 1 << 8, + /** OAuth2 authentication on outlook.com.*/ + MCOAuthTypeXOAuth2Outlook = 1 << 9, +}; + +/** It's the IMAP flags of the folder.*/ +typedef NS_OPTIONS(NSInteger, MCOIMAPFolderFlag) { + MCOIMAPFolderFlagNone = 0, + /** \Marked*/ + MCOIMAPFolderFlagMarked = 1 << 0, + /** \Unmarked*/ + MCOIMAPFolderFlagUnmarked = 1 << 1, + /** \NoSelect: When a folder can't be selected.*/ + MCOIMAPFolderFlagNoSelect = 1 << 2, + /** \NoInferiors: When the folder has no children.*/ + MCOIMAPFolderFlagNoInferiors = 1 << 3, + /** \Inbox: When the folder is the inbox.*/ + MCOIMAPFolderFlagInbox = 1 << 4, + /** \Sent: When the folder is the sent folder.*/ + MCOIMAPFolderFlagSentMail = 1 << 5, + /** \Starred: When the folder is the starred folder*/ + MCOIMAPFolderFlagStarred = 1 << 6, + /** \AllMail: When the folder is all mail.*/ + MCOIMAPFolderFlagAllMail = 1 << 7, + /** \Trash: When the folder is the trash.*/ + MCOIMAPFolderFlagTrash = 1 << 8, + /** \Drafts: When the folder is the drafts folder.*/ + MCOIMAPFolderFlagDrafts = 1 << 9, + /** \Spam: When the folder is the spam folder.*/ + MCOIMAPFolderFlagSpam = 1 << 10, + /** \Important: When the folder is the important folder.*/ + MCOIMAPFolderFlagImportant = 1 << 11, + /** \Archive: When the folder is archive.*/ + MCOIMAPFolderFlagArchive = 1 << 12, + /** \All: When the folder contains all mails, similar to \AllMail.*/ + MCOIMAPFolderFlagAll = MCOIMAPFolderFlagAllMail, + /** \Junk: When the folder is the spam folder.*/ + MCOIMAPFolderFlagJunk = MCOIMAPFolderFlagSpam, + /** \Flagged: When the folder contains all the flagged emails.*/ + MCOIMAPFolderFlagFlagged = MCOIMAPFolderFlagStarred, + /** Mask to identify the folder */ + MCOIMAPFolderFlagFolderTypeMask = MCOIMAPFolderFlagInbox | MCOIMAPFolderFlagSentMail | MCOIMAPFolderFlagStarred | MCOIMAPFolderFlagAllMail | + MCOIMAPFolderFlagTrash| MCOIMAPFolderFlagDrafts | MCOIMAPFolderFlagSpam | MCOIMAPFolderFlagImportant | MCOIMAPFolderFlagArchive, +}; + +/** It's the flags of a message.*/ +typedef NS_OPTIONS(NSInteger, MCOMessageFlag) { + MCOMessageFlagNone = 0, + /** Seen/Read flag.*/ + MCOMessageFlagSeen = 1 << 0, + /** Replied/Answered flag.*/ + MCOMessageFlagAnswered = 1 << 1, + /** Flagged/Starred flag.*/ + MCOMessageFlagFlagged = 1 << 2, + /** Deleted flag.*/ + MCOMessageFlagDeleted = 1 << 3, + /** Draft flag.*/ + MCOMessageFlagDraft = 1 << 4, + /** $MDNSent flag.*/ + MCOMessageFlagMDNSent = 1 << 5, + /** $Forwarded flag.*/ + MCOMessageFlagForwarded = 1 << 6, + /** $SubmitPending flag.*/ + MCOMessageFlagSubmitPending = 1 << 7, + /** $Submitted flag.*/ + MCOMessageFlagSubmitted = 1 << 8, +}; + +/** It's the encoding of a part.*/ +typedef NS_ENUM(NSInteger, MCOEncoding) { + /** 7bit encoding.*/ + MCOEncoding7Bit = 0, /** should match MAILIMAP_BODY_FLD_ENC_7BIT*/ + /** 8bit encoding.*/ + MCOEncoding8Bit = 1, /** should match MAILIMAP_BODY_FLD_ENC_8BIT*/ + /** binary encoding.*/ + MCOEncodingBinary = 2, /** should match MAILIMAP_BODY_FLD_ENC_BINARY*/ + /** base64 encoding.*/ + MCOEncodingBase64 = 3, /** should match MAILIMAP_BODY_FLD_ENC_BASE64*/ + /** quoted-printable encoding.*/ + MCOEncodingQuotedPrintable = 4, /** should match MAILIMAP_BODY_FLD_ENC_QUOTED_PRINTABLE*/ + /** other encoding.*/ + MCOEncodingOther = 5, /** should match MAILIMAP_BODY_FLD_ENC_OTHER*/ + + /** Negative values should be used for encoding not supported by libetpan.*/ + + /** UUEncode encoding.*/ + MCOEncodingUUEncode = -1 +}; + +/** It's the information to fetch for a given message in the IMAP FETCH request.*/ +typedef NS_OPTIONS(NSInteger, MCOIMAPMessagesRequestKind) { + /** UID of the message.*/ + MCOIMAPMessagesRequestKindUid = 0, /** This is the default and it's always fetched*/ + /** Flags of the message.*/ + MCOIMAPMessagesRequestKindFlags = 1 << 0, + /** Headers of the message (parsed by the server).*/ + MCOIMAPMessagesRequestKindHeaders = 1 << 1, + /** MIME structure of the message.*/ + MCOIMAPMessagesRequestKindStructure = 1 << 2, + /** Received date.*/ + MCOIMAPMessagesRequestKindInternalDate = 1 << 3, + /** Headers through headers data.*/ + MCOIMAPMessagesRequestKindFullHeaders = 1 << 4, + /** Subject of the message.*/ + MCOIMAPMessagesRequestKindHeaderSubject = 1 << 5, + /** Gmail Labels.*/ + MCOIMAPMessagesRequestKindGmailLabels = 1 << 6, + /** Gmail Message ID.*/ + MCOIMAPMessagesRequestKindGmailMessageID = 1 << 7, + /** Gmail Thread ID.*/ + MCOIMAPMessagesRequestKindGmailThreadID = 1 << 8, + /** Extra Headers.*/ + MCOIMAPMessagesRequestKindExtraHeaders = 1 << 9, + /* Request size of message */ + MCOIMAPMessagesRequestKindSize = 1 << 10, + +}; + +/** It defines the behavior of the STORE flags request.*/ +typedef NS_ENUM(NSInteger, MCOIMAPStoreFlagsRequestKind) { + /** Add the given flags.*/ + MCOIMAPStoreFlagsRequestKindAdd, + /** Remove the given flags.*/ + MCOIMAPStoreFlagsRequestKindRemove, + /** Set the given flags.*/ + MCOIMAPStoreFlagsRequestKindSet, +}; + +/** It's the search type.*/ +typedef NS_ENUM(NSInteger, MCOIMAPSearchKind) { + /** Search All */ + MCOIMAPSearchKindAll, + /** No search.*/ + MCOIMAPSearchKindNone, + /** Match sender.*/ + MCOIMAPSearchKindFrom, + /** Match to */ + MCOIMAPSearchKindTo, + /** Match CC: */ + MCOIMAPSearchKindCc, + /** Match BCC: */ + MCOIMAPSearchKindBcc, + /** Match recipient.*/ + MCOIMAPSearchKindRecipient, + /** Match subject.*/ + MCOIMAPSearchKindSubject, + /** Match content of the message, including the headers.*/ + MCOIMAPSearchKindContent, + /** Match content of the message, excluding the headers.*/ + MCOIMAPSearchKindBody, + /** Match uids */ + MCOIMAPSearchKindUids, + /** Match headers of the message.*/ + MCOIMAPSearchKindHeader, + /** Match messages that are read.*/ + MCOIMAPSearchKindRead, + /** Match messages that are not read.*/ + MCOIMAPSearchKindUnread, + /** Match messages that are flagged.*/ + MCOIMAPSearchKindFlagged, + /** Match messages that are not flagged.*/ + MCOIMAPSearchKindUnflagged, + /** Match messages that are answered.*/ + MCOIMAPSearchKindAnswered, + /** Match messages that are not answered.*/ + MCOIMAPSearchKindUnanswered, + /** Match messages that are a drafts.*/ + MCOIMAPSearchKindDraft, + /** Match messages that are not drafts.*/ + MCOIMAPSearchKindUndraft, + /** Match messages that are deleted.*/ + MCOIMAPSearchKindDeleted, + /** Match messages that are spam.*/ + MCOIMAPSearchKindSpam, + /** Match messages before the given date.*/ + MCOIMAPSearchKindBeforeDate, + /** Match messages on the given date.*/ + MCOIMAPSearchKindOnDate, + /** Match messages after the given date.*/ + MCOIMAPSearchKindSinceDate, + /** Match messages before the given received date.*/ + MCOIMAPSearchKindBeforeReceivedDate, + /** Match messages on the given received date.*/ + MCOIMAPSearchKindOnReceivedDate, + /** Match messages after the given received date.*/ + MCOIMAPSearchKindSinceReceivedDate, + /** Match messages that are larger than the given size in bytes.*/ + MCOIMAPSearchKindSizeLarger, + /** Match messages that are smaller than the given size in bytes.*/ + MCOIMAPSearchKindSizeSmaller, + /** Match X-GM-THRID.*/ + MCOIMAPSearchGmailThreadID, + /** Match X-GM-MSGID.*/ + MCOIMAPSearchGmailMessageID, + /** Match X-GM-RAW.*/ + MCOIMAPSearchGmailRaw, + /** Or expresssion.*/ + MCOIMAPSearchKindOr, + /** And expression.*/ + MCOIMAPSearchKindAnd, + /** Not expression.*/ + MCOIMAPSearchKindNot, +}; + +/** Keys for the namespace dictionary.*/ +#define MCOIMAPNamespacePersonal @"IMAPNamespacePersonal" +#define MCOIMAPNamespaceOther @"IMAPNamespaceOther" +#define MCOIMAPNamespaceShared @"IMAPNamespaceShared" + +/** This is the constants for the IMAP capabilities.*/ +/** See corresponding RFC for more information.*/ +typedef NS_ENUM(NSInteger, MCOIMAPCapability) { + /** ACL Capability.*/ + MCOIMAPCapabilityACL, + /** BINARY Capability.*/ + MCOIMAPCapabilityBinary, + /** CATENATE Capability.*/ + MCOIMAPCapabilityCatenate, + /** CHILDREN Capability.*/ + MCOIMAPCapabilityChildren, + /** COMPRESS Capability.*/ + MCOIMAPCapabilityCompressDeflate, + /** CONDSTORE Capability.*/ + MCOIMAPCapabilityCondstore, + /** ENABLE Capability.*/ + MCOIMAPCapabilityEnable, + /** IDLE Capability.*/ + MCOIMAPCapabilityIdle, + /** ID Capability.*/ + MCOIMAPCapabilityId, + /** LITERAL+ Capability.*/ + MCOIMAPCapabilityLiteralPlus, + /** MULTIAPPEND Capability.*/ + MCOIMAPCapabilityMultiAppend, + /** NAMESPACE Capability.*/ + MCOIMAPCapabilityNamespace, + /** QRESYNC Capability.*/ + MCOIMAPCapabilityQResync, + /** QUOTE Capability.*/ + MCOIMAPCapabilityQuota, + /** SORT Capability.*/ + MCOIMAPCapabilitySort, + /** STARTTLS Capability.*/ + MCOIMAPCapabilityStartTLS, + /** THREAD=ORDEREDSUBJECT Capability.*/ + MCOIMAPCapabilityThreadOrderedSubject, + /** THREAD=REFERENCES Capability.*/ + MCOIMAPCapabilityThreadReferences, + /** UIDPLUS Capability.*/ + MCOIMAPCapabilityUIDPlus, + /** UNSELECT Capability.*/ + MCOIMAPCapabilityUnselect, + /** XLIST Capability.*/ + MCOIMAPCapabilityXList, + /** AUTH=ANONYMOUS Capability.*/ + MCOIMAPCapabilityAuthAnonymous, + /** AUTH=CRAM-MD5 Capability.*/ + MCOIMAPCapabilityAuthCRAMMD5, + /** AUTH=DIGEST-MD5 Capability.*/ + MCOIMAPCapabilityAuthDigestMD5, + /** AUTH=EXTERNAL Capability.*/ + MCOIMAPCapabilityAuthExternal, + /** AUTH=GSSAPI Capability.*/ + MCOIMAPCapabilityAuthGSSAPI, + /** AUTH=KERBEROSV4 Capability.*/ + MCOIMAPCapabilityAuthKerberosV4, + /** AUTH=LOGIN Capability.*/ + MCOIMAPCapabilityAuthLogin, + /** AUTH=NTML Capability.*/ + MCOIMAPCapabilityAuthNTLM, + /** AUTH=OTP Capability.*/ + MCOIMAPCapabilityAuthOTP, + /** AUTH=PLAIN Capability.*/ + MCOIMAPCapabilityAuthPlain, + /** AUTH=SKEY Capability.*/ + MCOIMAPCapabilityAuthSKey, + /** AUTH=SRP Capability.*/ + MCOIMAPCapabilityAuthSRP, + /** AUTH=XOAUTH2 Capability.*/ + MCOIMAPCapabilityXOAuth2, + /** X-GM-EXT-1 Capability.*/ + MCOIMAPCapabilityGmail +}; + +/** Error domain for mailcore.*/ +#define MCOErrorDomain @"MCOErrorDomain" + +/** Here's the list of errors.*/ +typedef NS_ENUM(NSInteger, MCOErrorCode) { + /** No error occurred.*/ + MCOErrorNone, + /** An error related to the connection occurred.*/ + /** It could not connect or it's been disconnected.*/ + MCOErrorConnection, + /** TLS/SSL connection was not available.*/ + MCOErrorTLSNotAvailable, + /** The protocol could not be parsed.*/ + MCOErrorParse, + /** Certificate was not valid.*/ + MCOErrorCertificate, + /** An authentication error occurred.*/ + MCOErrorAuthentication, + /** Specific to Gmail: IMAP not enabled.*/ + MCOErrorGmailIMAPNotEnabled, + /** Specific to Gmail: Exceeded bandwidth limit.*/ + MCOErrorGmailExceededBandwidthLimit, + /** Specific to Gmail: Too many simultaneous connections.*/ + MCOErrorGmailTooManySimultaneousConnections, + /** Specific to Mobile Me: Moved to iCloud.*/ + MCOErrorMobileMeMoved, + /** Specific to Yahoo: not available.*/ + MCOErrorYahooUnavailable, + /** Non existant folder, select failed.*/ + MCOErrorNonExistantFolder, + /** IMAP: Error occurred while renaming a folder.*/ + MCOErrorRename, + /** IMAP: Error occurred while deleting a folder.*/ + MCOErrorDelete, + /** IMAP: Error occurred while creating a folder.*/ + MCOErrorCreate, + /** IMAP: Error occurred while subscribing/unsubcribing to a folder.*/ + MCOErrorSubscribe, + /** IMAP: Error occurred while adding a message to a folder.*/ + MCOErrorAppend, + /** IMAP: Error occurred while copying a message.*/ + MCOErrorCopy, + /** IMAP: Error occurred while expunging.*/ + MCOErrorExpunge, + /** IMAP: Error occurred while fetching messages.*/ + MCOErrorFetch, + /** IMAP: Error occurred while IDLing.*/ + MCOErrorIdle, + /** IMAP: Error occurred while sending/getting identity.*/ + MCOErrorIdentity, + /** IMAP: Error occurred while getting namespace.*/ + MCOErrorNamespace, + /** IMAP: Error occurred while storing flags.*/ + MCOErrorStore, + /** IMAP: Error wile getting capabilities.*/ + MCOErrorCapability, + /** STARTTLS is not available.*/ + MCOErrorStartTLSNotAvailable, + /** SMTP: Illegal attachment: certain kind of attachment cannot be sent.*/ + MCOErrorSendMessageIllegalAttachment, + /** SMTP: Storage limit: message is probably too big.*/ + MCOErrorStorageLimit, + /** SMTP: Sending message is not allowed.*/ + MCOErrorSendMessageNotAllowed, + /** SMTP: Specific to hotmail. Needs to connect to webmail.*/ + MCOErrorNeedsConnectToWebmail, + /** SMTP: Error while sending message.*/ + MCOErrorSendMessage, + /** SMTP: Authentication required.*/ + MCOErrorAuthenticationRequired, + /** POP: Error occurred while fetching message list.*/ + MCOErrorFetchMessageList, + /** POP: Error occurred while deleting message.*/ + MCOErrorDeleteMessage, + /** SMTP: Error while checking account.*/ + MCOErrorInvalidAccount, + /** IMAP: Error when trying to enable compression.*/ + MCOErrorCompression, + /** SMTP: Error when no sender has been specified.*/ + MCOErrorNoSender, + /** SMTP: Error when no recipient has been specified.*/ + MCOErrorNoRecipient, + /** IMAP: Error when a noop operation fails.*/ + MCOErrorNoop, + /** The count of all errors */ + MCOErrorCodeCount, +}; + +/** Here's the list of connection log types.*/ +typedef NS_ENUM(NSInteger, MCOConnectionLogType) { + /** Received data.*/ + MCOConnectionLogTypeReceived, + /** Sent data.*/ + MCOConnectionLogTypeSent, + /** Sent private data. It can be a password.*/ + MCOConnectionLogTypeSentPrivate, + /** Parse error.*/ + MCOConnectionLogTypeErrorParse, + /** Error while receiving data. The data passed to the log will be nil.*/ + MCOConnectionLogTypeErrorReceived, + /** Error while sending dataThe data passed to the log will be nil.*/ + MCOConnectionLogTypeErrorSent, +}; + +/** + It's a network traffic logger. + @param connectionID is the identifier of the underlaying network socket. + @param type is the type of the log. + @param data is the data related to the log. + */ +typedef void (^MCOConnectionLogger)(void * connectionID, MCOConnectionLogType type, NSData * data); + +/** + It's called when asynchronous operations stop/start running. + */ +typedef void (^MCOOperationQueueRunningChangeBlock)(void); + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOHTMLRendererDelegate.h b/MailCore.framework/Versions/A/Headers/MCOHTMLRendererDelegate.h new file mode 100644 index 0000000..95f55b5 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOHTMLRendererDelegate.h @@ -0,0 +1,107 @@ +// +// MCOHTMLRendererDelegate.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/23/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOHTMLRENDERERDELEGATE_H + +#define MAILCORE_MCOHTMLRENDERERDELEGATE_H + +#import + +/** This delegate protocol is used to help rendering of the message. + + It will be used for the following methods. + + [MCOMessageParser htmlRenderingWithDelegate:], + + [MCOMessageBuilder htmlRenderingWithDelegate:] + + -[MCOIMAPMessage htmlRenderingWithFolder:delegate:] +*/ + +@class MCOAbstractPart; +@class MCOAbstractMessage; +@class MCOMessageHeader; +@class MCOAbstractMessagePart; + +@protocol MCOHTMLRendererDelegate + +/** All methods are optional.*/ +@optional + +/** This delegate method should return YES if it can render a preview of the attachment as an image. + part is always a single part. + +If the attachment can be previewed, it will be rendered using the image template. +If not, the attachment template will be used.*/ +- (BOOL) MCOAbstractMessage:(MCOAbstractMessage *)msg canPreviewPart:(MCOAbstractPart *)part; + +/** This delegate method should return YES if the part should be rendered.*/ +- (BOOL) MCOAbstractMessage:(MCOAbstractMessage *)msg shouldShowPart:(MCOAbstractPart *)part; + +/** This delegate method returns the values to be applied to the template for the given header. + See the content of MCHTMLRendererCallback.cpp for the default values of the header.*/ +- (NSDictionary *) MCOAbstractMessage:(MCOAbstractMessage *)msg templateValuesForHeader:(MCOMessageHeader *)header; + +/** This delegate method returns the values to be applied to the template for the given attachment. + See the content of MCHTMLRendererCallback.cpp for the default values of the attachment.*/ +- (NSDictionary *) MCOAbstractMessage:(MCOAbstractMessage *)msg templateValuesForPart:(MCOAbstractPart *)part; + +/** @name Template Methods + The following methods returns templates. They will match the syntax of ctemplate. + See https://code.google.com/p/ctemplate/ */ + +/** This delegate method returns the template for the main header of the message. + See the content of MCHTMLRendererCallback.cpp for the default values of the template.*/ +- (NSString *) MCOAbstractMessage:(MCOAbstractMessage *)msg templateForMainHeader:(MCOMessageHeader *)header; + +/** This delegate method returns the template an image attachment.*/ +- (NSString *) MCOAbstractMessage:(MCOAbstractMessage *)msg templateForImage:(MCOAbstractPart *)header; + +/** This delegate method returns the template attachment other than images. + See the content of MCHTMLRendererCallback.cpp for the default values of the template.*/ +- (NSString *) MCOAbstractMessage:(MCOAbstractMessage *)msg templateForAttachment:(MCOAbstractPart *)part; + +/** This delegate method returns the template of the main message. + It should include HEADER and a BODY values. + See the content of MCHTMLRendererCallback.cpp for the default values of the template.*/ +- (NSString *) MCOAbstractMessage_templateForMessage:(MCOAbstractMessage *)msg; + +/** This delegate method returns the template of an embedded message (included as attachment). + It should include HEADER and a BODY values. + See the content of MCHTMLRendererCallback.cpp for the default values of the template.*/ +- (NSString *) MCOAbstractMessage:(MCOAbstractMessage *)msg templateForEmbeddedMessage:(MCOAbstractMessagePart *)part; + +/** This delegate method returns the template for the header of an embedded message. + See the content of MCHTMLRendererCallback.cpp for the default values of the template.*/ +- (NSString *) MCOAbstractMessage:(MCOAbstractMessage *)msg templateForEmbeddedMessageHeader:(MCOMessageHeader *)header; + +/** This delegate method returns the separator between the text of the message and the attachments. + This delegate method returns the template for the header of an embedded message.*/ +- (NSString *) MCOAbstractMessage_templateForAttachmentSeparator:(MCOAbstractMessage *)msg; + +/** This delegate method cleans HTML content. + For example, it could fix broken tags, add missing , tags. + Default implementation uses HTMLCleaner::cleanHTML to clean HTML content. */ +- (NSString *) MCOAbstractMessage:(MCOAbstractMessage *)msg cleanHTMLForPart:(NSString *)html; + +/** @name Filters + + The following methods will filter the HTML content and may apply some filters to + change how to display the message.*/ + +/** This delegate method will apply the filter to HTML rendered content of a given text part. + For example, it could filter the CSS content.*/ +- (NSString *) MCOAbstractMessage:(MCOAbstractMessage *)msg filterHTMLForPart:(NSString *)html; + +/** This delegate method will apply a filter to the whole HTML content. + For example, it could collapse the quoted messages.*/ +- (NSString *) MCOAbstractMessage:(MCOAbstractMessage *)msg filterHTMLForMessage:(NSString *)html; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOHTMLRendererIMAPDelegate.h b/MailCore.framework/Versions/A/Headers/MCOHTMLRendererIMAPDelegate.h new file mode 100644 index 0000000..a127ec2 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOHTMLRendererIMAPDelegate.h @@ -0,0 +1,52 @@ +// +// MCOHTMLRendererIMAPDelegate.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/23/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOHTMLRENDERERIMAPDELEGATE_H + +#define MAILCORE_MCOHTMLRENDERERIMAPDELEGATE_H + +#import + +/** + This delegate protocol is used to fetch the content of the part of the message when the HTML render needs them. + It will help fetch the minimal amount of information from the message required to render the HTML. + + It will be used for the following method. + + [MCOIMAPMessage htmlRenderingWithFolder:delegate:] +*/ + +@class MCOIMAPPart; + +@protocol MCOHTMLRendererIMAPDelegate + +/** All methods are optional.*/ +@optional + +/** + The delegate method returns NULL if the delegate have not fetch the part yet. The opportunity can also be used to + start fetching the attachment. + It will return the data synchronously if it has already fetched it. +*/ +- (NSData *) MCOAbstractMessage:(MCOAbstractMessage *)msg dataForIMAPPart:(MCOIMAPPart *)part folder:(NSString *)folder; + +/** + The delegate method will notify the delegate to start fetching the given part. + It will be used to render an attachment that cannot be previewed. +*/ +- (void) MCOAbstractMessage:(MCOAbstractMessage *)msg prefetchAttachmentIMAPPart:(MCOIMAPPart *)part folder:(NSString *)folder; + +/** + The delegate method will notify the delegate to start fetching the given part. + It will be used to render an attachment that can be previewed. +*/ +- (void) MCOAbstractMessage:(MCOAbstractMessage *)msg prefetchImageIMAPPart:(MCOIMAPPart *)part folder:(NSString *)folder; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOIMAP.h b/MailCore.framework/Versions/A/Headers/MCOIMAP.h new file mode 100755 index 0000000..7acffce --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOIMAP.h @@ -0,0 +1,44 @@ +// +// MCOIMAP.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/22/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOIMAP_H + +#define MAILCORE_MCOIMAP_H + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOIMAPAppendMessageOperation.h b/MailCore.framework/Versions/A/Headers/MCOIMAPAppendMessageOperation.h new file mode 100644 index 0000000..1e5fbd3 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOIMAPAppendMessageOperation.h @@ -0,0 +1,42 @@ +// +// MCOIMAPAppendMessageOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/25/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOIMAPAPPENDMESSAGEOPERATION_H + +#define MAILCORE_MCOIMAPAPPENDMESSAGEOPERATION_H + +/** This class implements an operation that adds a message to a folder. */ + +#import +#import + +@interface MCOIMAPAppendMessageOperation : MCOIMAPBaseOperation + +@property (nonatomic, assign) time_t date; + +/** + This block will be called as bytes are sent +*/ +@property (nonatomic, copy) MCOIMAPBaseOperationProgressBlock progress; + +/** + Starts the asynchronous append operation. + + @param completionBlock Called when the operation is finished. + + - On success `error` will be nil and `createdUID` will be the value of the + UID of the created message if the server supports UIDPLUS or zero if not. + + - On failure, `error` will be set with `MCOErrorDomain` as domain and an + error code available in MCOConstants.h, `createdUID` will be zero. +*/ +- (void) start:(void (^)(NSError * error, uint32_t createdUID))completionBlock; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOIMAPBaseOperation.h b/MailCore.framework/Versions/A/Headers/MCOIMAPBaseOperation.h new file mode 100644 index 0000000..82a3437 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOIMAPBaseOperation.h @@ -0,0 +1,42 @@ +// +// MCOIMAPBaseOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/26/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOIMAPBASEOPERATION_H + +#define MAILCORE_MCOIMAPBASEOPERATION_H + +/** Represents a generic IMAP operation with methods that are called with progress updates */ + +#import + +typedef void (^MCOIMAPBaseOperationProgressBlock)(unsigned int current, unsigned int maximum); +typedef void (^MCOIMAPBaseOperationItemProgressBlock)(unsigned int current); + +@interface MCOIMAPBaseOperation : MCOOperation + +@property (nonatomic, assign, getter=isUrgent) BOOL urgent; + +/* Can be overriden by subclasses */ + +/* + Will be called when a sending or receiving the contents of a message + @param current The number of bytes sent or received + @param maximum The total number of bytes expected +*/ +- (void)bodyProgress:(unsigned int)current maximum:(unsigned int)maximum; + +/* + Will be called when a new item is received in a list of items, like for example a message list + @param current The number of items downloaded + @param maximum The total number of items expected +*/ +- (void)itemProgress:(unsigned int)current maximum:(unsigned int)maximum; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOIMAPCapabilityOperation.h b/MailCore.framework/Versions/A/Headers/MCOIMAPCapabilityOperation.h new file mode 100644 index 0000000..96314e2 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOIMAPCapabilityOperation.h @@ -0,0 +1,40 @@ +// +// MCOIMAPCapabilityOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/25/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOIMAPCAPABILITYOPERATION_H + +#define MAILCORE_MCOIMAPCAPABILITYOPERATION_H + +/** + This class implements an operation to query for IMAP capabilities, + like for example the extensions UIDPLUS, IDLE, NAMESPACE, ... etc +*/ + +#import + +@class MCOIndexSet; + +@interface MCOIMAPCapabilityOperation : MCOIMAPBaseOperation + + +/** + Starts the asynchronous capabilities operation. + + @param completionBlock Called when the operation is finished. + + - On success `error` will be nil and `capabilities` will contain a set of IMAP capabilities. + See `MCOConstants.h` under `MCOIMAPCapability` for a list of possible values. + + - On failure, `error` will be set with `MCOErrorDomain` as domain and an + error code available in MCOConstants.h, `capabilities` will be nil +*/ +- (void) start:(void (^)(NSError * error, MCOIndexSet * capabilities))completionBlock; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOIMAPCopyMessagesOperation.h b/MailCore.framework/Versions/A/Headers/MCOIMAPCopyMessagesOperation.h new file mode 100644 index 0000000..4c573a5 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOIMAPCopyMessagesOperation.h @@ -0,0 +1,37 @@ +// +// MCOIMAPCopyMessagesOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/25/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#import + +#ifndef MAILCORE_MCOCOPYMESSAGESOPERATION_H + +#define MAILCORE_MCOCOPYMESSAGESOPERATION_H + +/** Implements an operation for copying messages between folders */ + +@class MCOIndexSet; + +@interface MCOIMAPCopyMessagesOperation : MCOIMAPBaseOperation + +/** + Starts the asynchronous copy operation. + + @param completionBlock Called when the operation is finished. + + - On success `error` will be nil and `destUids` will contain the UIDs of the messages created + in the destination folder. If the server doesn't support UIDPLUS then `destUids` will be nil. + + - On failure, `error` will be set with `MCOErrorDomain` as domain and an + error code available in `MCOConstants.h`, `destUids` will be nil +*/ + +- (void) start:(void (^)(NSError * error, NSDictionary * uidMapping))completionBlock; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOIMAPFetchContentOperation.h b/MailCore.framework/Versions/A/Headers/MCOIMAPFetchContentOperation.h new file mode 100644 index 0000000..254cd14 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOIMAPFetchContentOperation.h @@ -0,0 +1,43 @@ +// +// MCOIMAPFetchContentOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/25/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOIMAPFETCHCONTENTOPERATION_H + +#define MAILCORE_MCOIMAPFETCHCONTENTOPERATION_H + +/** + This class implements an operation to fetch the content of a message. + It can be a part or a full message. +*/ + +#import +#import + +@interface MCOIMAPFetchContentOperation : MCOIMAPBaseOperation + +/** + This block will be called as bytes are received from the network +*/ +@property (nonatomic, copy) MCOIMAPBaseOperationProgressBlock progress; + +/** + Starts the asynchronous fetch operation. + + @param completionBlock Called when the operation is finished. + + - On success `error` will be nil and `data` will contain the requested data + + - On failure, `error` will be set with `MCOErrorDomain` as domain and an + error code available in `MCOConstants.h`, `data` will be nil +*/ + +- (void) start:(void (^)(NSError * error, NSData * data))completionBlock; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOIMAPFetchFoldersOperation.h b/MailCore.framework/Versions/A/Headers/MCOIMAPFetchFoldersOperation.h new file mode 100644 index 0000000..853c55f --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOIMAPFetchFoldersOperation.h @@ -0,0 +1,33 @@ +// +// MCOIMAPFetchFoldersOperation.h +// mailcore2 +// +// Created by Matt Ronge on 1/31/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOIMAPFETCHFOLDERSOPERATION_H + +#define MAILCORE_MCOIMAPFETCHFOLDERSOPERATION_H + +/** This class implements an operation to fetch a list of folders. */ + +#import + +@interface MCOIMAPFetchFoldersOperation : MCOIMAPBaseOperation + +/** + Starts the asynchronous fetch operation. + + @param completionBlock Called when the operation is finished. + + - On success `error` will be nil and `folders` will contain an array of MCOIMAPFolder + + - On failure, `error` will be set with `MCOErrorDomain` as domain and an + error code available in `MCOConstants.h`, `folders` will be nil +*/ +- (void) start:(void (^)(NSError * error, NSArray * /* MCOIMAPFolder */ folders))completionBlock; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOIMAPFetchMessagesOperation.h b/MailCore.framework/Versions/A/Headers/MCOIMAPFetchMessagesOperation.h new file mode 100644 index 0000000..13dad1b --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOIMAPFetchMessagesOperation.h @@ -0,0 +1,45 @@ +// +// MCOIMAPFetchMessagesOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/25/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOIMAPFETCHMESSAGESOPERATION_H + +#define MAILCORE_MCOIMAPFETCHMESSAGESOPERATION_H + +#import +#import + +/** This class implements an operation to fetch a list of messages from a folder */ + +@class MCOIndexSet; + +@interface MCOIMAPFetchMessagesOperation : MCOIMAPBaseOperation + +/** This block will be called each time a new message is downloaded. */ +@property (nonatomic, copy) MCOIMAPBaseOperationItemProgressBlock progress; + +/** Extra headers to request. Must set requestKind | IMAPMessagesRequestKindExtraHeaders */ +@property (nonatomic, copy) NSArray * extraHeaders; + +/** + Starts the asynchronous fetch operation. + + @param completionBlock Called when the operation is finished. + + - On success `error` will be nil and `messages` will be an array of MCOIMAPMessage. + `vanishedMessages` will contain the messages removed on the server if the server supports QRESYNC and if it was a sync request + + - On failure, `error` will be set with `MCOErrorDomain` as domain and an + error code available in `MCOConstants.h`, `messages` and `vanishedMessages` will be nil + + If you are not supporting QRESYNC you can safely ignore `vanishedMessages`. +*/ +- (void) start:(void (^)(NSError * error, NSArray * /* MCOIMAPMessage */ messages, MCOIndexSet * vanishedMessages))completionBlock; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOIMAPFetchNamespaceOperation.h b/MailCore.framework/Versions/A/Headers/MCOIMAPFetchNamespaceOperation.h new file mode 100644 index 0000000..5d58f05 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOIMAPFetchNamespaceOperation.h @@ -0,0 +1,39 @@ +// +// MCOIMAPFetchNamespaceOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/25/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOIMAPFETCHNAMESPACEOPERATION_H + +#define MAILCORE_MCOIMAPFETCHNAMESPACEOPERATION_H + +/** This class implements an operation to fetch any IMAP namespaces. */ + +#import + +@interface MCOIMAPFetchNamespaceOperation : MCOIMAPBaseOperation + +/** + Starts the asynchronous namespace fetch operation. + + @param completionBlock Called when the operation is finished. + + - On success `error` will be nil and `namespaces` will contain these keys: + + - `MCOIMAPNamespacePersonal` for personal namespaces, + - `MCOIMAPNamespaceOther` for other namespaces, + - `MCOIMAPNamespaceShared` for shared namespaces. + + Values of the dictionary are MCOIMAPNamespace + + - On failure, `error` will be set with `MCOErrorDomain` as domain and an + error code available in `MCOConstants.h`, `namespaces` will be nil +*/ +- (void) start:(void (^)(NSError * error, NSDictionary * namespaces))completionBlock; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOIMAPFolder.h b/MailCore.framework/Versions/A/Headers/MCOIMAPFolder.h new file mode 100644 index 0000000..048dfb5 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOIMAPFolder.h @@ -0,0 +1,34 @@ +// +// MCOIMAPFolder.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/23/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOIMAPFOLDER_H + +#define MAILCORE_MCOIMAPFOLDER_H + +/** This class represents an IMAP folder */ + +#import +#import + +@interface MCOIMAPFolder : NSObject + +/** The folder's path, like for example INBOX.Archive */ +@property (nonatomic, copy) NSString * path; + +/** It's the delimiter for each component of the path. Commonly . or / */ +@property (nonatomic, assign) char delimiter; + +/** + Any flags the folder may have, like if the folder is for Drafts, Spam, Junk, etc. Or + it could be marked with metadata like that it has no children. +*/ +@property (nonatomic, assign) MCOIMAPFolderFlag flags; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOIMAPFolderInfo.h b/MailCore.framework/Versions/A/Headers/MCOIMAPFolderInfo.h new file mode 100644 index 0000000..53ad35b --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOIMAPFolderInfo.h @@ -0,0 +1,42 @@ +// +// MCOIMAPFolderInfo.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/25/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOIMAPFOLDERINFO_H + +#define MAILCORE_MCOIMAPFOLDERINFO_H + +#import + +/* This class holds IMAP folder metadata */ + +@interface MCOIMAPFolderInfo : NSObject + +/** Create an empty instance */ ++ (MCOIMAPFolderInfo *) info; + +/** The folder's IMAP UIDNEXT value. Used to determine the uid for the next received message. */ +@property (nonatomic, assign) uint32_t uidNext; + +/** The folders IMAP UIDVALIDITY value. Must be used to determine if the server has changed assigned UIDs */ +@property (nonatomic, assign) uint32_t uidValidity; + +/** An advanced value used for doing quick flag syncs if the server supports it. The MODSEQ value. */ +@property (nonatomic, assign) uint64_t modSequenceValue; + +/** Total number of messages in the folder */ +@property (nonatomic, assign) int messageCount; + +// first uid of the unseen messages. +@property (nonatomic, assign) uint32_t firstUnseenUid; + +/** An boolean indicates that this folder or IMAP server allows to add a new permanent flags */ +@property (nonatomic, assign) BOOL allowsNewPermanentFlags; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOIMAPFolderInfoOperation.h b/MailCore.framework/Versions/A/Headers/MCOIMAPFolderInfoOperation.h new file mode 100644 index 0000000..e25016c --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOIMAPFolderInfoOperation.h @@ -0,0 +1,39 @@ +// +// MCOIMAPFolderInfoOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/25/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOIMAPFOLDERINFOOPERATION_H + +#define MAILCORE_MCOIMAPFOLDERINFOOPERATION_H + +#import + +/** + The class is used to get folder metadata (like UIDVALIDITY, UIDNEXT, etc). + @see MCOIMAPFolderInfo +*/ + +@class MCOIMAPFolderInfo; + +@interface MCOIMAPFolderInfoOperation : MCOIMAPBaseOperation + +/** + Starts the asynchronous operation. + + @param completionBlock Called when the operation is finished. + + - On success `error` will be nil and `info` will contain the folder metadata + + - On failure, `error` will be set with `MCOErrorDomain` as domain and an + error code available in `MCOConstants.h`, `info` will be nil +*/ + +- (void) start:(void (^)(NSError * error, MCOIMAPFolderInfo * info))completionBlock; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOIMAPFolderStatus.h b/MailCore.framework/Versions/A/Headers/MCOIMAPFolderStatus.h new file mode 100644 index 0000000..fedd31a --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOIMAPFolderStatus.h @@ -0,0 +1,39 @@ +// +// MCOIMAPFolderStatus.h +// mailcore2 +// +// Created by Sebastian on 6/5/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOIMAPFOLDERSTATUS_H + +#define MAILCORE_MCOIMAPFOLDERSTATUS_H + +#import + +/* This class holds IMAP folder metadata */ + +@interface MCOIMAPFolderStatus : NSObject + +/** The folder's IMAP UIDNEXT value. Used to determine the uid for the next received message. */ +@property (nonatomic, assign) uint32_t uidNext; + +/** The folders IMAP UIDVALIDITY value. Must be used to determine if the server has changed assigned UIDs */ +@property (nonatomic, assign) uint32_t uidValidity; + +/** Number of recent messages received in the folder */ +@property (nonatomic, assign) uint32_t recentCount; + +/** Number of unseen messages in the folder */ +@property (nonatomic, assign) uint32_t unseenCount; + +/** Number of messages in the folder */ +@property (nonatomic, assign) uint32_t messageCount; + +/** Highest modification sequence value for this folder. See CONDSTORE RFC 4551. */ +@property (nonatomic, assign) uint64_t setHighestModSeqValue; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOIMAPFolderStatusOperation.h b/MailCore.framework/Versions/A/Headers/MCOIMAPFolderStatusOperation.h new file mode 100644 index 0000000..2117260 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOIMAPFolderStatusOperation.h @@ -0,0 +1,39 @@ +// +// MCOIMAPFolderStatusOperation.h +// mailcore2 +// +// Created by Sebastian on 6/5/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOIMAPFOLDERSTATUSOPERATION_H + +#define MAILCORE_MCOIMAPFOLDERSTATUSOPERATION_H + +#import + +/** + The class is used to get folder metadata (like UIDVALIDITY, UIDNEXT, etc). + @see MCOIMAPFolderStatus + */ + +@class MCOIMAPFolderStatus; + +@interface MCOIMAPFolderStatusOperation : MCOIMAPBaseOperation + +/** + Starts the asynchronous operation. + + @param completionBlock Called when the operation is finished. + + - On success `error` will be nil and `status` will contain the status metadata + + - On failure, `error` will be set with `MCOErrorDomain` as domain and an + error code available in `MCOConstants.h`, `info` will be nil + */ + +- (void) start:(void (^)(NSError * error, MCOIMAPFolderStatus * status))completionBlock; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOIMAPIdentity.h b/MailCore.framework/Versions/A/Headers/MCOIMAPIdentity.h new file mode 100644 index 0000000..1690c0e --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOIMAPIdentity.h @@ -0,0 +1,42 @@ +// +// MCOIMAPIdentity.h +// mailcore2 +// +// Created by Hoa V. DINH on 8/24/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOIMAPIDENTITY_H + +#define MAILCORE_MCOIMAPIDENTITY_H + +#import + +@interface MCOIMAPIdentity : NSObject + +/** Returns a simple identity */ ++ (MCOIMAPIdentity *) identityWithVendor:(NSString *)vendor + name:(NSString *)name + version:(NSString *)version; + +/** Vendor of the IMAP client */ +@property (nonatomic, copy) NSString * vendor; + +/** Name of the IMAP client */ +@property (nonatomic, copy) NSString * name; + +/** Version of the IMAP client */ +@property (nonatomic, copy) NSString * version; + +/** All fields names of the identity of the client */ +- (NSArray *) allInfoKeys; + +/** Set a custom field in the identity */ +- (NSString *) infoForKey:(NSString *)key; + +/** Retrieve a custom field in the identity */ +- (void) setInfo:(NSString *)value forKey:(NSString *)key; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOIMAPIdentityOperation.h b/MailCore.framework/Versions/A/Headers/MCOIMAPIdentityOperation.h new file mode 100644 index 0000000..20b9fc8 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOIMAPIdentityOperation.h @@ -0,0 +1,39 @@ +// +// MCOIMAPIdentityOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/25/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOIMAPIDENTITYOPERATION_H + +#define MAILCORE_MCOIMAPIDENTITYOPERATION_H + +/** + This class implements an operation to get the servers identification info or + to send the clients identification info. Useful for bug reports and usage + statistics. + @warn Not all servers support this. +*/ + +#import + +@interface MCOIMAPIdentityOperation : MCOIMAPBaseOperation + +/** + Starts the asynchronous identity operation. + + @param completionBlock Called when the operation is finished. + + - On success `error` will be nil and `serverIdentity` will contain identifying server information. + See [RFC2971](http://tools.ietf.org/html/rfc2971) for commons dictionary keys. + + - On failure, `error` will be set with `MCOErrorDomain` as domain and an + error code available in `MCOConstants.h`, `serverIdentity` will be nil +*/ +- (void) start:(void (^)(NSError * error, NSDictionary * serverIdentity))completionBlock; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOIMAPIdleOperation.h b/MailCore.framework/Versions/A/Headers/MCOIMAPIdleOperation.h new file mode 100644 index 0000000..672a325 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOIMAPIdleOperation.h @@ -0,0 +1,40 @@ +// +// MCOIMAPIdleOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/25/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOIMAPIDLEOPERATION_H + +#define MAILCORE_MCOIMAPIDLEOPERATION_H + +/** + This class implements an IMAP IDLE. IDLE is used to keep a connection + open with the server so that new messages can be pushed to the client. + See [RFC2177](http://tools.ietf.org/html/rfc2177) +*/ + +#import + +@interface MCOIMAPIdleOperation : MCOIMAPBaseOperation + +/** Stop the current IDLE session */ +- (void) interruptIdle; + +/** + Starts IDLE + + @param completionBlock Called when the IDLE times out, errors out or detects a change + + - On success `error` will be nil + + - On failure, `error` will be set with `MCOErrorDomain` as domain and an + error code available in `MCOConstants.h` +*/ +- (void) start:(void (^)(NSError * error))completionBlock; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOIMAPMessage.h b/MailCore.framework/Versions/A/Headers/MCOIMAPMessage.h new file mode 100644 index 0000000..7ca40b9 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOIMAPMessage.h @@ -0,0 +1,81 @@ +// +// MCOIMAPMessage.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/23/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOIMAPMESSAGE_H + +#define MAILCORE_MCOIMAPMESSAGE_H + +/** + This represents an IMAP message. + + If you fetched the MIME structure of the message, you can fetch + efficiently the content of the message by fetching only the parts + that you need to show it. + + For example, you could fetch only the text parts to show the summary + of the message, using [MCOIMAPSession fetchMessageAttachmentByUIDOperationWithFolder:uid:partID:encoding:] + + You can also decide to fetch entirely the message using + [MCOIMAPSession fetchMessageByUIDOperationWithFolder:uid:] +*/ + +#import +#import + +@protocol MCOHTMLRendererIMAPDelegate; + +@interface MCOIMAPMessage : MCOAbstractMessage + +/** IMAP UID of the message. */ +@property (nonatomic, assign) uint32_t uid; + +/* Size of the entire message */ +@property (nonatomic, assign) uint32_t size; + +/** Flags of the message, like if it is deleted, read, starred etc */ +@property (nonatomic, assign) MCOMessageFlag flags; + +/** The contents of the message flags when it was fetched from the server */ +@property (nonatomic, assign) MCOMessageFlag originalFlags; + +/** Flag keywords of the message, mostly custom flags */ +@property (nonatomic, copy) NSArray * /* NSString */ customFlags; + +/** It's the last modification sequence value of the message synced from the server. See RFC4551 */ +@property (nonatomic, assign) uint64_t modSeqValue; + +/** Main MIME part of the message */ +@property (nonatomic, retain) MCOAbstractPart * mainPart; + +/** All Gmail labels of the message */ +@property (nonatomic, copy) NSArray * /* NSString */ gmailLabels; + +/** Gmail message ID of the message */ +@property (nonatomic, assign) uint64_t gmailMessageID; + +/** Gmail thread ID of the message */ +@property (nonatomic, assign) uint64_t gmailThreadID; + +/** + Returns the part with the given part identifier. + @param partID A part identifier looks like 1.2.1 +*/ +- (MCOAbstractPart *) partForPartID:(NSString *)partID; + +/** + HTML rendering of the message to be displayed in a web view. + The delegate should implement at least + [MCOAbstractMessage:dataForIMAPPart:folder:] + so that the complete HTML rendering can take place. +*/ +- (NSString *) htmlRenderingWithFolder:(NSString *)folder + delegate:(id )delegate; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOIMAPMessagePart.h b/MailCore.framework/Versions/A/Headers/MCOIMAPMessagePart.h new file mode 100644 index 0000000..c455d33 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOIMAPMessagePart.h @@ -0,0 +1,24 @@ +// +// MCOIMAPMessagePart.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/23/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOIMAPMESSAGEPART_H + +#define MAILCORE_MCOIMAPMESSAGEPART_H + +/** Represents a message part. */ + +#import + +@interface MCOIMAPMessagePart : MCOAbstractMessagePart + +/** A part identifier is of the form 1.2.1*/ +@property (nonatomic, copy) NSString * partID; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOIMAPMessageRenderingOperation.h b/MailCore.framework/Versions/A/Headers/MCOIMAPMessageRenderingOperation.h new file mode 100644 index 0000000..2c7f56d --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOIMAPMessageRenderingOperation.h @@ -0,0 +1,35 @@ +// +// MCOIMAPMessageRenderingOperation.h +// mailcore2 +// +// Created by Paul Young on 07/07/2013. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOIMAPMESSAGERENDERINGOPERATION_H + +#define MAILCORE_MCOIMAPMESSAGERENDERINGOPERATION_H + +#import + +/** + The class is used to get the HTML string of a message. + */ + +@interface MCOIMAPMessageRenderingOperation : MCOIMAPBaseOperation + +/** + Starts the asynchronous operation. + + @param completionBlock Called when the operation is finished. + + - On success `error` will be nil and `htmlString` will contain the message + + - On failure, `error` will be set and `htmlString` will be nil + */ + +- (void) start:(void (^)(NSString * htmlString, NSError * error))completionBlock; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOIMAPMultipart.h b/MailCore.framework/Versions/A/Headers/MCOIMAPMultipart.h new file mode 100644 index 0000000..c083f42 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOIMAPMultipart.h @@ -0,0 +1,24 @@ +// +// MCOIMAPMultipart.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/23/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOIMAPMULTIPART_H + +#define MAILCORE_MCOIMAPMULTIPART_H + +/** Represents the a multipart retrieved from IMAP */ + +#import + +@interface MCOIMAPMultipart : MCOAbstractMultipart + +/** A part identifier looks like 1.2.1 */ +@property (nonatomic, copy) NSString * partID; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOIMAPNamespace.h b/MailCore.framework/Versions/A/Headers/MCOIMAPNamespace.h new file mode 100644 index 0000000..3e842aa --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOIMAPNamespace.h @@ -0,0 +1,55 @@ +// +// MCOIMAPNamespace.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/23/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOIMAPNAMESPACE_H + +#define MAILCORE_MCOIMAPNAMESPACE_H + +/** Represents an IMAP namespace */ + +#import + +@class MCOIMAPNamespace; + +@interface MCOIMAPNamespace : NSObject + +/** + Returns a simple namespace with only one item. +*/ ++ (MCOIMAPNamespace *) namespaceWithPrefix:(NSString *)prefix delimiter:(char)delimiter; + +/** Returns the prefix of the main item of this namespace. */ +- (NSString *) mainPrefix; + +/** Returns the path delimiter of the main item of this namespace */ +- (char) mainDelimiter; + +/** Returns the list of prefixes of this namespace. */ +- (NSArray * /* NSString */) prefixes; + +/** + Returns the folder path for the given list of path components in the context + of the main item of the namespace. +*/ +- (NSString *) pathForComponents:(NSArray *)components; + +/** + Returns the folder path for the given list of path components and a prefix. + It will use the best item matching the prefix to compute the path. +*/ +- (NSString *) pathForComponents:(NSArray *)components prefix:(NSString *)prefix; + +/** Returns the components given a folder path. */ +- (NSArray * /* NSString */) componentsFromPath:(NSString *)path; + +/** Returns YES if the namespace contains the given folder path. */ +- (BOOL) containsFolderPath:(NSString *)path; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOIMAPNamespaceItem.h b/MailCore.framework/Versions/A/Headers/MCOIMAPNamespaceItem.h new file mode 100644 index 0000000..64ae3c5 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOIMAPNamespaceItem.h @@ -0,0 +1,36 @@ +// +// MCOIMAPNamespaceItem.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/23/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOIMAPNAMESPACEITEM_H + +#define MAILCORE_MCOIMAPNAMESPACEITEM_H + +/** Represents a namespace item */ + +#import + +@interface MCOIMAPNamespaceItem : NSObject + +/** This is the prefix for this namespace item */ +@property (nonatomic, copy) NSString * prefix; + +/** This is the delimiter of the path for this namespace item */ +@property (nonatomic, assign) char delimiter; + +/** Returns folder path for given path components in the context of this namespace item */ +- (NSString *) pathForComponents:(NSArray *)components; + +/** Returns components for the given path in the context of this namespace */ +- (NSArray * /* NSString */) componentsForPath:(NSString *)path; + +/** Returns YES if the namespace contains this folder path */ +- (BOOL) containsFolder:(NSString *)folder; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOIMAPOperation.h b/MailCore.framework/Versions/A/Headers/MCOIMAPOperation.h new file mode 100644 index 0000000..f8003c0 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOIMAPOperation.h @@ -0,0 +1,33 @@ +// +// MCOIMAPOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/23/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOIMAPOPERATION_H + +#define MAILCORE_MCOIMAPOPERATION_H + +/** This class implements a generic IMAP operation */ + +#import + +@interface MCOIMAPOperation : MCOIMAPBaseOperation + +/** + Starts the asynchronous append operation. + + @param completionBlock Called when the operation is finished. + + - On success `error` will be nil + + - On failure, `error` will be set with `MCOErrorDomain` as domain and an + error code available in MCOConstants.h, +*/ +- (void) start:(void (^)(NSError * error))completionBlock; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOIMAPPart.h b/MailCore.framework/Versions/A/Headers/MCOIMAPPart.h new file mode 100644 index 0000000..660113b --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOIMAPPart.h @@ -0,0 +1,38 @@ +// +// MCOIMAPPart.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/23/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOIMAPABSTRACTPART_H + +#define MAILCORE_MCOIMAPABSTRACTPART_H + +#import + +#import + +/** Represents a single IMAP message part */ + +@interface MCOIMAPPart : MCOAbstractPart + +/** A part identifier looks like 1.2.1 */ +@property (nonatomic, copy) NSString * partID; + +/** The size of the single part in bytes */ +@property (nonatomic, nonatomic) unsigned int size; + +/** It's the encoding of the single part */ +@property (nonatomic, nonatomic) MCOEncoding encoding; + +/** + Returns the decoded size of the part. + For example, for a part that's encoded with base64, it will return actual_size * 3/4. +*/ +- (unsigned int) decodedSize; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOIMAPQuotaOperation.h b/MailCore.framework/Versions/A/Headers/MCOIMAPQuotaOperation.h new file mode 100644 index 0000000..c0463bb --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOIMAPQuotaOperation.h @@ -0,0 +1,15 @@ +// +// MCOIMAPQuotaOperation.h +// mailcore2 +// +// Created by Petro Korenev on 8/2/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#import "MCOIMAPBaseOperation.h" + +@interface MCOIMAPQuotaOperation : MCOIMAPBaseOperation + +- (void) start:(void (^)(NSError * error, NSUInteger usage, NSUInteger limit))completionBlock; + +@end diff --git a/MailCore.framework/Versions/A/Headers/MCOIMAPSearchExpression.h b/MailCore.framework/Versions/A/Headers/MCOIMAPSearchExpression.h new file mode 100644 index 0000000..51688dc --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOIMAPSearchExpression.h @@ -0,0 +1,356 @@ +// +// MCOIMAPSearchExpression.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/25/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOIMAPSEARCHEXPRESSION_H + +#define MAILCORE_MCOIMAPSEARCHEXPRESSION_H + +/** Used to construct an IMAP search query */ + +#import +#import +#import + +@interface MCOIMAPSearchExpression : NSObject + +/** + Creates a search expression that returns all UIDS for the mailbox + + Example: + + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchAll] +*/ ++ (MCOIMAPSearchExpression *) searchAll; + +/** + Creates a search expression that matches the sender of an email. + + Example: + + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchFrom:@"laura@etpan.org"] +*/ ++ (MCOIMAPSearchExpression *) searchFrom:(NSString *)value; + +/** + Creates a search expression that matches any recipient of an email. + + Example: + + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchRecipient:@"ngan@etpan.org"] + **/ ++ (MCOIMAPSearchExpression *) searchRecipient:(NSString *)value; + +/** + Creates a search expression that matches on the receiver (to) of an email. Useful to check whether the mail is directly addressed to the receiver. + + Example: + + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchTo:@"ngan@etpan.org"] +**/ ++ (MCOIMAPSearchExpression *) searchTo:(NSString *)value; + +/** + Creates a search expression that matches on the cc of an email. Useful to check whether the mail is addressed to the receiver as cc. + + Example: + + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchCc:@"ngan@etpan.org"] + **/ ++ (MCOIMAPSearchExpression *) searchCc:(NSString *)value; + +/** + Creates a search expression that matches on the bcc field of an email. Useful to check whether the mail is addressed to the receiver as bcc. + + Example: + + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchBcc:@"ngan@etpan.org"] + **/ ++ (MCOIMAPSearchExpression *) searchBcc:(NSString *)value; + +/* + Creates a search expression that matches the subject of an email. + + Example: + + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchSubject:@"airline"] +**/ ++ (MCOIMAPSearchExpression *) searchSubject:(NSString *)value; + +/** + Creates a search expression that matches the content of an email, including the headers. + + Example: + + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchContent:@"meeting"] +*/ ++ (MCOIMAPSearchExpression *) searchContent:(NSString *)value; + +/** + Creates a search expression that matches the content of an email, excluding the headers. + + Example: + + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchBody:@"building"] + */ ++ (MCOIMAPSearchExpression *) searchBody:(NSString *)value; + +/** + Creates a search expression that matches the uids specified. + + Example: + + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchUids:uids] + **/ ++ (MCOIMAPSearchExpression *) searchUIDs:(MCOIndexSet *) uids; + +/** + Creates a search expression that matches the content of a specific header. + + Example: + + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchHeader:@"List-Id" value:@"shoes"] +**/ ++ (MCOIMAPSearchExpression *) searchHeader:(NSString *)header value:(NSString *)value; + +/** + Creates a search expression that matches messages with the Read flag. + + Example: + + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchRead] + **/ ++ (MCOIMAPSearchExpression *) searchRead; + +/** + Creates a search expression that matches messages without the Read flag. + + Example: + + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchUnread] + **/ ++ (MCOIMAPSearchExpression *) searchUnread; + +/** + Creates a search expression that matches messages that have been flagged. + + Example: + + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchFlagged] + **/ ++ (MCOIMAPSearchExpression *) searchFlagged; + +/** + Creates a search expression that matches messages that haven't been flagged. + + Example: + + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchUnflagged] + **/ ++ (MCOIMAPSearchExpression *) searchUnflagged; + +/** + Creates a search expression that matches messages that have the answered flag set. + + Example: + + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchAnswered] + **/ ++ (MCOIMAPSearchExpression *) searchAnswered; + +/** + Creates a search expression that matches messages that don't have the answered flag set.. + + Example: + + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchUnanswered] + **/ ++ (MCOIMAPSearchExpression *) searchUnanswered; + +/** + Creates a search expression that matches draft messages. + + Example: + + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchDraft] + **/ ++ (MCOIMAPSearchExpression *) searchDraft; + +/** + Creates a search expression that matches messages that aren't drafts. + + Example: + + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchUndraft] + **/ ++ (MCOIMAPSearchExpression *) searchUndraft; + +/** + Creates a search expression that matches messages that are deleted. + + Example: + + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchDeleted] + **/ ++ (MCOIMAPSearchExpression *) searchDeleted; + +/** + Creates a search expression that matches messages that are spam. + + Example: + + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchSpam] + **/ ++ (MCOIMAPSearchExpression *) searchSpam; + +/** + Creates a search expression that matches messages sent before a date. + + Example: + + NSDate *yesterday = [NSDate dateWithTimeIntervalSinceNow:-(60.0 * 60.0 * 24.0)]; + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchBeforeDate:yesterday] + **/ ++ (MCOIMAPSearchExpression *) searchBeforeDate:(NSDate *)date; + +/** + Creates a search expression that matches messages sent on a date. + + Example: + + NSDate *now = [NSDate date]; + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchOnDate:now] + **/ ++ (MCOIMAPSearchExpression *) searchOnDate:(NSDate *)date; + +/** + Creates a search expression that matches messages sent since a date. + + Example: + + NSDate *now = [NSDate date]; + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchSinceDate:now] + **/ ++ (MCOIMAPSearchExpression *) searchSinceDate:(NSDate *)date; + +/** + Creates a search expression that matches messages received before a date. + + Example: + + NSDate *yesterday = [NSDate dateWithTimeIntervalSinceNow:-(60.0 * 60.0 * 24.0)]; + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchBeforeReceivedDate:yesterday] + **/ ++ (MCOIMAPSearchExpression *) searchBeforeReceivedDate:(NSDate *)date; + +/** + Creates a search expression that matches messages received on a date. + + Example: + + NSDate *now = [NSDate date]; + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchOnReceivedDate:now] + **/ ++ (MCOIMAPSearchExpression *) searchOnReceivedDate:(NSDate *)date; + +/** + Creates a search expression that matches messages received since a date. + + Example: + + NSDate *yesterday = [NSDate dateWithTimeIntervalSinceNow:-(60.0 * 60.0 * 24.0)]; + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchSinceReceivedDate:yesterday] + **/ ++ (MCOIMAPSearchExpression *) searchSinceReceivedDate:(NSDate *)date; + +/** + Creates a search expression that matches messages larger than a given size in bytes. + + Example: + + uint32_t minSize = 1024 * 10; // 10 KB + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchSizeLargerThan:minSize] + **/ ++ (MCOIMAPSearchExpression *) searchSizeLargerThan:(uint32_t)size; + +/** + Creates a search expression that matches messages smaller than a given size in bytes. + + Example: + + uint32_t maxSize = 1024 * 10; // 10 KB + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchSizeSmallerThan:maxSize] + **/ ++ (MCOIMAPSearchExpression *) searchSizeSmallerThan:(uint32_t)size; + +/** + Creates a search expression that matches emails with the given gmail thread id + + Example: + + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchGmailThreadID:aThreadID] + */ ++ (MCOIMAPSearchExpression *) searchGmailThreadID:(uint64_t)number; + + +/** + Creates a search expression that matches emails with the given gmail message id + + Example: + + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchGmailMessageID:aMessageID] + */ ++ (MCOIMAPSearchExpression *) searchGmailMessageID:(uint64_t)number; + +/** + Creates a search expression that gets emails that match a gmail raw search + expression. + + Example: + + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchGmailRaw:@"from:bill has:attachment filename:cal meeting schedule"] + */ ++ (MCOIMAPSearchExpression *) searchGmailRaw:(NSString *)expr; + + +/** + Creates a search expression that's a disjunction of two search expressions. + + Example: + + MCOIMAPSearchExpression * exprFrom = [MCOIMAPSearchExpression searchFrom:@"laura@etpan.org"] + MCOIMAPSearchExpression * exprSubject = [MCOIMAPSearchExpression searchContent:@"meeting"] + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchAnd:exprFrom other:exprSubject]; +**/ + ++ (MCOIMAPSearchExpression *) searchAnd:(MCOIMAPSearchExpression *)expression other:(MCOIMAPSearchExpression *)other; +/** + Creates a search expression that's a conjunction of two search expressions. + + Example: + + MCOIMAPSearchExpression * exprFrom = [MCOIMAPSearchExpression searchFrom:@"laura@etpan.org"] + MCOIMAPSearchExpression * exprOtherFrom = [MCOIMAPSearchExpression searchRecipient:@"ngan@etpan.org"] + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchOr:exprFrom exprOtherFrom]; +*/ ++ (MCOIMAPSearchExpression *) searchOr:(MCOIMAPSearchExpression *)expression other:(MCOIMAPSearchExpression *)other; + +/** + Creates a search expression that matches when the argument is not matched. + + Example: + + MCOIMAPSearchExpression * exprSubject = [MCOIMAPSearchExpression searchSubject:@"airline"] + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchNot:exprSubject]; + The expression will match when the subject does not contain the word airline + + */ ++ (MCOIMAPSearchExpression *) searchNot:(MCOIMAPSearchExpression *)expression; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOIMAPSearchOperation.h b/MailCore.framework/Versions/A/Headers/MCOIMAPSearchOperation.h new file mode 100644 index 0000000..1ec3c95 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOIMAPSearchOperation.h @@ -0,0 +1,36 @@ +// +// MCOIMAPSearchOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/25/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOSEARCHOPERATION_H + +#define MAILCORE_MCOSEARCHOPERATION_H + +/** This class runs an IMAP search operation */ + +#import + +@class MCOIndexSet; + +@interface MCOIMAPSearchOperation : MCOIMAPBaseOperation + +/** + Starts the asynchronous search operation. + + @param completionBlock Called when the operation is finished. + + - On success `error` will be nil and `searchResults` will contain the UIDs of any matching messages + + - On failure, `error` will be set with `MCOErrorDomain` as domain and an + error code available in MCOConstants.h, `searchResult` will be nil +*/ + +- (void) start:(void (^)(NSError * error, MCOIndexSet * searchResult))completionBlock; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOIMAPSession.h b/MailCore.framework/Versions/A/Headers/MCOIMAPSession.h new file mode 100755 index 0000000..7a35b7e --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOIMAPSession.h @@ -0,0 +1,711 @@ +// +// MCOIMAPSession.h +// mailcore2 +// +// Created by Matt Ronge on 1/31/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOIMAPSESSION_H + +#define MAILCORE_MCOIMAPSESSION_H + +#import +#import + +@class MCOIMAPFetchFoldersOperation; +@class MCOIMAPOperation; +@class MCOIMAPNamespace; +@class MCOIMAPFolderInfoOperation; +@class MCOIMAPFolderStatusOperation; +@class MCOIMAPAppendMessageOperation; +@class MCOIMAPCopyMessagesOperation; +@class MCOIndexSet; +@class MCOIMAPFetchMessagesOperation; +@class MCOIMAPFetchContentOperation; +@class MCOIMAPSearchOperation; +@class MCOIMAPIdleOperation; +@class MCOIMAPFetchNamespaceOperation; +@class MCOIMAPSearchExpression; +@class MCOIMAPIdentityOperation; +@class MCOIMAPCapabilityOperation; +@class MCOIMAPQuotaOperation; +@class MCOIMAPMessageRenderingOperation; +@class MCOIMAPMessage; +@class MCOIMAPIdentity; + +/** + This is the main IMAP class from which all operations are created + + After calling a method that returns an operation you must call start: on the instance + to begin the operation. +*/ + +@interface MCOIMAPSession : NSObject + +/** This is the hostname of the IMAP server to connect to. */ +@property (nonatomic, copy) NSString *hostname; + +/** This is the port of the IMAP server to connect to. */ +@property (nonatomic, assign) unsigned int port; + +/** This is the username of the account. */ +@property (nonatomic, copy) NSString *username; + +/** This is the password of the account. */ +@property (nonatomic, copy) NSString *password; + +/** This is the OAuth2 token. */ +@property (nonatomic, copy) NSString *OAuth2Token; + +/** + This is the authentication type to use to connect. + `MCOAuthTypeSASLNone` means that it uses the clear-text is used (and is the default). + @warning *Important*: Over an encrypted connection like TLS, the password will still be secure +*/ +@property (nonatomic, assign) MCOAuthType authType; + +/** + This is the encryption type to use. + See MCOConnectionType for more information. +*/ +@property (nonatomic, assign) MCOConnectionType connectionType; + +/** This is the timeout of the connection. */ +@property (nonatomic, assign) NSTimeInterval timeout; + +/** When set to YES, the connection will fail if the certificate is incorrect. */ +@property (nonatomic, assign, getter=isCheckCertificateEnabled) BOOL checkCertificateEnabled; + +/** When set to YES, VoIP capability will be enabled on the IMAP connection on iOS */ +@property (nonatomic, assign, getter=isVoIPEnabled) BOOL voIPEnabled; + +/** The default namespace. */ +@property (nonatomic, strong) MCOIMAPNamespace * defaultNamespace; + +/** The identity of the IMAP client. */ +@property (nonatomic, strong, readonly) MCOIMAPIdentity * clientIdentity; + +/** The identity of the IMAP server. */ +@property (nonatomic, strong, readonly) MCOIMAPIdentity * serverIdentity; + +/** Display name of the Gmail user. It will be nil if it's not a Gmail server. */ +@property (nonatomic, copy, readonly) NSString * gmailUserDisplayName; + +/** + When set to YES, the session is allowed open to open several connections to the same folder. + @warning Some older IMAP servers don't like this +*/ +@property (nonatomic, assign) BOOL allowsFolderConcurrentAccessEnabled; + +/** + Maximum number of connections to the server allowed. +*/ +@property (nonatomic, assign) unsigned int maximumConnections; + +/** + Sets logger callback. The network traffic will be sent to this block. + + [session setConnectionLogger:^(void * connectionID, MCOConnectionLogType type, NSData * data) { + NSLog(@"%@", [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease]); + // ... + }]; +*/ +@property (nonatomic, copy) MCOConnectionLogger connectionLogger; + +/** This property provides some hints to MCOIMAPSession about where it's called from. + It will make MCOIMAPSession safe. It will also set all the callbacks of operations to run on this given queue. + Defaults to the main queue. + This property should be used only if there's performance issue using MCOIMAPSession in the main thread. */ +#if OS_OBJECT_USE_OBJC +@property (nonatomic, retain) dispatch_queue_t dispatchQueue; +#else +@property (nonatomic, assign) dispatch_queue_t dispatchQueue; +#endif + +/** + The value will be YES when asynchronous operations are running, else it will return NO. +*/ +@property (nonatomic, assign, readonly, getter=isOperationQueueRunning) BOOL operationQueueRunning; + +/** + Sets operation running callback. It will be called when operations start or stop running. + + [session setOperationQueueRunningChangeBlock:^{ + if ([session isOperationQueueRunning]) { + ... + } + else { + ... + } + }]; +*/ +@property (nonatomic, copy) MCOOperationQueueRunningChangeBlock operationQueueRunningChangeBlock; + +/** + Cancel all operations + */ +- (void) cancelAllOperations; + +/** @name Folder Operations */ + +/** + Returns an operation that retrieves folder metadata (like UIDNext) + + MCOIMAPFolderInfoOperation * op = [session folderInfoOperation:@"INBOX"]; + [op start:^(NSError *error, MCOIMAPFolderInfo * info) { + NSLog(@"UIDNEXT: %lu", (unsigned long) [info uidNext]); + NSLog(@"UIDVALIDITY: %lu", (unsigned long) [info uidValidity]); + NSLog(@"HIGHESTMODSEQ: %llu", (unsigned long long) [info modSequenceValue]); + NSLog(@"messages count: %lu", [info messageCount]); + }]; +*/ + +- (MCOIMAPFolderInfoOperation *) folderInfoOperation:(NSString *)folder; + +/** + Returns an operation that retrieves folder status (like UIDNext - Unseen -) + + MCOIMAPFolderStatusOperation * op = [session folderStatusOperation:@"INBOX"]; + [op start:^(NSError *error, MCOIMAPFolderStatus * info) { + NSLog(@"UIDNEXT: %lu", (unsigned long) [info uidNext]); + NSLog(@"UIDVALIDITY: %lu", (unsigned long) [info uidValidity]); + NSLog(@"messages count: %lu", [info totalMessages]); + }]; + */ + +- (MCOIMAPFolderStatusOperation *) folderStatusOperation:(NSString *)folder; + +/** + Returns an operation that gets the list of subscribed folders. + + MCOIMAPFetchFoldersOperation * op = [session fetchSubscribedFoldersOperation]; + [op start:^(NSError * error, NSArray * folders) { + ... + }]; + */ + +- (MCOIMAPFetchFoldersOperation *) fetchSubscribedFoldersOperation; + +/** + Returns an operation that gets all folders + + MCOIMAPFetchFoldersOperation * op = [session fetchAllFoldersOperation]; + [op start:^(NSError * error, NSArray *folders) { + ... + }]; +*/ +- (MCOIMAPFetchFoldersOperation *) fetchAllFoldersOperation; + +/** + Creates an operation for renaming a folder + + MCOIMAPOperation * op = [session renameFolderOperation:@"my documents" otherName:@"Documents"]; + [op start:^(NSError * error) { + ... + }]; + +*/ +- (MCOIMAPOperation *) renameFolderOperation:(NSString *)folder otherName:(NSString *)otherName; + +/** + Create an operation for deleting a folder + + MCOIMAPOperation * op = [session deleteFolderOperation:@"holidays 2009"]; + [op start:^(NSError * error) { + ... + }]]; +*/ +- (MCOIMAPOperation *) deleteFolderOperation:(NSString *)folder; + +/** + Returns an operation that creates a new folder + + MCOIMAPOperation * op = [session createFolderOperation:@"holidays 2013"]; + [op start:^(NSError * error) { + ... + }]; +*/ +- (MCOIMAPOperation *) createFolderOperation:(NSString *)folder; + +/** + Returns an operation to subscribe to a folder. + + MCOIMAPOperation * op = [session createFolderOperation:@"holidays 2013"]; + [op start:^(NSError * error) { + if (error != nil) + return; + MCOIMAPOperation * op = [session subscribeFolderOperation:@"holidays 2013"]; + ... + }]; +*/ +- (MCOIMAPOperation *) subscribeFolderOperation:(NSString *)folder; + +/** + Returns an operation to unsubscribe from a folder. + + MCOIMAPOperation * op = [session unsubscribeFolderOperation:@"holidays 2009"]; + [op start:^(NSError * error) { + if (error != nil) + return; + MCOIMAPOperation * op = [session deleteFolderOperation:@"holidays 2009"] + ... + }]; +*/ +- (MCOIMAPOperation *) unsubscribeFolderOperation:(NSString *)folder; + +/** + Returns an operation to expunge a folder. + + MCOIMAPOperation * op = [session expungeOperation:@"INBOX"]; + [op start:^(NSError * error) { + ... + }]; +*/ +- (MCOIMAPOperation *) expungeOperation:(NSString *)folder; + +/** @name Message Actions */ + +/** + Returns an operation to add a message to a folder. + + MCOIMAPOperation * op = [session appendMessageOperationWithFolder:@"Sent Mail" messageData:rfc822Data flags:MCOMessageFlagNone]; + [op start:^(NSError * error, uint32_t createdUID) { + if (error == nil) { + NSLog(@"created message with UID %lu", (unsigned long) createdUID); + } + }]; +*/ +- (MCOIMAPAppendMessageOperation *)appendMessageOperationWithFolder:(NSString *)folder + messageData:(NSData *)messageData + flags:(MCOMessageFlag)flags; + +/** + Returns an operation to add a message with custom flags to a folder. + + MCOIMAPOperation * op = [session appendMessageOperationWithFolder:@"Sent Mail" messageData:rfc822Data flags:MCOMessageFlagNone customFlags:@[@"$CNS-Greeting-On"]]; + [op start:^(NSError * error, uint32_t createdUID) { + if (error == nil) { + NSLog(@"created message with UID %lu", (unsigned long) createdUID); + } + }]; + */ +- (MCOIMAPAppendMessageOperation *)appendMessageOperationWithFolder:(NSString *)folder + messageData:(NSData *)messageData + flags:(MCOMessageFlag)flags + customFlags:(NSArray *)customFlags; + +/** + Returns an operation to copy messages to a folder. + + MCOIMAPCopyMessagesOperation * op = [session copyMessagesOperationWithFolder:@"INBOX" + uids:[MCIndexSet indexSetWithIndex:456] + destFolder:@"Cocoa"]; + [op start:^(NSError * error, NSDictionary * uidMapping) { + NSLog(@"copied to folder with UID mapping %@", uidMapping); + }]; +*/ +- (MCOIMAPCopyMessagesOperation *)copyMessagesOperationWithFolder:(NSString *)folder + uids:(MCOIndexSet *)uids + destFolder:(NSString *)destFolder NS_RETURNS_NOT_RETAINED; + +/** + Returns an operation to change flags of messages. + + For example: Adds the seen flag to the message with UID 456. + + MCOIMAPOperation * op = [session storeFlagsOperationWithFolder:@"INBOX" + uids:[MCOIndexSet indexSetWithIndex:456] + kind:MCOIMAPStoreFlagsRequestKindAdd + flags:MCOMessageFlagSeen]; + [op start:^(NSError * error) { + ... + }]; +*/ +- (MCOIMAPOperation *) storeFlagsOperationWithFolder:(NSString *)folder + uids:(MCOIndexSet *)uids + kind:(MCOIMAPStoreFlagsRequestKind)kind + flags:(MCOMessageFlag)flags; +/** + Returns an operation to change flags and custom flags of messages. + + For example: Adds the seen flag and $CNS-Greeting-On flag to the message with UID 456. + + MCOIMAPOperation * op = [session storeFlagsOperationWithFolder:@"INBOX" + uids:[MCOIndexSet indexSetWithIndex:456] + kind:MCOIMAPStoreFlagsRequestKindAdd + flags:MCOMessageFlagSeen + customFlags:@["$CNS-Greeting-On"]]; + [op start:^(NSError * error) { + ... + }]; + */ +- (MCOIMAPOperation *) storeFlagsOperationWithFolder:(NSString *)folder + uids:(MCOIndexSet *)uids + kind:(MCOIMAPStoreFlagsRequestKind)kind + flags:(MCOMessageFlag)flags + customFlags:(NSArray *)customFlags; +/** + Returns an operation to change labels of messages. Intended for Gmail + + For example: Adds the label "Home" flag to the message with UID 456. + + MCOIMAPOperation * op = [session storeFlagsOperationWithFolder:@"INBOX" + uids:[MCOIndexSet indexSetWithIndex:456] + kind:MCOIMAPStoreFlagsRequestKindAdd + labels:[NSArray arrayWithObject:@"Home"]]; + [op start:^(NSError * error) { + ... + }]; +*/ +- (MCOIMAPOperation *) storeLabelsOperationWithFolder:(NSString *)folder + uids:(MCOIndexSet *)uids + kind:(MCOIMAPStoreFlagsRequestKind)kind + labels:(NSArray *)labels; + +/** @name Fetching Messages */ + +/** + Returns an operation to fetch messages by UID. + + MCOIMAPFetchMessagesOperation * op = [session fetchMessagesByUIDOperationWithFolder:@"INBOX" + requestKind:MCOIMAPMessagesRequestKindHeaders | MCOIMAPMessagesRequestKindStructure + uids:MCORangeMake(1, UINT64_MAX)]; + [op start:^(NSError * error, NSArray * messages, MCOIndexSet * vanishedMessages) { + for(MCOIMAPMessage * msg in messages) { + NSLog(@"%lu: %@", [msg uid], [msg header]); + } + }]; +*/ +- (MCOIMAPFetchMessagesOperation *) fetchMessagesByUIDOperationWithFolder:(NSString *)folder + requestKind:(MCOIMAPMessagesRequestKind)requestKind + uids:(MCOIndexSet *)uids; + +/** + Returns an operation to fetch messages by (sequence) number. + For example: show 50 most recent uids. + NSString *folder = @"INBOX"; + MCOIMAPFolderInfoOperation *folderInfo = [session folderInfoOperation:folder]; + + [folderInfo start:^(NSError *error, MCOIMAPFolderInfo *info) { + int numberOfMessages = 50; + numberOfMessages -= 1; + MCOIndexSet *numbers = [MCOIndexSet indexSetWithRange:MCORangeMake([info messageCount] - numberOfMessages, numberOfMessages)]; + + MCOIMAPFetchMessagesOperation *fetchOperation = [session fetchMessagesByNumberOperationWithFolder:folder + requestKind:MCOIMAPMessagesRequestKindUid + numbers:numbers]; + + [fetchOperation start:^(NSError *error, NSArray *messages, MCOIndexSet *vanishedMessages) { + for (MCOIMAPMessage * message in messages) { + NSLog(@"%u", [message uid]); + } + }]; + }]; +*/ +- (MCOIMAPFetchMessagesOperation *) fetchMessagesByNumberOperationWithFolder:(NSString *)folder + requestKind:(MCOIMAPMessagesRequestKind)requestKind + numbers:(MCOIndexSet *)numbers; + +/** + Returns an operation to sync the last changes related to the given message list given a modSeq. + + MCOIMAPFetchMessagesOperation * op = [session syncMessagesByUIDWithFolder:@"INBOX" + requestKind:MCOIMAPMessagesRequestKindUID + uids:MCORangeMake(1, UINT64_MAX) + modSeq:lastModSeq]; + [op start:^(NSError * error, NSArray * messages, MCOIndexSet * vanishedMessages) { + NSLog(@"added or modified messages: %@", messages); + NSLog(@"deleted messages: %@", vanishedMessages); + }]; + +@warn *Important*: This is only for servers that support Conditional Store. See [RFC4551](http://tools.ietf.org/html/rfc4551) +vanishedMessages will be set only for servers that support QRESYNC. See [RFC5162](http://tools.ietf.org/html/rfc5162) +*/ +- (MCOIMAPFetchMessagesOperation *) syncMessagesByUIDWithFolder:(NSString *)folder + requestKind:(MCOIMAPMessagesRequestKind)requestKind + uids:(MCOIndexSet *)uids + modSeq:(uint64_t)modSeq; + +/** + Returns an operation to fetch the content of a message. + @param urgent is set to YES, an additional connection to the same folder might be opened to fetch the content. + + MCOIMAPFetchContentOperation * op = [session fetchMessageByUIDOperationWithFolder:@"INBOX" uid:456 urgent:NO]; + [op start:^(NSError * error, NSData * messageData) { + MCOMessageParser * parser = [MCOMessageParser messageParserWithData:messageData] + ... + }]; +*/ +- (MCOIMAPFetchContentOperation *) fetchMessageByUIDOperationWithFolder:(NSString *)folder + uid:(uint32_t)uid + urgent:(BOOL)urgent; + +/** + Returns an operation to fetch the content of a message. + + MCOIMAPFetchContentOperation * op = [session fetchMessageByUIDOperationWithFolder:@"INBOX" uid:456]; + [op start:^(NSError * error, NSData * messageData) { + MCOMessageParser * parser = [MCOMessageParser messageParserWithData:messageData] + ... + }]; +*/ +- (MCOIMAPFetchContentOperation *) fetchMessageByUIDOperationWithFolder:(NSString *)folder + uid:(uint32_t)uid; + +/** @name Fetching Attachment Operations */ + +/** + Returns an operation to fetch an attachment. + @param urgent is set to YES, an additional connection to the same folder might be opened to fetch the content. + + MCOIMAPFetchContentOperation * op = [session fetchMessageAttachmentByUIDOperationWithFolder:@"INBOX" + uid:456 + partID:@"1.2" + encoding:MCOEncodingBase64 + urgent:YES]; + [op start:^(NSError * error, NSData * partData) { + ... + }]; +*/ +- (MCOIMAPFetchContentOperation *) fetchMessageAttachmentByUIDOperationWithFolder:(NSString *)folder + uid:(uint32_t)uid + partID:(NSString *)partID + encoding:(MCOEncoding)encoding + urgent:(BOOL)urgent; + +/** + Returns an operation to fetch an attachment. + + Example 1: + + MCOIMAPFetchContentOperation * op = [session fetchMessageAttachmentByUIDOperationWithFolder:@"INBOX" + uid:456 + partID:@"1.2" + encoding:MCOEncodingBase64]; + [op start:^(NSError * error, NSData * partData) { + ... + }]; + + Example 2: + + MCOIMAPFetchContentOperation * op = [session fetchMessageAttachmentByUIDOperationWithFolder:@"INBOX" + uid:[message uid] + partID:[part partID] + encoding:[part encoding]]; + [op start:^(NSError * error, NSData * partData) { + ... + }]; +*/ +- (MCOIMAPFetchContentOperation *) fetchMessageAttachmentByUIDOperationWithFolder:(NSString *)folder + uid:(uint32_t)uid + partID:(NSString *)partID + encoding:(MCOEncoding)encoding; + +/** @name General IMAP Actions */ + +/** + Returns an operation to wait for something to happen in the folder. + See [RFC2177](http://tools.ietf.org/html/rfc2177) for me info. + + MCOIMAPIdleOperation * op = [session idleOperationWithFolder:@"INBOX" + lastKnownUID:0]; + [op start:^(NSError * error) { + ... + }]; +*/ +- (MCOIMAPIdleOperation *) idleOperationWithFolder:(NSString *)folder + lastKnownUID:(uint32_t)lastKnownUID; + +/** + Returns an operation to fetch the list of namespaces. + + MCOIMAPFetchNamespaceOperation * op = [session fetchNamespaceOperation]; + [op start:^(NSError * error, NSDictionary * namespaces) { + if (error != nil) + return; + MCOIMAPNamespace * ns = [namespace objectForKey:MCOIMAPNamespacePersonal]; + NSString * path = [ns pathForComponents:[NSArray arrayWithObject:]]; + MCOIMAPOperation * createOp = [session createFolderOperation:foobar]; + [createOp start:^(NSError * error) { + ... + }]; + }]; +*/ +- (MCOIMAPFetchNamespaceOperation *) fetchNamespaceOperation; + +/** + Returns an operation to send the client or get the server identity. + + MCOIMAPIdentity * identity = [MCOIMAPIdentity identityWithVendor:@"Mozilla" name:@"Thunderbird" version:@"17.0.5"]; + MCOIMAPIdentityOperation * op = [session identityOperationWithClientIdentity:identity]; + [op start:^(NSError * error, MCOIMAPIdentity * serverIdentity) { + ... + }]; +*/ +- (MCOIMAPIdentityOperation *) identityOperationWithClientIdentity:(MCOIMAPIdentity *)identity; + +/** + Returns an operation that will connect to the given IMAP server without authenticating. + Useful for checking initial server capabilities. + + MCOIMAPOperation * op = [session connectOperation]; + [op start:^(NSError * error) { + ... + }]; + */ +- (MCOIMAPOperation *)connectOperation; + +/** + Returns an operation that will perform a No-Op operation on the given IMAP server. + + MCOIMAPOperation * op = [session noopOperation]; + [op start:^(NSError * error) { + ... + }]; + */ +- (MCOIMAPOperation *) noopOperation; + +/** + Returns an operation that will check whether the IMAP account is valid. + + MCOIMAPOperation * op = [session checkAccountOperation]; + [op start:^(NSError * error) { + ... + }]; +*/ + +- (MCOIMAPOperation *) checkAccountOperation; + +/** + Returns an operation to request capabilities of the server. + See MCOIMAPCapability for the list of capabilities. + + canIdle = NO; + MCOIMAPCapabilityOperation * op = [session capabilityOperation]; + [op start:^(NSError * error, MCOIndexSet * capabilities) { + if ([capabilities containsIndex:MCOIMAPCapabilityIdle]) { + canIdle = YES; + } + }]; +*/ +- (MCOIMAPCapabilityOperation *) capabilityOperation; + +- (MCOIMAPQuotaOperation *) quotaOperation; + +/** @name Search Operations */ + +/** + Returns an operation to search for messages with a simple match. + + MCOIMAPSearchOperation * op = [session searchOperationWithFolder:@"INBOX" + kind:MCOIMAPSearchKindFrom + searchString:@"laura"]; + [op start:^(NSError * error, MCOIndexSet * searchResult) { + ... + }]; +*/ +- (MCOIMAPSearchOperation *) searchOperationWithFolder:(NSString *)folder + kind:(MCOIMAPSearchKind)kind + searchString:(NSString *)searchString; + +/** + Returns an operation to search for messages. + + MCOIMAPSearchExpression * expr = [MCOIMAPSearchExpression searchFrom:@"laura@etpan.org"] + MCOIMAPSearchOperation * op = [session searchExpressionOperationWithFolder:@"INBOX" + expression:expr]; + [op start:^(NSError * error, MCOIndexSet * searchResult) { + ... + }]; +*/ +- (MCOIMAPSearchOperation *) searchExpressionOperationWithFolder:(NSString *)folder + expression:(MCOIMAPSearchExpression *)expression; + +/** @name Rendering Operations */ + +/** + Returns an operation to render the HTML version of a message to be displayed in a web view. + + MCOIMAPMessageRenderingOperation * op = [session htmlRenderingOperationWithMessage:msg + folder:@"INBOX"]; + + [op start:^(NSString * htmlString, NSError * error) { + ... + }]; +*/ +- (MCOIMAPMessageRenderingOperation *) htmlRenderingOperationWithMessage:(MCOIMAPMessage *)message + folder:(NSString *)folder; + +/** + Returns an operation to render the HTML body of a message to be displayed in a web view. + + MCOIMAPMessageRenderingOperation * op = [session htmlBodyRenderingOperationWithMessage:msg + folder:@"INBOX"]; + + [op start:^(NSString * htmlString, NSError * error) { + ... + }]; + */ +- (MCOIMAPMessageRenderingOperation *) htmlBodyRenderingOperationWithMessage:(MCOIMAPMessage *)message + folder:(NSString *)folder; + +/** + Returns an operation to render the plain text version of a message. + + MCOIMAPMessageRenderingOperation * op = [session plainTextRenderingOperationWithMessage:msg + folder:@"INBOX"]; + + [op start:^(NSString * htmlString, NSError * error) { + ... + }]; + */ +- (MCOIMAPMessageRenderingOperation *) plainTextRenderingOperationWithMessage:(MCOIMAPMessage *)message + folder:(NSString *)folder; + +/** + Returns an operation to render the plain text body of a message. + All end of line will be removed and white spaces cleaned up if requested. + This method can be used to generate the summary of the message. + + MCOIMAPMessageRenderingOperation * op = [session plainTextBodyRenderingOperationWithMessage:msg + folder:@"INBOX" + stripWhitespace:YES]; + + [op start:^(NSString * htmlString, NSError * error) { + ... + }]; + */ +- (MCOIMAPMessageRenderingOperation *) plainTextBodyRenderingOperationWithMessage:(MCOIMAPMessage *)message + folder:(NSString *)folder + stripWhitespace:(BOOL)stripWhitespace; + +/** + Returns an operation to render the plain text body of a message. + All end of line will be removed and white spaces cleaned up. + This method can be used to generate the summary of the message. + + MCOIMAPMessageRenderingOperation * op = [session plainTextBodyRenderingOperationWithMessage:msg + folder:@"INBOX"]; + + [op start:^(NSString * htmlString, NSError * error) { + ... + }]; + */ +- (MCOIMAPMessageRenderingOperation *) plainTextBodyRenderingOperationWithMessage:(MCOIMAPMessage *)message + folder:(NSString *)folder; + +/** + Returns an operation to disconnect the session. + It will disconnect all the sockets created by the session. + + MCOIMAPOperation * op = [session disconnectOperation]; + [op start:^(NSError * error) { + ... + }]; + */ +- (MCOIMAPOperation *) disconnectOperation; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOIndexSet.h b/MailCore.framework/Versions/A/Headers/MCOIndexSet.h new file mode 100644 index 0000000..3705fa3 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOIndexSet.h @@ -0,0 +1,74 @@ +// +// MCOIndexSet.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/23/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOINDEXSET_H + +#define MAILCORE_MCOINDEXSET_H + +#import + +#import + +/** similar to NSMutableIndexSet but supports int64_t. MCORange has a location (uint64_t) and length (uint64_t). */ + +@interface MCOIndexSet : NSObject + +/** Creates an empty index set.*/ ++ (MCOIndexSet *) indexSet; + +/** Creates an index set that contains a range of integers.*/ ++ (MCOIndexSet *) indexSetWithRange:(MCORange)range; + +/** Creates an index set with a single integer.*/ ++ (MCOIndexSet *) indexSetWithIndex:(uint64_t)idx; + +/** Returns the number of integers in that index set.*/ +- (unsigned int) count; + +/** Adds an integer to the index set.*/ +- (void) addIndex:(uint64_t)idx; + +/** Removes an integer from the index set.*/ +- (void) removeIndex:(uint64_t)idx; + +/** Returns YES if the index set contains the given integer.*/ +- (BOOL) containsIndex:(uint64_t)idx; + +/** Adds a range of integers to the index set.*/ +- (void) addRange:(MCORange)range; + +/** Removes a range of integers from the index set.*/ +- (void) removeRange:(MCORange)range; + +/** Removes all integers that are not in the given range.*/ +- (void) intersectsRange:(MCORange)range; + +/** Adds all indexes from an other index set to the index set.*/ +- (void) addIndexSet:(MCOIndexSet *)indexSet; + +/** Remove all indexes from an other index set from the index set.*/ +- (void) removeIndexSet:(MCOIndexSet *)indexSet; + +/** Removes all integers that are not in the given index set.*/ +- (void) intersectsIndexSet:(MCOIndexSet *)indexSet; + +/** Returns all the ranges of ths index set.*/ +- (MCORange *) allRanges; + +/** Returns the number of ranges in this index set.*/ +- (unsigned int) rangesCount; + +/** Enumerates all the indexes of the index set.*/ +- (void) enumerateIndexes:(void (^)(uint64_t idx))block; + +/** Returns an NSIndexSet from a MCOIndexSet */ +- (NSIndexSet *) nsIndexSet; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOMailProvider.h b/MailCore.framework/Versions/A/Headers/MCOMailProvider.h new file mode 100644 index 0000000..85a23a8 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOMailProvider.h @@ -0,0 +1,86 @@ +// +// MCOMailProvider.h +// mailcore2 +// +// Created by Robert Widmann on 4/28/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#import + +/** + Represents a email service provider, like for example Gmail, Yahoo, Fastmail.fm etc. +*/ + +@interface MCOMailProvider : NSObject + +@property (nonatomic, copy) NSString * identifier; + +- (id) initWithInfo:(NSDictionary *)info; + +/** + A list of ways that you can connect to the IMAP server + @return An array of MCONetService +*/ +- (NSArray * /* MCONetService */) imapServices; + +/** + A list of ways that you can connect to the SMTP server + @return An array of MCONetService +*/ +- (NSArray * /* MCONetService */) smtpServices; + +/** + A list of ways that you can connect to the POP3 server + @return An array of MCONetService +*/ +- (NSArray * /* MCONetService */) popServices; + +- (BOOL) matchEmail:(NSString *)email; +- (BOOL) matchMX:(NSString *)hostname; + +/** + Where sent mail is stored on the IMAP server + @return Returns nil if it is unknown +*/ +- (NSString *) sentMailFolderPath; + +/** + Where starred mail is stored on the IMAP server. + This only applies to some servers like Gmail + @return Returns nil if it is unknown +*/ +- (NSString *) starredFolderPath; + +/** + Where all mail or the archive folder is stored on the IMAP server + @return Returns nil if it is unknown +*/ +- (NSString *) allMailFolderPath; + +/** + Where trash is stored on the IMAP server + @return Returns nil if it is unknown +*/ +- (NSString *) trashFolderPath; + +/** + Where draft messages are stored on the IMAP server + @return Returns nil if it is unknown +*/ +- (NSString *) draftsFolderPath; + +/** + Where spam messages are stored on the IMAP server + @return Returns nil if it is unknown +*/ +- (NSString *) spamFolderPath; + +/** + Where important messages are stored on the IMAP server + This only applies to some servers, like Gmail + @return Returns nil if it is unknown +*/ +- (NSString *) importantFolderPath; + +@end diff --git a/MailCore.framework/Versions/A/Headers/MCOMailProvidersManager.h b/MailCore.framework/Versions/A/Headers/MCOMailProvidersManager.h new file mode 100644 index 0000000..09df25a --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOMailProvidersManager.h @@ -0,0 +1,51 @@ +// +// MCOMailProvidersManager.h +// mailcore2 +// +// Created by Robert Widmann on 4/28/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#import + +/** + This class is used to detect an email provider and it's associated + metadata either by MX record or by the email addresss. + + An app might want to use this during setup to limit the number of settings + a user has to input. +*/ + +@class MCOMailProvider; + +@interface MCOMailProvidersManager : NSObject + +/** The shared manager that is used for all lookups */ ++ (MCOMailProvidersManager *) sharedManager; + +/** + Given an email address will try to determine the provider + @return The email provider info or nil if it can't be determined. +*/ +- (MCOMailProvider *) providerForEmail:(NSString *)email; + +/** + Given the DNS MX record will try to determine the provider + @return The email provider info or nil if it can't be determined. +*/ +- (MCOMailProvider *) providerForMX:(NSString *)hostname; + +/** + Will return information about a provider. Useful if you already know the + provider (like if it has been determined previously) + @return The email provider info or nil if none matches +*/ +- (MCOMailProvider *) providerForIdentifier:(NSString *)identifier; + +/** + Registers the providers in the JSON file at the file path so they + can be used with MCOMailProvidersManager. + */ +- (void) registerProvidersWithFilename:(NSString *)filename; + +@end diff --git a/MailCore.framework/Versions/A/Headers/MCOMessageBuilder.h b/MailCore.framework/Versions/A/Headers/MCOMessageBuilder.h new file mode 100644 index 0000000..a52afc0 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOMessageBuilder.h @@ -0,0 +1,80 @@ +// +// MCOMessageBuilder.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/22/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOMESSAGEBUILDER_H + +#define MAILCORE_MCOMESSAGEBUILDER_H + +#import + +/** + This class will allow you to build a RFC 822 formatted message. + For example when you need to send a message using SMTP, + you need to generate first a RFC 822 formatted message. + This class will help you do that. + + MCOMessageBuilder * builder = [[MCOMessageBuilder alloc] init]; + [[builder header] setFrom:[MCOAddress addressWithDisplayName:@"Hoa V. DINH" mailbox:@"hoa@etpan.org"]; + NSArray * to = [NSArray arrayWithObject:[MCOAddress addressWithDisplayName:@"Gael Roualland" mailbox:@"gael@etpan.org"]]; + [[builder header] setTo:to]; + [[builder header] setSubject:@"A nice picture!"]; + [builder setHTMLBody:@"
Here's the message I need to send.
"]; + [builder addAttachment:[MCOAttachment attachmentWithContentsOfFile:@"/Users/foo/Pictures/image.jpg"]]; + NSData * rfc822Data = [builder data]; + +*/ + +@class MCOAttachment; +@protocol MCOHTMLRendererDelegate; + +@interface MCOMessageBuilder : MCOAbstractMessage + +/** Main HTML content of the message.*/ +@property (nonatomic, copy, setter=setHTMLBody:) NSString * htmlBody; + +/** Plain text content of the message.*/ +@property (nonatomic, copy) NSString * textBody; + +/** List of file attachments.*/ +@property (nonatomic, copy) NSArray * /* MCOAttachment */ attachments; + +/** List of related file attachments (included as cid: link in the HTML part).*/ +@property (nonatomic, copy) NSArray * /* MCOAttachment */ relatedAttachments; + +/** Prefix for the boundary identifier. Default value is nil.*/ +@property (nonatomic, copy) NSString * boundaryPrefix; + +/** Add an attachment.*/ +- (void) addAttachment:(MCOAttachment *)attachment; + +/** Add a related attachment.*/ +- (void) addRelatedAttachment:(MCOAttachment *)attachment; + +/** RFC 822 formatted message.*/ +- (NSData *) data; + +/** HTML rendering of the message to be displayed in a web view. The delegate can be nil.*/ +- (NSString *) htmlRenderingWithDelegate:(id )delegate; + +/** HTML rendering of the body of the message to be displayed in a web view.*/ +- (NSString *) htmlBodyRendering; + +/** Text rendering of the message.*/ +- (NSString *) plainTextRendering; + +/** Text rendering of the body of the message. All end of line will be removed and white spaces cleaned up. + This method can be used to generate the summary of the message.*/ +- (NSString *) plainTextBodyRendering; + +/** Text rendering of the body of the message. All end of line will be removed and white spaces cleaned up if requested. + This method can be used to generate the summary of the message.*/ +- (NSString *) plainTextBodyRenderingAndStripWhitespace:(BOOL)stripWhitespace; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOMessageHeader.h b/MailCore.framework/Versions/A/Headers/MCOMessageHeader.h new file mode 100644 index 0000000..f9bb222 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOMessageHeader.h @@ -0,0 +1,101 @@ +// +// MCOMessageHeader.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/10/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOMESSAGEHEADER_H + +#define MAILCORE_MCOMESSAGEHEADER_H + +#import + +/** This class implements common fields of a message header.*/ + +@class MCOAddress; + +@interface MCOMessageHeader : NSObject + +/** Message-ID field.*/ +@property (nonatomic, copy) NSString * messageID; + +/** Message-ID auto-generated flag.*/ +@property (nonatomic, readonly, getter=isMessageIDAutoGenerated) BOOL messageIDAutoGenerated; + +/** References field. It's an array of message-ids.*/ +@property (nonatomic, copy) NSArray * /* NSString */ references; + +/** In-Reply-To field. It's an array of message-ids.*/ +@property (nonatomic, copy) NSArray * /* NSString */ inReplyTo; + +/** Date field: sent date of the message.*/ +@property (nonatomic, strong) NSDate * date; + +/** Received date: received date of the message.*/ +@property (nonatomic, strong) NSDate * receivedDate; + +/** Sender field.*/ +@property (nonatomic, copy) MCOAddress * sender; + +/** From field: address of the sender of the message.*/ +@property (nonatomic, copy) MCOAddress * from; + +/** To field: recipient of the message. It's an array of MCOAddress.*/ +@property (nonatomic, copy) NSArray * /* MCOAddress */ to; + +/** Cc field: cc recipient of the message. It's an array of MCOAddress.*/ +@property (nonatomic, copy) NSArray * /* MCOAddress */ cc; + +/** Bcc field: bcc recipient of the message. It's an array of MCOAddress.*/ +@property (nonatomic, copy) NSArray * /* MCOAddress */ bcc; + +/** Reply-To field. It's an array of MCOAddress.*/ +@property (nonatomic, copy) NSArray * /* MCOAddress */ replyTo; + +/** Subject of the message.*/ +@property (nonatomic, copy) NSString * subject; + +/** Email user agent name: X-Mailer header.*/ +@property (nonatomic, copy) NSString * userAgent; + +/** Returns a header created from RFC 822 data.*/ ++ (MCOMessageHeader *) headerWithData:(NSData *)data; + +/** Initialize a header with RFC 822 data.*/ +- (id) initWithData:(NSData *)data; + +/** Adds a custom header.*/ +- (void) setExtraHeaderValue:(NSString *)value forName:(NSString *)name; + +/** Remove a given custom header.*/ +- (void) removeExtraHeaderForName:(NSString *)name; + +/** Returns the value of a given custom header.*/ +- (NSString *) extraHeaderValueForName:(NSString *)name; + +/** Returns an array with the names of all custom headers.*/ +- (NSArray * /* NSString */) allExtraHeadersNames; + +/** Extracted subject (also remove square brackets).*/ +- (NSString *) extractedSubject; + +/** Extracted subject (don't remove square brackets).*/ +- (NSString *) partialExtractedSubject; + +/** Fill the header using the given RFC 822 data.*/ +- (void) importHeadersData:(NSData *)data; + +/** Returns a header that can be used as a base for a reply message.*/ +- (MCOMessageHeader *) replyHeaderWithExcludedRecipients:(NSArray *)excludedRecipients; + +/** Returns a header that can be used as a base for a reply all message.*/ +- (MCOMessageHeader *) replyAllHeaderWithExcludedRecipients:(NSArray *)excludedRecipients; + +/** Returns a header that can be used as a base for a forward message.*/ +- (MCOMessageHeader *) forwardHeader; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOMessageParser.h b/MailCore.framework/Versions/A/Headers/MCOMessageParser.h new file mode 100644 index 0000000..6bbed0b --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOMessageParser.h @@ -0,0 +1,57 @@ +// +// MCOMessageParser.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/22/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOMESSAGEPARSER_H + +#define MAILCORE_MCOMESSAGEPARSER_H + +/** + This class implements a parsed message. + When the full content of a message has been fetched using POP or IMAP, + you need to parse it. +*/ + +#import + +@protocol MCOHTMLRendererDelegate; + +@interface MCOMessageParser : MCOAbstractMessage + +/** returns a parsed message from the given RFC 822 data.*/ ++ (MCOMessageParser *) messageParserWithData:(NSData *)data; + +/** data is the RFC 822 formatted message.*/ +- (id) initWithData:(NSData *)data; +- (void) dealloc; + +/** It's the main part of the message. It can be MCOMessagePart, MCOMultipart or MCOAttachment.*/ +- (MCOAbstractPart *) mainPart; + +/** data of the RFC 822 formatted message. It's the input of the parser.*/ +- (NSData *) data; + +/** HTML rendering of the message to be displayed in a web view. delegate can be nil.*/ +- (NSString *) htmlRenderingWithDelegate:(id )delegate; + +/** HTML rendering of the body of the message to be displayed in a web view.*/ +- (NSString *) htmlBodyRendering; + +/** Text rendering of the message.*/ +- (NSString *) plainTextRendering; + +/** Text rendering of the body of the message. All end of line will be removed and white spaces cleaned up. + This method can be used to generate the summary of the message.*/ +- (NSString *) plainTextBodyRendering; + +/** Text rendering of the body of the message. All end of line will be removed and white spaces cleaned up if requested. + This method can be used to generate the summary of the message.*/ +- (NSString *) plainTextBodyRenderingAndStripWhitespace:(BOOL)stripWhitespace; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOMessagePart.h b/MailCore.framework/Versions/A/Headers/MCOMessagePart.h new file mode 100644 index 0000000..5098e35 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOMessagePart.h @@ -0,0 +1,21 @@ +// +// MessagePart.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/22/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOMESSAGEPART_H + +#define MAILCORE_MCOMESSAGEPART_H + +#import + +/** Message part parsed from RFC 822 message data. */ + +@interface MCOMessagePart : MCOAbstractMessagePart + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOMultipart.h b/MailCore.framework/Versions/A/Headers/MCOMultipart.h new file mode 100644 index 0000000..1b97a13 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOMultipart.h @@ -0,0 +1,21 @@ +// +// MCOMultipart.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/22/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOMULTIPART_H + +#define MAILCORE_MCOMULTIPART_H + +#import + +/** Multipart parsed from RFC 822 message data. */ + +@interface MCOMultipart : MCOAbstractMultipart + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCONNTP.h b/MailCore.framework/Versions/A/Headers/MCONNTP.h new file mode 100644 index 0000000..980d0c3 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCONNTP.h @@ -0,0 +1,21 @@ +// +// MCONNTP.h +// mailcore2 +// +// Created by Robert Widmann on 8/13/14. +// Copyright (c) 2014 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCONNTP_H + +#define MAILCORE_MCONNTP_H + +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCONNTPDisconnectOperation.h b/MailCore.framework/Versions/A/Headers/MCONNTPDisconnectOperation.h new file mode 100644 index 0000000..7d8986b --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCONNTPDisconnectOperation.h @@ -0,0 +1,21 @@ +// +// MCONNTPDisconnectOperation.h +// mailcore2 +// +// Created by Robert Widmann on 8/13/14. +// Copyright (c) 2014 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCONNTPDICONNECTOPERATION_H + +#define MAILCORE_MCONNTPDICONNECTOPERATION_H + +#import +#import + +/* The class is used to perform a disconnect operation. */ +@interface MCONNTPDisconnectOperation : NSObject + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCONNTPFetchArticleOperation.h b/MailCore.framework/Versions/A/Headers/MCONNTPFetchArticleOperation.h new file mode 100644 index 0000000..b8bffcb --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCONNTPFetchArticleOperation.h @@ -0,0 +1,39 @@ +// +// MCONNTPFetchArticleOperation.h +// mailcore2 +// +// Created by Robert Widmann on 8/13/14. +// Copyright (c) 2014 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCONNTPFETCHARTICLEOPERATION_H + +#define MAILCORE_MCONNTPFETCHARTICLEOPERATION_H + +#import +#import + +/** Fetch a message from NNTP3 */ + +typedef void (^MCONNTPOperationProgressBlock)(unsigned int current, unsigned int maximum); + +@interface MCONNTPFetchArticleOperation : MCONNTPOperation + +/** This block will be called as data is downloaded from the network */ +@property (nonatomic, copy) MCONNTPOperationProgressBlock progress; + +/** + Starts the asynchronous fetch operation. + + @param completionBlock Called when the operation is finished. + + - On success `error` will be nil and `data` will contain the message data + + - On failure, `error` will be set with `MCOErrorDomain` as domain and an + error code available in MCOConstants.h, `data` will be nil + */ +- (void) start:(void (^)(NSError * error, NSData * messageData))completionBlock; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCONNTPFetchArticlesOperation.h b/MailCore.framework/Versions/A/Headers/MCONNTPFetchArticlesOperation.h new file mode 100644 index 0000000..35a0889 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCONNTPFetchArticlesOperation.h @@ -0,0 +1,35 @@ +// +// MCONNTPFetchArticlesOperation.h +// mailcore2 +// +// Created by Robert Widmann on 8/13/14. +// Copyright (c) 2014 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCONNTPFETCHARTICLESOPERATION_H + +#define MAILCORE_MCONNTPFETCHARTICLESOPERATION_H + +#import +#import + +@class MCOIndexSet; + +/** This is an asynchronous operation that will fetch the list of a messages on the NNTP server. */ +@interface MCONNTPFetchArticlesOperation : MCONNTPOperation + +/** + Starts the asynchronous fetch operation. + + @param completionBlock Called when the operation is finished. + + - On success `error` will be nil and `articles` will be an index set of article numbers. + + - On failure, `error` will be set with `MCOErrorDomain` as domain and an + error code available in MCOConstants.h, `messages` will be null + */ +- (void) start:(void (^)(NSError * error, MCOIndexSet * articles))completionBlock; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCONNTPFetchHeaderOperation.h b/MailCore.framework/Versions/A/Headers/MCONNTPFetchHeaderOperation.h new file mode 100644 index 0000000..63ce767 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCONNTPFetchHeaderOperation.h @@ -0,0 +1,39 @@ +// +// MCONNTPFetchHeaderOperation.h +// mailcore2 +// +// Created by Robert Widmann on 8/13/14. +// Copyright (c) 2014 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCONNTPFETCHHEADEROPERATION_H + +#define MAILCORE_MCONNTPFETCHHEADEROPERATION_H + +#import +#import + +/** + This is an asynchronous operation that will fetch the header of a message. + @See MCONNTPSession + */ + +@class MCOMessageHeader; + +@interface MCONNTPFetchHeaderOperation : MCONNTPOperation + +/** + Starts the asynchronous fetch operation. + + @param completionBlock Called when the operation is finished. + + - On success `error` will be nil and `header` will contain the message header + + - On failure, `error` will be set with `MCOErrorDomain` as domain and an + error code available in MCOConstants.h, `header` will be null + */ +- (void) start:(void (^)(NSError * error, MCOMessageHeader * header))completionBlock; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCONNTPGroupInfo.h b/MailCore.framework/Versions/A/Headers/MCONNTPGroupInfo.h new file mode 100644 index 0000000..e34445a --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCONNTPGroupInfo.h @@ -0,0 +1,27 @@ +// +// MCONNTPGroupInfo.h +// mailcore2 +// +// Created by Robert Widmann on 8/13/14. +// Copyright (c) 2014 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCONNTPGROUPINFO_H + +#define MAILCORE_MCONNTPGROUPINFO_H + +#import + +/** This is information of a message fetched by MCONNTPListNewsgroupsOperation.*/ + +@interface MCONNTPGroupInfo : NSObject + +/** The name of the news group. */ +@property (nonatomic, copy) NSString *name; + +/** The number of messages in the news group. */ +@property (nonatomic, assign) unsigned int messageCount; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCONNTPListNewsgroupsOperation.h b/MailCore.framework/Versions/A/Headers/MCONNTPListNewsgroupsOperation.h new file mode 100644 index 0000000..ea702b7 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCONNTPListNewsgroupsOperation.h @@ -0,0 +1,32 @@ +// +// MCONNTPListNewsgroupsOperation.h +// mailcore2 +// +// Created by Robert Widmann on 8/13/14. +// Copyright (c) 2014 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCONNTPLISTNEWSGROUPSOPERATION_H + +#define MAILCORE_MCONNTPLISTNEWSGROUPSOPERATION_H + +#import +#import + +@interface MCONNTPListNewsgroupsOperation : MCONNTPOperation + +/** + Starts the asynchronous fetch operation. + + @param completionBlock Called when the operation is finished. + + - On success `error` will be nil and `messages` will be an array of MCONNTPGroupInfo + + - On failure, `error` will be set with `MCOErrorDomain` as domain and an + error code available in MCOConstants.h, `messages` will be null + */ +- (void) start:(void (^)(NSError * error, NSArray * /* MCONNTPGroupInfo */ messages))completionBlock; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCONNTPOperation.h b/MailCore.framework/Versions/A/Headers/MCONNTPOperation.h new file mode 100644 index 0000000..9d4e2fc --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCONNTPOperation.h @@ -0,0 +1,37 @@ +// +// MCONNTPOperation.h +// mailcore2 +// +// Created by Robert Widmann on 8/13/14. +// Copyright (c) 2014 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCONNTPOPERATION_H + +#define MAILCORE_MCONNTPOPERATION_H + +#import +#import + +/** + This is a generic asynchronous NNTP3 operation. + @see MCONNTPSession + */ + +@interface MCONNTPOperation : MCOOperation + +/** + Starts the asynchronous operation. + + @param completionBlock Called when the operation is finished. + + - On success `error` will be nil + + - On failure, `error` will be set with `MCOErrorDomain` as domain and an + error code available in MCOConstants.h, + */ +- (void) start:(void (^)(NSError * error))completionBlock; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCONNTPSession.h b/MailCore.framework/Versions/A/Headers/MCONNTPSession.h new file mode 100644 index 0000000..6712d9e --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCONNTPSession.h @@ -0,0 +1,137 @@ +// +// MCONNTPSession.h +// mailcore2 +// +// Created by Robert Widmann on 8/13/14. +// Copyright (c) 2014 MailCore. All rights reserved. +// + +#import + +#ifndef MAILCORE_MCONNTPSESSION_H + +#define MAILCORE_MCONNTPSESSION_H + +#import + +#import + +@class MCONNTPFetchArticlesOperation; +@class MCONNTPFetchHeaderOperation; +@class MCONNTPFetchArticleOperation; +@class MCONNTPListNewsgroupsOperation; +@class MCONNTPOperation; + +/** This class implements asynchronous access to the NNTP protocol.*/ + +@interface MCONNTPSession : NSObject + +/** This is the hostname of the NNTP server to connect to.*/ +@property (nonatomic, copy) NSString * hostname; + +/** This is the port of the NNTP server to connect to.*/ +@property (nonatomic, assign) unsigned int port; + +/** This is the username of the account.*/ +@property (nonatomic, copy) NSString * username; + +/** This is the password of the account.*/ +@property (nonatomic, copy) NSString * password; + +/** This is the encryption type to use. + See MCOConnectionType for more information.*/ +@property (nonatomic, assign) MCOConnectionType connectionType; + +/** This is the timeout of the connection.*/ +@property (nonatomic, assign) NSTimeInterval timeout; + +/** When set to YES, the connection will fail if the certificate is incorrect.*/ +@property (nonatomic, assign, getter=isCheckCertificateEnabled) BOOL checkCertificateEnabled; + +/** + Sets logger callback. The network traffic will be sent to this block. + + [session setConnectionLogger:^(void * connectionID, MCOConnectionLogType type, NSData * data) { + ... + }]; + */ +@property (nonatomic, copy) MCOConnectionLogger connectionLogger; + +/** This property provides some hints to MCONNTPSession about where it's called from. + It will make MCONNTPSession safe. It will also set all the callbacks of operations to run on this given queue. + Defaults to the main queue. + This property should be used only if there's performance issue using MCONNTPSession in the main thread. */ +@property (nonatomic, assign) dispatch_queue_t dispatchQueue; + +/** @name Operations */ + +/** + Returns an operation that will fetch the list of article numbers. + + MCONNTPFetchArticlesOperation * op = [session fetchArticlesOperation]; + [op start:^(NSError * error, MCOIndexSet * articles) { + }]; + */ +- (MCONNTPFetchArticlesOperation *) fetchArticlesOperation:(NSString *)group; + +/** + Returns an operation that will fetch the header of the given message. + + MCONNTPFetchHeaderOperation * op = [session fetchHeaderOperationWithIndex:idx inGroup:@"Group"]; + [op start:^(NSError * error, MCOMessageHeader * header) { + // header is the parsed header of the message. + }]; + */ +- (MCONNTPFetchHeaderOperation *) fetchHeaderOperationWithIndex:(unsigned int)index inGroup:(NSString *)group; + +/** + Returns an operation that will fetch the content of the given message. + + MCONNTPFetchArticleOperation * op = [session fetchArticleOperationWithIndex:idx inGroup:@"Group"]; + [op start:^(NSError * error, NSData * messageData) { + // messageData is the RFC 822 formatted message data. + }]; + */ +- (MCONNTPFetchArticleOperation *) fetchArticleOperationWithIndex:(unsigned int)index inGroup:(NSString *)group; + +/** + Returns an operation that will list all available newsgroups. + + MCONNTPListNewsgroupsOperation * op = [session listAllNewsgroupsOperation]; + [op start:^(NSError * error, NSArray * subscribedGroups) { + }]; + */ +- (MCONNTPListNewsgroupsOperation *) listAllNewsgroupsOperation; + +/** + Returns an operation that will list all newsgroups subscribed to by the user. + + MCONNTPListNewsgroupsOperation * op = [session listSubscribedNewsgroupsOperation]; + [op start:^(NSError * error, NSArray * subscribedGroups) { + }]; + */ +- (MCONNTPListNewsgroupsOperation *) listSubscribedNewsgroupsOperation; + +/** + Returns an operation that will disconnect the session. + + MCONNTPOperation * op = [session disconnectOperation]; + [op start:^(NSError * error) { + ... + }]; + */ +- (MCONNTPOperation *) disconnectOperation; + +/** + Returns an operation that will check whether the NNTP account is valid. + + MCONNTPOperation * op = [session checkAccountOperation]; + [op start:^(NSError * error) { + ... + }]; + */ +- (MCONNTPOperation *) checkAccountOperation; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCONetService.h b/MailCore.framework/Versions/A/Headers/MCONetService.h new file mode 100644 index 0000000..eb198e5 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCONetService.h @@ -0,0 +1,41 @@ +// +// MCONetService.h +// mailcore2 +// +// Created by Robert Widmann on 4/28/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#import +#import + +/** + This class provides a specific way to access a given service +*/ + +@interface MCONetService : NSObject + +/** + The hostname of the server. [MCONetService hostnameWithEmail:] is recommended + instead as it can handle services with custom domains +*/ +@property (nonatomic, copy) NSString * hostname; + +/** The port number of the service */ +@property (nonatomic, assign) unsigned int port; + +/** What kind of connection type is supported, like SSL, Start TLS, Plain etc. */ +@property (nonatomic, assign) MCOConnectionType connectionType; + ++ (MCONetService *) serviceWithInfo:(NSDictionary *)info; + +- (id) initWithInfo:(NSDictionary *)info; +- (NSDictionary *) info; + +/** + If the service uses a custom domain this will return the proper hostname based + off the email address +*/ +- (NSString *) hostnameWithEmail:(NSString *)email; + +@end diff --git a/MailCore.framework/Versions/A/Headers/MCOObjectWrapper.h b/MailCore.framework/Versions/A/Headers/MCOObjectWrapper.h new file mode 100644 index 0000000..67cb45e --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOObjectWrapper.h @@ -0,0 +1,31 @@ +// +// MCOObjectWrapper.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/25/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOOBJECTWRAPPER_H + +#define MAILCORE_MCOOBJECTWRAPPER_H + +#import + +#ifdef __cplusplus +namespace mailcore { + class Object; +} +#endif + +@interface MCOObjectWrapper : NSObject + +#ifdef __cplusplus +@property (nonatomic, assign) mailcore::Object * object; + ++ (MCOObjectWrapper *) objectWrapperWithObject:(mailcore::Object *)object; +#endif + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOOperation.h b/MailCore.framework/Versions/A/Headers/MCOOperation.h new file mode 100644 index 0000000..e3aa758 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOOperation.h @@ -0,0 +1,41 @@ +// +// MCOOperation.h +// mailcore2 +// +// Created by Matt Ronge on 01/31/13. +// Copyright (c) 2013 __MyCompanyName__. All rights reserved. +// + +#ifndef MAILCORE_MCOOPERATION_H + +#define MAILCORE_MCOOPERATION_H + +#import + +@interface MCOOperation : NSObject + +/** Returns whether the operation is cancelled.*/ +@property (readonly) BOOL isCancelled; + +/** Returns whether the operation should run even if it's cancelled.*/ +@property (nonatomic, assign) BOOL shouldRunWhenCancelled; + +/** The queue this operation dispatches the callback on. Defaults to the main queue. + This property should be used only if there's performance issue creating or calling the callback + in the main thread. */ +#if OS_OBJECT_USE_OBJC +@property (nonatomic, retain) dispatch_queue_t callbackDispatchQueue; +#else +@property (nonatomic, assign) dispatch_queue_t callbackDispatchQueue; +#endif + +/** This methods is called on the main thread when the asynchronous operation is finished. + Needs to be overriden by subclasses.*/ +- (void) operationCompleted; + +/** Cancel the operation.*/ +- (void) cancel; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOPOP.h b/MailCore.framework/Versions/A/Headers/MCOPOP.h new file mode 100644 index 0000000..5a75ff4 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOPOP.h @@ -0,0 +1,20 @@ +// +// MCOPOP.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/30/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOPOP_H + +#define MAILCORE_MCOPOP_H + +#import +#import +#import +#import +#import +#import + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOPOPFetchHeaderOperation.h b/MailCore.framework/Versions/A/Headers/MCOPOPFetchHeaderOperation.h new file mode 100644 index 0000000..d4735ce --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOPOPFetchHeaderOperation.h @@ -0,0 +1,39 @@ +// +// MCOFetchHeaderOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/29/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOPOPFETCHHEADEROPERATION_H + +#define MAILCORE_MCOPOPFETCHHEADEROPERATION_H + +#import +#import + +/** + This is an asynchronous operation that will fetch the header of a message. + @See MCOPOPSession +*/ + +@class MCOMessageHeader; + +@interface MCOPOPFetchHeaderOperation : MCOPOPOperation + +/** + Starts the asynchronous fetch operation. + + @param completionBlock Called when the operation is finished. + + - On success `error` will be nil and `header` will contain the message header + + - On failure, `error` will be set with `MCOErrorDomain` as domain and an + error code available in MCOConstants.h, `header` will be null +*/ +- (void) start:(void (^)(NSError * error, MCOMessageHeader * header))completionBlock; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOPOPFetchMessageOperation.h b/MailCore.framework/Versions/A/Headers/MCOPOPFetchMessageOperation.h new file mode 100644 index 0000000..b97825c --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOPOPFetchMessageOperation.h @@ -0,0 +1,39 @@ +// +// MCOFetchMessageOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/29/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOPOPFETCHMESSAGEOPERATION_H + +#define MAILCORE_MCOPOPFETCHMESSAGEOPERATION_H + +#import +#import + +/** Fetch a message from POP3 */ + +typedef void (^MCOPOPOperationProgressBlock)(unsigned int current, unsigned int maximum); + +@interface MCOPOPFetchMessageOperation : MCOPOPOperation + +/** This block will be called as data is downloaded from the network */ +@property (nonatomic, copy) MCOPOPOperationProgressBlock progress; + +/** + Starts the asynchronous fetch operation. + + @param completionBlock Called when the operation is finished. + + - On success `error` will be nil and `data` will contain the message data + + - On failure, `error` will be set with `MCOErrorDomain` as domain and an + error code available in MCOConstants.h, `data` will be nil +*/ +- (void) start:(void (^)(NSError * error, NSData * messageData))completionBlock; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOPOPFetchMessagesOperation.h b/MailCore.framework/Versions/A/Headers/MCOPOPFetchMessagesOperation.h new file mode 100644 index 0000000..aef4908 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOPOPFetchMessagesOperation.h @@ -0,0 +1,34 @@ +// +// MCOPOPFetchMessagesOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/29/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOPOPFETCHMESSAGESOPERATION_H + +#define MAILCORE_MCOPOPFETCHMESSAGESOPERATION_H + +#import +#import + +/** This is an asynchronous operation that will fetch the list of a messages on the POP3 account. */ + +@interface MCOPOPFetchMessagesOperation : MCOPOPOperation + +/** + Starts the asynchronous fetch operation. + + @param completionBlock Called when the operation is finished. + + - On success `error` will be nil and `messages` will be an array of MCOPOPMessageInfo + + - On failure, `error` will be set with `MCOErrorDomain` as domain and an + error code available in MCOConstants.h, `messages` will be null +*/ +- (void) start:(void (^)(NSError * error, NSArray * /* MCOPOPMessageInfo */ messages))completionBlock; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOPOPMessageInfo.h b/MailCore.framework/Versions/A/Headers/MCOPOPMessageInfo.h new file mode 100644 index 0000000..416747f --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOPOPMessageInfo.h @@ -0,0 +1,31 @@ +// +// MCOPOPMessageInfo.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/30/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOPOPMESSAGEINFO_H + +#define MAILCORE_MCOPOPMESSAGEINFO_H + +#import + +/** This is information of a message fetched by MCOPOPFetchMessagesOperation.*/ + +@interface MCOPOPMessageInfo : NSObject + +/** This is the index of a given message.*/ +@property (nonatomic, assign) unsigned int index; + +/** This is the size of the given message.*/ +@property (nonatomic, assign) unsigned int size; + +/** This is the unique identifier of the message. + It can be used as a cache identifier.*/ +@property (nonatomic, copy) NSString * uid; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOPOPNoopOperation.h b/MailCore.framework/Versions/A/Headers/MCOPOPNoopOperation.h new file mode 100644 index 0000000..015a168 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOPOPNoopOperation.h @@ -0,0 +1,34 @@ +// +// MCOPOPNoopOperation.h +// mailcore2 +// +// Created by Robert Widmann on 9/24/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOPOPNOOPOPERATION_H + +#define MAILCORE_MCOPOPNOOPOPERATION_H + +#import +#import + +/** This is an asynchronous operation that will perform a No-Op on the POP3 account. */ + +@interface MCOPOPNoopOperation : MCOPOPOperation + +/** + Starts the asynchronous noop operation. + + @param completionBlock Called when the operation is finished. + + - On success `error` will be nil + + - On failure, `error` will be set with `MCOErrorDomain` as domain and an + error code available in MCOConstants.h + */ +- (void) start:(void (^)(NSError * error))completionBlock; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOPOPOperation.h b/MailCore.framework/Versions/A/Headers/MCOPOPOperation.h new file mode 100644 index 0000000..30180cc --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOPOPOperation.h @@ -0,0 +1,37 @@ +// +// MCODeleteMessagesOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/29/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOPOPOPERATION_H + +#define MAILCORE_MCOPOPOPERATION_H + +#import +#import + +/** + This is a generic asynchronous POP3 operation. + @see MCOPOPSession +*/ + +@interface MCOPOPOperation : MCOOperation + +/** + Starts the asynchronous operation. + + @param completionBlock Called when the operation is finished. + + - On success `error` will be nil + + - On failure, `error` will be set with `MCOErrorDomain` as domain and an + error code available in MCOConstants.h, +*/ +- (void) start:(void (^)(NSError * error))completionBlock; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOPOPSession.h b/MailCore.framework/Versions/A/Headers/MCOPOPSession.h new file mode 100644 index 0000000..260fe5d --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOPOPSession.h @@ -0,0 +1,155 @@ +// +// MCOPOPSession.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/29/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOPOPSESSION_H + +#define MAILCORE_MCOPOPSESSION_H + +#import + +#import + +@class MCOPOPFetchMessagesOperation; +@class MCOPOPFetchHeaderOperation; +@class MCOPOPFetchMessageOperation; +@class MCOPOPOperation; +@class MCOIndexSet; + +/** This class implements asynchronous access to the POP3 protocol.*/ + +@interface MCOPOPSession : NSObject + +/** This is the hostname of the POP3 server to connect to.*/ +@property (nonatomic, copy) NSString * hostname; + +/** This is the port of the POP3 server to connect to.*/ +@property (nonatomic, assign) unsigned int port; + +/** This is the username of the account.*/ +@property (nonatomic, copy) NSString * username; + +/** This is the password of the account.*/ +@property (nonatomic, copy) NSString * password; + +/** + This is the authentication type to use to connect. + `MCOAuthTypeSASLNone` means that it uses the clear-text is used (and is the default). + @warning *Important*: Over an encrypted connection like TLS, the password will still be secure +*/ +@property (nonatomic, assign) MCOAuthType authType; + +/** This is the encryption type to use. +See MCOConnectionType for more information.*/ +@property (nonatomic, assign) MCOConnectionType connectionType; + +/** This is the timeout of the connection.*/ +@property (nonatomic, assign) NSTimeInterval timeout; + +/** When set to YES, the connection will fail if the certificate is incorrect.*/ +@property (nonatomic, assign, getter=isCheckCertificateEnabled) BOOL checkCertificateEnabled; + +/** + Sets logger callback. The network traffic will be sent to this block. + + [session setConnectionLogger:^(void * connectionID, MCOConnectionLogType type, NSData * data) { + ... + }]; + */ +@property (nonatomic, copy) MCOConnectionLogger connectionLogger; + +/** This property provides some hints to MCOPOPSession about where it's called from. + It will make MCOPOPSession safe. It will also set all the callbacks of operations to run on this given queue. + Defaults to the main queue. + This property should be used only if there's performance issue using MCOPOPSession in the main thread. */ +#if OS_OBJECT_USE_OBJC +@property (nonatomic, retain) dispatch_queue_t dispatchQueue; +#else +@property (nonatomic, assign) dispatch_queue_t dispatchQueue; +#endif + +/** @name Operations */ + +/** + Returns an operation that will fetch the list of messages. + + MCOPOPFetchMessagesOperation * op = [session fetchMessagesOperation]; + [op start:^(NSError * error, NSArray * messages) { + // messages is an array of MCOPOPMessageInfo + // [info index] can be used as reference for a given message in the other operations. + }]; +*/ +- (MCOPOPFetchMessagesOperation *) fetchMessagesOperation; + +/** + Returns an operation that will fetch the header of the given message. + + MCOPOPFetchHeaderOperation * op = [session fetchHeaderOperationWithIndex:idx]; + [op start:^(NSError * error, MCOMessageHeader * header) { + // header is the parsed header of the message. + }]; +*/ +- (MCOPOPFetchHeaderOperation *) fetchHeaderOperationWithIndex:(unsigned int)index; + +/** + Returns an operation that will fetch the content of the given message. + + MCOPOPFetchMessageOperation * op = [session fetchMessageOperationWithIndex:idx]; + [op start:^(NSError * error, NSData * messageData) { + // messageData is the RFC 822 formatted message data. + }]; +*/ +- (MCOPOPFetchMessageOperation *) fetchMessageOperationWithIndex:(unsigned int)index; + +/** + Returns an operation that will delete the given messages. + Will disconnect when finished. + + MCOIndexSet * indexes = [MCOIndexSet indexSet]; + [indexes addIndex:1]; + [indexes addIndex:2]; + [indexes addIndex:3]; + MCOPOPOperation * op = [session deleteMessagesOperationWithIndexes:indexes]; + [op start:^(NSError * error) { + ... + }]; +*/ +- (MCOPOPOperation *) deleteMessagesOperationWithIndexes:(MCOIndexSet *)indexes; + +/** + Returns an operation that will disconnect the session. + + MCOPOPOperation * op = [session disconnectOperation]; + [op start:^(NSError * error) { + ... + }]; + */ +- (MCOPOPOperation *) disconnectOperation; + +/** + Returns an operation that will check whether the POP account is valid. + + MCOPOPOperation * op = [session checkAccountOperation]; + [op start:^(NSError * error) { + ... + }]; +*/ +- (MCOPOPOperation *) checkAccountOperation; + +/** + Returns an operation that will perform a No-Op operation. + + MCOPOPOperation * op = [session noopOperation]; + [op start:^(NSError * error) { + ... + }]; + */ +- (MCOPOPOperation *) noopOperation; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOProvider.h b/MailCore.framework/Versions/A/Headers/MCOProvider.h new file mode 100644 index 0000000..09f2cb0 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOProvider.h @@ -0,0 +1,17 @@ +// +// MCOPROVIDER.h +// mailcore2 +// +// Created by Pushkar Singh on 5/24/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef _MAILCORE__MCOPROVIDER_h +#define _MAILCORE__MCOPROVIDER_h + + +#import +#import +#import + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCORFC822.h b/MailCore.framework/Versions/A/Headers/MCORFC822.h new file mode 100644 index 0000000..ce894aa --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCORFC822.h @@ -0,0 +1,19 @@ +// +// MCORFC822.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/22/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCORFC822_H + +#define MAILCORE_MCORFC822_H + +#import +#import +#import +#import +#import + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCORange.h b/MailCore.framework/Versions/A/Headers/MCORange.h new file mode 100644 index 0000000..fa6d4ae --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCORange.h @@ -0,0 +1,77 @@ +// +// MCORange.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/24/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCORANGE_H + +#define MAILCORE_MCORANGE_H + +#import + +#ifdef __cplusplus +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +@class MCOIndexSet; + +typedef struct { + /** first integer of the range.*/ + uint64_t location; + + /** length of the range.*/ + uint64_t length; +} MCORange; + +/** Constants for an emtpy range.*/ +extern MCORange MCORangeEmpty; + +/** Returns a new range given a location and length.*/ +MCORange MCORangeMake(uint64_t location, uint64_t length); + +/** Returns an index set that is the result of sustracting a range from a range.*/ +MCOIndexSet * MCORangeRemoveRange(MCORange range1, MCORange range2); + +/** Returns an index set that is the result of the union a range from a range.*/ +MCOIndexSet * MCORangeUnion(MCORange range1, MCORange range2); + +#ifdef __cplusplus + +/** Returns a C++ range from an Objective-C range.*/ +mailcore::Range MCORangeToMCRange(MCORange range); + +/** Returns an Objective-C range from a C++ range.*/ +MCORange MCORangeWithMCRange(mailcore::Range range); + +#endif + +/** Returns the intersection of two ranges.*/ +MCORange MCORangeIntersection(MCORange range1, MCORange range2); + +/** Returns YES if two given ranges have an intersection.*/ +BOOL MCORangeHasIntersection(MCORange range1, MCORange range2); + +/** Returns left bound of a range.*/ +uint64_t MCORangeLeftBound(MCORange range); + +/** Returns right bound of a range.*/ +uint64_t MCORangeRightBound(MCORange range); + +/** Returns a serializable form (NSString) of a range */ +NSString * MCORangeToString(MCORange range); + +/** Create a range from a serializable form (NSString). */ +MCORange MCORangeFromString(NSString * rangeString); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOSMTP.h b/MailCore.framework/Versions/A/Headers/MCOSMTP.h new file mode 100644 index 0000000..49d01de --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOSMTP.h @@ -0,0 +1,17 @@ +// +// MCOSMTP.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/29/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOSMTP_H + +#define MAILCORE_MCOSMTP_H + +#import +#import +#import + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOSMTPOperation.h b/MailCore.framework/Versions/A/Headers/MCOSMTPOperation.h new file mode 100644 index 0000000..7b92148 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOSMTPOperation.h @@ -0,0 +1,33 @@ +// +// MCOSMTPCheckAccountOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/29/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOSMTPOPERATION_H + +#define MAILCORE_MCOSMTPOPERATION_H + +#import + +/** This is an asynchronous SMTP operation, used for sending messages. */ + +@interface MCOSMTPOperation : MCOOperation + +/** + Starts the asynchronous operation. + + @param completionBlock Called when the operation is finished. + + - On success `error` will be nil + + - On failure, `error` will be set with `MCOErrorDomain` as domain and an + error code available in MCOConstants.h, +*/ +- (void) start:(void (^)(NSError * error))completionBlock; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOSMTPSendOperation.h b/MailCore.framework/Versions/A/Headers/MCOSMTPSendOperation.h new file mode 100644 index 0000000..82b238c --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOSMTPSendOperation.h @@ -0,0 +1,38 @@ +// +// MCOSMTPSendOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/29/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOSMTPSENDOPERATION_H + +#define MAILCORE_MCOSMTPSENDOPERATION_H + +#import + +/** This is an asynchronous operation that will send a message through SMTP. */ + +typedef void (^MCOSMTPOperationProgressBlock)(unsigned int current, unsigned int maximum); + +@interface MCOSMTPSendOperation : MCOSMTPOperation + +/** This block will be called as the message is sent */ +@property (nonatomic, copy) MCOSMTPOperationProgressBlock progress; + +/* + Starts the asynchronous operation. + + @param completionBlock Called when the operation is finished. + + - On success `error` will be nil + + - On failure, `error` will be set with `MCOErrorDomain` as domain and an + error code available in MCOConstants.h, +*/ +- (void) start:(void (^)(NSError * error))completionBlock; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOSMTPSession.h b/MailCore.framework/Versions/A/Headers/MCOSMTPSession.h new file mode 100644 index 0000000..286cd7c --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOSMTPSession.h @@ -0,0 +1,145 @@ +// +// MCOSMTPSession.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/29/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOSMTPSESSION_H + +#define MAILCORE_MCOSMTPSESSION_H + +#import + +#import + +/** + This class is used to create an SMTP connection and send messages + + After calling a method that returns an operation you must call start: on the instance + to begin the operation. +*/ + +@class MCOSMTPSendOperation; +@class MCOSMTPOperation; +@class MCOAddress; + +@interface MCOSMTPSession : NSObject + +/** This is the hostname of the SMTP server to connect to. */ +@property (nonatomic, copy) NSString * hostname; + +/** This is the port of the SMTP server to connect to. */ +@property (nonatomic, assign) unsigned int port; + +/** This is the username of the account. */ +@property (nonatomic, copy) NSString * username; + +/** This is the password of the account. */ +@property (nonatomic, copy) NSString * password; + +/** This is the OAuth2 token. */ +@property (nonatomic, copy) NSString *OAuth2Token; + +/** + This is the authentication type to use to connect. + `MCOAuthTypeSASLNone` means that it uses the clear-text is used (and is the default). + @warning *Important*: Over an encrypted connection like TLS, the password will still be secure +*/ +@property (nonatomic, assign) MCOAuthType authType; + +/** + This is the encryption type to use. + See MCOConnectionType for more information. +*/ +@property (nonatomic, assign) MCOConnectionType connectionType; + +/** This is the timeout of the connection. */ +@property (nonatomic, assign) NSTimeInterval timeout; + +/** When set to YES, the connection will fail if the certificate is incorrect. */ +@property (nonatomic, assign, getter=isCheckCertificateEnabled) BOOL checkCertificateEnabled; + +/** + If set to YES, when sending the EHLO or HELO command, use IP address instead of hostname. + Default is NO. +*/ +@property (nonatomic, assign, getter=isUseHeloIPEnabled) BOOL useHeloIPEnabled; + +/** + Sets logger callback. The network traffic will be sent to this block. + + [session setConnectionLogger:^(void * connectionID, MCOConnectionLogType type, NSData * data) { + ... + }]; + */ +@property (nonatomic, copy) MCOConnectionLogger connectionLogger; + +/** This property provides some hints to MCOSMTPSession about where it's called from. + It will make MCOSMTPSession safe. It will also set all the callbacks of operations to run on this given queue. + Defaults to the main queue. + This property should be used only if there's performance issue using MCOSMTPSession in the main thread. */ +#if OS_OBJECT_USE_OBJC +@property (nonatomic, retain) dispatch_queue_t dispatchQueue; +#else +@property (nonatomic, assign) dispatch_queue_t dispatchQueue; +#endif + +/** @name Operations */ + +/** + Returns an operation that will send the given message through SMTP. + It will use the recipient set in the message data (To, Cc and Bcc). + It will also filter out Bcc from the content of the message. + + Generate RFC 822 data using MCOMessageBuilder + + MCOSMTPOperation * op = [session sendOperationWithData:rfc822Data]; + [op start:^(NSError * error) { + ... + }]; +*/ +- (MCOSMTPSendOperation *) sendOperationWithData:(NSData *)messageData; + +/** + Returns an operation that will send the given message through SMTP. + It will use the sender and recipient set from the parameters. + It will also filter out Bcc from the content of the message. + + Generate RFC 822 data using MCOMessageBuilder + + MCOSMTPOperation * op = [session sendOperationWithData:rfc822Data + from:[MCOAddress addressWithMailbox:@"hoa@etpan.org"] + recipients:[NSArray arrayWithObject:[MCOAddress addressWithMailbox:@"laura@etpan.org"]]]; + [op start:^(NSError * error) { + ... + }]; + */ +- (MCOSMTPSendOperation *) sendOperationWithData:(NSData *)messageData + from:(MCOAddress *)from + recipients:(NSArray *)recipients; + +/** + Returns an operation that will check whether the SMTP account is valid. + + MCOSMTPOperation * op = [session checkAccountOperationWithFrom:[MCOAddress addressWithMailbox:@"hoa@etpan.org"]]; + [op start:^(NSError * error) { + ... + }]; +*/ +- (MCOSMTPOperation *) checkAccountOperationWithFrom:(MCOAddress *)from; + +/** + Returns an operation that will perform a No-Op. + + MCOSMTPOperation * op = [session noopOperation]; + [op start:^(NSError * error) { + ... + }]; + */ +- (MCOSMTPOperation *) noopOperation; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOUtils.h b/MailCore.framework/Versions/A/Headers/MCOUtils.h new file mode 100644 index 0000000..30e83a7 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOUtils.h @@ -0,0 +1,28 @@ +// +// MCOUtils.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/22/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOUTILS_H + +#define MAILCORE_MCOUTILS_H + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCObjC.h b/MailCore.framework/Versions/A/Headers/MCObjC.h new file mode 100644 index 0000000..68d35f1 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCObjC.h @@ -0,0 +1,26 @@ +// +// MCObjC.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/27/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCOBJC_H + +#define MAILCORE_MCOBJC_H + +#ifdef __OBJC__ + +#import +#import +#import +#import +#import +#import +#import +#import + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCObject.h b/MailCore.framework/Versions/A/Headers/MCObject.h new file mode 100644 index 0000000..caf8ab3 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCObject.h @@ -0,0 +1,71 @@ +#ifndef MAILCORE_MCOBJECT_H + +#define MAILCORE_MCOBJECT_H + +#include +#if __APPLE__ +#include +#endif + +#ifdef __cplusplus + +#define MC_PROPERTY(mcType, setter, getter) \ + virtual void setter(mcType * getter); \ + virtual mcType * getter(); + +namespace mailcore { + + extern bool zombieEnabled; + + class String; + class HashMap; + + class Object { + public: + Object(); + virtual ~Object(); + + virtual int retainCount(); + virtual Object * retain(); + virtual void release(); + virtual Object * autorelease(); + virtual String * description(); + virtual String * className(); + + virtual bool isEqual(Object * otherObject); + virtual unsigned int hash(); + + // optional + virtual Object * copy(); + virtual HashMap * serializable(); + virtual void importSerializable(HashMap * serializable); + + typedef void (Object::*Method) (void *); + virtual void performMethod(Method method, void * context); + virtual void performMethodOnMainThread(Method method, void * context, bool waitUntilDone = false); + virtual void performMethodAfterDelay(Method method, void * context, double delay); +#if __APPLE__ + virtual void performMethodOnDispatchQueue(Method method, void * context, void * targetDispatchQueue, bool waitUntilDone = false); + virtual void performMethodOnDispatchQueueAfterDelay(Method method, void * context, void * targetDispatchQueue, double delay); + virtual void cancelDelayedPerformMethodOnDispatchQueue(Method method, void * context, void * targetDispatchQueue); +#endif + virtual void cancelDelayedPerformMethod(Method method, void * context); + + // serialization utils + static void registerObjectConstructor(const char * className, void * (* objectConstructor)(void)); + static Object * objectWithSerializable(HashMap * serializable); + + public: // private + + private: + pthread_mutex_t mLock; + int mCounter; + void init(); + static void initObjectConstructors(); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOperation.h b/MailCore.framework/Versions/A/Headers/MCOperation.h new file mode 100644 index 0000000..b9d5f95 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOperation.h @@ -0,0 +1,59 @@ +#ifndef MAILCORE_MCOPERATION_H + +#define MAILCORE_MCOPERATION_H + +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class OperationCallback; + + class Operation : public Object { + public: + Operation(); + virtual ~Operation(); + + virtual void setCallback(OperationCallback * callback); + virtual OperationCallback * callback(); + + virtual void cancel(); + virtual bool isCancelled(); + + // Will be called on main thread. + virtual void beforeMain(); + + virtual void main(); + + // Will be called on main thread. + virtual void afterMain(); + + virtual void start(); + +#ifdef __APPLE__ + virtual void setCallbackDispatchQueue(dispatch_queue_t callbackDispatchQueue); + virtual dispatch_queue_t callbackDispatchQueue(); +#endif + void performMethodOnCallbackThread(Method method, void * context, bool waitUntilDone = false); + + virtual bool shouldRunWhenCancelled(); + virtual void setShouldRunWhenCancelled(bool shouldRunWhenCancelled); + + private: + OperationCallback * mCallback; + bool mCancelled; + bool mShouldRunWhenCancelled; + pthread_mutex_t mLock; +#ifdef __APPLE__ + dispatch_queue_t mCallbackDispatchQueue; +#endif + + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOperationCallback.h b/MailCore.framework/Versions/A/Headers/MCOperationCallback.h new file mode 100644 index 0000000..b8bea4d --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOperationCallback.h @@ -0,0 +1,20 @@ +#ifndef MAILCORE_MCOPERATIONCALLBACK_H + +#define MAILCORE_MCOPERATIONCALLBACK_H + +#ifdef __cplusplus + +namespace mailcore { + + class Operation; + + class OperationCallback { + public: + virtual void operationFinished(Operation * op) {} + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCOperationQueue.h b/MailCore.framework/Versions/A/Headers/MCOperationQueue.h new file mode 100644 index 0000000..119befc --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCOperationQueue.h @@ -0,0 +1,68 @@ +#ifndef MAILCORE_MCOPERATIONQUEUE_H + +#define MAILCORE_MCOPERATIONQUEUE_H + +#include +#include +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class Operation; + class OperationQueueCallback; + class Array; + + class OperationQueue : public Object { + public: + OperationQueue(); + virtual ~OperationQueue(); + + virtual void addOperation(Operation * op); + virtual void cancelAllOperations(); + + virtual unsigned int count(); + + virtual void setCallback(OperationQueueCallback * callback); + virtual OperationQueueCallback * callback(); + +#ifdef __APPLE__ + virtual void setDispatchQueue(dispatch_queue_t dispatchQueue); + virtual dispatch_queue_t dispatchQueue(); +#endif + + private: + Array * mOperations; + pthread_t mThreadID; + bool mStarted; + struct mailsem * mOperationSem; + struct mailsem * mStartSem; + struct mailsem * mStopSem; + pthread_mutex_t mLock; + bool mWaiting; + struct mailsem * mWaitingFinishedSem; + bool mQuitting; + OperationQueueCallback * mCallback; +#if __APPLE__ + dispatch_queue_t mDispatchQueue; +#endif + bool _pendingCheckRunning; + + void startThread(); + static void runOperationsOnThread(OperationQueue * queue); + void runOperations(); + void beforeMain(Operation * op); + void callbackOnMainThread(Operation * op); + void checkRunningOnMainThread(void * context); + void checkRunningAfterDelay(void * context); + void stoppedOnMainThread(void * context); + void performOnCallbackThread(Operation * op, Method method, void * context, bool waitUntilDone); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCPOP.h b/MailCore.framework/Versions/A/Headers/MCPOP.h new file mode 100644 index 0000000..db17430 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCPOP.h @@ -0,0 +1,9 @@ +#ifndef MAILCORE_MCPOP_H + +#define MAILCORE_MCPOP_H + +#include +#include +#include + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCPOPAsyncSession.h b/MailCore.framework/Versions/A/Headers/MCPOPAsyncSession.h new file mode 100644 index 0000000..dae0f7b --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCPOPAsyncSession.h @@ -0,0 +1,98 @@ +// +// MCPopAsyncSession.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/16/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCPOPASYNCSESSION_H + +#define MAILCORE_MCPOPASYNCSESSION_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class POPOperation; + class POPSession; + class POPFetchHeaderOperation; + class POPFetchMessageOperation; + class POPDeleteMessagesOperation; + class POPFetchMessagesOperation; + class POPOperationQueueCallback; + class POPConnectionLogger; + + class POPAsyncSession : public Object { + public: + POPAsyncSession(); + virtual ~POPAsyncSession(); + + virtual void setHostname(String * hostname); + virtual String * hostname(); + + virtual void setPort(unsigned int port); + virtual unsigned int port(); + + virtual void setUsername(String * login); + virtual String * username(); + + virtual void setPassword(String * password); + virtual String * password(); + + virtual void setAuthType(AuthType authType); + virtual AuthType authType(); + + virtual void setConnectionType(ConnectionType connectionType); + virtual ConnectionType connectionType(); + + virtual void setTimeout(time_t timeout); + virtual time_t timeout(); + + virtual void setCheckCertificateEnabled(bool enabled); + virtual bool isCheckCertificateEnabled(); + + virtual void setConnectionLogger(ConnectionLogger * logger); + virtual ConnectionLogger * connectionLogger(); + +#ifdef __APPLE__ + virtual void setDispatchQueue(dispatch_queue_t dispatchQueue); + virtual dispatch_queue_t dispatchQueue(); +#endif + + virtual POPFetchMessagesOperation * fetchMessagesOperation(); + + virtual POPFetchHeaderOperation * fetchHeaderOperation(unsigned int index); + + virtual POPFetchMessageOperation * fetchMessageOperation(unsigned int index); + + // Will disconnect. + virtual POPOperation * deleteMessagesOperation(IndexSet * indexes); + + virtual POPOperation * disconnectOperation(); + + virtual POPOperation * checkAccountOperation(); + + virtual POPOperation * noopOperation(); + + private: + POPSession * mSession; + OperationQueue * mQueue; + POPOperationQueueCallback * mQueueCallback; + ConnectionLogger * mConnectionLogger; + pthread_mutex_t mConnectionLoggerLock; + POPConnectionLogger * mInternalLogger; + + public: // private + virtual void runOperation(POPOperation * operation); + virtual POPSession * session(); + virtual void logConnection(ConnectionLogType logType, Data * buffer); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCPOPFetchHeaderOperation.h b/MailCore.framework/Versions/A/Headers/MCPOPFetchHeaderOperation.h new file mode 100644 index 0000000..d046654 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCPOPFetchHeaderOperation.h @@ -0,0 +1,44 @@ +// +// MCPOPFetchHeaderOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/16/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCPOPFETCHHEADEROPERATION_H + +#define MAILCORE_MCPOPFETCHHEADEROPERATION_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class MessageHeader; + + class POPFetchHeaderOperation : public POPOperation { + public: + POPFetchHeaderOperation(); + virtual ~POPFetchHeaderOperation(); + + virtual void setMessageIndex(unsigned int messageIndex); + virtual unsigned int messageIndex(); + + virtual MessageHeader * header(); + + public: // subclass behavior + virtual void main(); + + private: + unsigned int mMessageIndex; + MessageHeader * mHeader; + + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCPOPFetchMessageOperation.h b/MailCore.framework/Versions/A/Headers/MCPOPFetchMessageOperation.h new file mode 100644 index 0000000..86d08af --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCPOPFetchMessageOperation.h @@ -0,0 +1,41 @@ +// +// MCPOPFetchMessageOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/16/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCPOPFETCHMESSAGEOPERATION_H + +#define MAILCORE_MCPOPFETCHMESSAGEOPERATION_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + class POPFetchMessageOperation : public POPOperation { + public: + POPFetchMessageOperation(); + virtual ~POPFetchMessageOperation(); + + virtual void setMessageIndex(unsigned int messageIndex); + virtual unsigned int messageIndex(); + + virtual Data * data(); + + public: // subclass behavior + virtual void main(); + + private: + unsigned int mMessageIndex; + Data * mData; + + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCPOPFetchMessagesOperation.h b/MailCore.framework/Versions/A/Headers/MCPOPFetchMessagesOperation.h new file mode 100644 index 0000000..eaee884 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCPOPFetchMessagesOperation.h @@ -0,0 +1,37 @@ +// +// MCPOPFetchMessagesOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/16/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCPOPFETCHMESSAGESOPERATION_H + +#define MAILCORE_MCPOPFETCHMESSAGESOPERATION_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class POPFetchMessagesOperation : public POPOperation { + public: + POPFetchMessagesOperation(); + virtual ~POPFetchMessagesOperation(); + + virtual Array * /* POPMessageInfo */ messages(); + + public: // subclass behavior + virtual void main(); + + private: + Array * /* POPMessageInfo */ mMessages; + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCPOPMessageInfo.h b/MailCore.framework/Versions/A/Headers/MCPOPMessageInfo.h new file mode 100644 index 0000000..be85bc9 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCPOPMessageInfo.h @@ -0,0 +1,42 @@ +#ifndef MAILCORE_MCPOPMESSAGEINFO_H + +#define MAILCORE_MCPOPMESSAGEINFO_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class POPMessageInfo : public Object { + public: + POPMessageInfo(); + virtual ~POPMessageInfo(); + + virtual void setIndex(unsigned int index); + virtual unsigned int index(); + + virtual void setSize(unsigned int size); + virtual unsigned int size(); + + virtual void setUid(String * uid); + virtual String * uid(); + + public: // subclass behavior + POPMessageInfo(POPMessageInfo * other); + virtual String * description(); + virtual Object * copy(); + + private: + unsigned int mIndex; + unsigned int mSize; + String * mUid; + + void init(); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCPOPNoopOperation.h b/MailCore.framework/Versions/A/Headers/MCPOPNoopOperation.h new file mode 100644 index 0000000..705d396 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCPOPNoopOperation.h @@ -0,0 +1,32 @@ +// +// MCPOPNoopOperation.h +// mailcore2 +// +// Created by Robert Widmann on 9/24/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCPOPNOOPOPERATION_H + +#define MAILCORE_MCPOPNOOPOPERATION_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class POPNoopOperation : public POPOperation { + public: + POPNoopOperation(); + virtual ~POPNoopOperation(); + + public: // subclass behavior + virtual void main(); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCPOPOperation.h b/MailCore.framework/Versions/A/Headers/MCPOPOperation.h new file mode 100644 index 0000000..1b454e9 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCPOPOperation.h @@ -0,0 +1,53 @@ +// +// MCPOPOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/16/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCPOPOPERATION_H + +#define MAILCORE_MCPOPOPERATION_H + +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class POPAsyncSession; + class POPOperationCallback; + + class POPOperation : public Operation, public POPProgressCallback { + public: + POPOperation(); + virtual ~POPOperation(); + + virtual void setSession(POPAsyncSession * session); + virtual POPAsyncSession * session(); + + virtual void setPopCallback(POPOperationCallback * callback); + virtual POPOperationCallback * popCallback(); + + virtual void setError(ErrorCode error); + virtual ErrorCode error(); + + virtual void start(); + + private: + POPAsyncSession * mSession; + POPOperationCallback * mPopCallback; + ErrorCode mError; + private: + virtual void bodyProgress(POPSession * session, unsigned int current, unsigned int maximum); + virtual void bodyProgressOnMainThread(void * context); + + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCPOPOperationCallback.h b/MailCore.framework/Versions/A/Headers/MCPOPOperationCallback.h new file mode 100644 index 0000000..ccc2168 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCPOPOperationCallback.h @@ -0,0 +1,28 @@ +// +// MCPOPOperationCallback.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/16/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCPOPOPERATIONCALLBACK_H + +#define MAILCORE_MCPOPOPERATIONCALLBACK_H + +#ifdef __cplusplus + +namespace mailcore { + + class POPOperation; + + class POPOperationCallback { + public: + virtual void bodyProgress(POPOperation * session, unsigned int current, unsigned int maximum) {}; + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCPOPProgressCallback.h b/MailCore.framework/Versions/A/Headers/MCPOPProgressCallback.h new file mode 100644 index 0000000..c28e396 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCPOPProgressCallback.h @@ -0,0 +1,20 @@ +#ifndef MAILCORE_MCPOPPROGRESSCALLBACK_H + +#define MAILCORE_MCPOPPROGRESSCALLBACK_H + +#ifdef __cplusplus + +namespace mailcore { + + class POPSession; + + class POPProgressCallback { + public: + virtual void bodyProgress(POPSession * session, unsigned int current, unsigned int maximum) {}; + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCPOPSession.h b/MailCore.framework/Versions/A/Headers/MCPOPSession.h new file mode 100644 index 0000000..dfe6765 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCPOPSession.h @@ -0,0 +1,100 @@ +#ifndef MAILCORE_MCPOPSESSION_H + +#define MAILCORE_MCPOPSESSION_H + +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class POPMessageInfo; + class POPProgressCallback; + class MessageHeader; + + class POPSession : public Object { + public: + POPSession(); + virtual ~POPSession(); + + virtual void setHostname(String * hostname); + virtual String * hostname(); + + virtual void setPort(unsigned int port); + virtual unsigned int port(); + + virtual void setUsername(String * username); + virtual String * username(); + + virtual void setPassword(String * password); + virtual String * password(); + + virtual void setAuthType(AuthType authType); + virtual AuthType authType(); + + virtual void setConnectionType(ConnectionType connectionType); + virtual ConnectionType connectionType(); + + virtual void setTimeout(time_t timeout); + virtual time_t timeout(); + + virtual void setCheckCertificateEnabled(bool enabled); + virtual bool isCheckCertificateEnabled(); + + virtual void connect(ErrorCode * pError); + virtual void disconnect(); + + virtual void login(ErrorCode * pError); + + virtual void checkAccount(ErrorCode * pError); + + virtual void noop(ErrorCode * pError); + + Array * /* POPMessageInfo */ fetchMessages(ErrorCode * pError); + + MessageHeader * fetchHeader(unsigned int index, ErrorCode * pError); + MessageHeader * fetchHeader(POPMessageInfo * msg, ErrorCode * pError); + + Data * fetchMessage(unsigned int index, POPProgressCallback * callback, ErrorCode * pError); + Data * fetchMessage(POPMessageInfo * msg, POPProgressCallback * callback, ErrorCode * pError); + + void deleteMessage(unsigned int index, ErrorCode * pError); + void deleteMessage(POPMessageInfo * msg, ErrorCode * pError); + + virtual void setConnectionLogger(ConnectionLogger * logger); + virtual ConnectionLogger * connectionLogger(); + + private: + String * mHostname; + unsigned int mPort; + String * mUsername; + String * mPassword; + AuthType mAuthType; + ConnectionType mConnectionType; + bool mCheckCertificateEnabled; + time_t mTimeout; + + mailpop3 * mPop; + POPCapability mCapabilities; + POPProgressCallback * mProgressCallback; + int mState; + + ConnectionLogger * mConnectionLogger; + + void init(); + void bodyProgress(unsigned int current, unsigned int maximum); + bool checkCertificate(); + static void body_progress(size_t current, size_t maximum, void * context); + void setup(); + void unsetup(); + void connectIfNeeded(ErrorCode * pError); + void loginIfNeeded(ErrorCode * pError); + void listIfNeeded(ErrorCode * pError); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCProvider.h b/MailCore.framework/Versions/A/Headers/MCProvider.h new file mode 100644 index 0000000..b13bb26 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCProvider.h @@ -0,0 +1,17 @@ +// +// MCProvider.h +// mailcore2 +// +// Created by Robert Widmann on 4/28/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCPROVIDER_H + +#define MAILCORE_MCPROVIDER_H + +#include +#include +#include + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCRFC822.h b/MailCore.framework/Versions/A/Headers/MCRFC822.h new file mode 100644 index 0000000..66c4d40 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCRFC822.h @@ -0,0 +1,11 @@ +#ifndef MAILCORE_MCRFC822_H + +#define MAILCORE_MCRFC822_H + +#include +#include +#include +#include +#include + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCRange.h b/MailCore.framework/Versions/A/Headers/MCRange.h new file mode 100644 index 0000000..12e1a9c --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCRange.h @@ -0,0 +1,40 @@ +#ifndef MAILCORE_MCRANGE_H + +#define MAILCORE_MCRANGE_H + +#ifdef __cplusplus + +#include + +#ifndef UINT64_MAX +# define UINT64_MAX 18446744073709551615ULL +#endif + +namespace mailcore { + + class IndexSet; + class String; + + // infinite length : UINT64_MAX + // empty range : location = UINT64_MAX + struct Range { + uint64_t location; + uint64_t length; + }; + + extern Range RangeEmpty; + + Range RangeMake(uint64_t location, uint64_t length); + IndexSet * RangeRemoveRange(Range range1, Range range2); + IndexSet * RangeUnion(Range range1, Range range2); + Range RangeIntersection(Range range1, Range range2); + bool RangeHasIntersection(Range range1, Range range2); + uint64_t RangeLeftBound(Range range); + uint64_t RangeRightBound(Range range); + String * RangeToString(Range range); + Range RangeFromString(String * rangeString); +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCRenderer.h b/MailCore.framework/Versions/A/Headers/MCRenderer.h new file mode 100644 index 0000000..441b63b --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCRenderer.h @@ -0,0 +1,17 @@ +// +// MCRenderer.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 2/2/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCRENDERER_H + +#define MAILCORE_MCRENDERER_H + +#include +#include +#include + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCSMTP.h b/MailCore.framework/Versions/A/Headers/MCSMTP.h new file mode 100644 index 0000000..452e024 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCSMTP.h @@ -0,0 +1,8 @@ +#ifndef MAILCORE_MCSMTP_H + +#define MAILCORE_MCSMTP_H + +#include +#include + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCSMTPAsyncSession.h b/MailCore.framework/Versions/A/Headers/MCSMTPAsyncSession.h new file mode 100644 index 0000000..fa0893d --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCSMTPAsyncSession.h @@ -0,0 +1,90 @@ +#ifndef MAILCORE_MCSMTPASYNCSESSION_H + +#define MAILCORE_MCSMTPASYNCSESSION_H + +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class MessageBuilder; + class SMTPOperation; + class SMTPSession; + class Address; + class SMTPOperationQueueCallback; + class SMTPConnectionLogger; + + class SMTPAsyncSession : public Object { + public: + SMTPAsyncSession(); + virtual ~SMTPAsyncSession(); + + virtual void setHostname(String * hostname); + virtual String * hostname(); + + virtual void setPort(unsigned int port); + virtual unsigned int port(); + + virtual void setUsername(String * username); + virtual String * username(); + + virtual void setPassword(String * password); + virtual String * password(); + + virtual void setOAuth2Token(String * token); + virtual String * OAuth2Token(); + + virtual void setAuthType(AuthType authType); + virtual AuthType authType(); + + virtual void setConnectionType(ConnectionType connectionType); + virtual ConnectionType connectionType(); + + virtual void setTimeout(time_t timeout); + virtual time_t timeout(); + + virtual void setCheckCertificateEnabled(bool enabled); + virtual bool isCheckCertificateEnabled(); + + virtual void setUseHeloIPEnabled(bool enabled); + virtual bool useHeloIPEnabled(); + + virtual void setConnectionLogger(ConnectionLogger * logger); + virtual ConnectionLogger * connectionLogger(); + +#ifdef __APPLE__ + virtual void setDispatchQueue(dispatch_queue_t dispatchQueue); + virtual dispatch_queue_t dispatchQueue(); +#endif + + virtual SMTPOperation * sendMessageOperation(Data * messageData); + virtual SMTPOperation * sendMessageOperation(Address * from, Array * recipients, + Data * messageData); + virtual SMTPOperation * checkAccountOperation(Address * from); + + virtual SMTPOperation * noopOperation(); + + public: // private + virtual void runOperation(SMTPOperation * operation); + virtual SMTPSession * session(); + virtual void tryAutomaticDisconnect(); + virtual void logConnection(ConnectionLogType logType, Data * buffer); + + private: + SMTPSession * mSession; + OperationQueue * mQueue; + SMTPOperationQueueCallback * mQueueCallback; + ConnectionLogger * mConnectionLogger; + pthread_mutex_t mConnectionLoggerLock; + SMTPConnectionLogger * mInternalLogger; + + virtual void tryAutomaticDisconnectAfterDelay(void * context); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCSMTPNoopOperation.h b/MailCore.framework/Versions/A/Headers/MCSMTPNoopOperation.h new file mode 100644 index 0000000..0911675 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCSMTPNoopOperation.h @@ -0,0 +1,34 @@ +// +// MCSMTPNoopOperation.h +// mailcore2 +// +// Created by Robert Widmann on 9/24/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCSMTPNOOPOPERATION_H + +#define MAILCORE_MCSMTPNOOPOPERATION_H + +#include +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class SMTPNoopOperation : public SMTPOperation { + public: + SMTPNoopOperation(); + virtual ~SMTPNoopOperation(); + + public: // subclass behavior + virtual void main(); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCSMTPOperation.h b/MailCore.framework/Versions/A/Headers/MCSMTPOperation.h new file mode 100644 index 0000000..1d24f48 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCSMTPOperation.h @@ -0,0 +1,52 @@ +// +// MCSMTPOperation.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/11/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCSMTPOPERATION_H + +#define MAILCORE_MCSMTPOPERATION_H + +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class SMTPAsyncSession; + class SMTPOperationCallback; + + class SMTPOperation : public Operation, public SMTPProgressCallback { + public: + SMTPOperation(); + virtual ~SMTPOperation(); + + virtual void setSession(SMTPAsyncSession * session); + virtual SMTPAsyncSession * session(); + + virtual void setSmtpCallback(SMTPOperationCallback * callback); + virtual SMTPOperationCallback * smtpCallback(); + + virtual void setError(ErrorCode error); + virtual ErrorCode error(); + + virtual void start(); + + private: + SMTPAsyncSession * mSession; + SMTPOperationCallback * mSmtpCallback; + ErrorCode mError; + private: + virtual void bodyProgress(SMTPSession * session, unsigned int current, unsigned int maximum); + virtual void bodyProgressOnMainThread(void * context); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCSMTPOperationCallback.h b/MailCore.framework/Versions/A/Headers/MCSMTPOperationCallback.h new file mode 100644 index 0000000..5a3d00d --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCSMTPOperationCallback.h @@ -0,0 +1,28 @@ +// +// MCSMTPOperationCallback.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/11/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCSMTPOPERATIONCALLBACK_H + +#define MAILCORE_MCSMTPOPERATIONCALLBACK_H + +#ifdef __cplusplus + +namespace mailcore { + + class SMTPOperation; + + class SMTPOperationCallback { + public: + virtual void bodyProgress(SMTPOperation * session, unsigned int current, unsigned int maximum) {}; + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCSMTPProgressCallback.h b/MailCore.framework/Versions/A/Headers/MCSMTPProgressCallback.h new file mode 100644 index 0000000..7016cfc --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCSMTPProgressCallback.h @@ -0,0 +1,20 @@ +#ifndef MAILCORE_MCSMTPPROGRESSCALLBACK_H + +#define MAILCORE_MCSMTPPROGRESSCALLBACK_H + +#ifdef __cplusplus + +namespace mailcore { + + class SMTPSession; + + class SMTPProgressCallback { + public: + virtual void bodyProgress(SMTPSession * session, unsigned int current, unsigned int maximum) {}; + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCSMTPSession.h b/MailCore.framework/Versions/A/Headers/MCSMTPSession.h new file mode 100644 index 0000000..844369f --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCSMTPSession.h @@ -0,0 +1,111 @@ +#ifndef MAILCORE_MCSMTPSESSION_H + +#define MAILCORE_MCSMTPSESSION_H + +#include +#include + +#ifdef __cplusplus + +namespace mailcore { + + class Address; + class SMTPProgressCallback; + class MessageBuilder; + + class SMTPSession : public Object { + public: + SMTPSession(); + virtual ~SMTPSession(); + + virtual void setHostname(String * hostname); + virtual String * hostname(); + + virtual void setPort(unsigned int port); + virtual unsigned int port(); + + virtual void setUsername(String * username); + virtual String * username(); + + virtual void setPassword(String * password); + virtual String * password(); + + // To authenticate using OAuth2, username and oauth2token should be set. + // auth type to use is AuthTypeOAuth2. + virtual void setOAuth2Token(String * token); + virtual String * OAuth2Token(); + + virtual void setAuthType(AuthType authType); + virtual AuthType authType(); + + virtual void setConnectionType(ConnectionType connectionType); + virtual ConnectionType connectionType(); + + virtual void setTimeout(time_t timeout); + virtual time_t timeout(); + + virtual void setCheckCertificateEnabled(bool enabled); + virtual bool isCheckCertificateEnabled(); + + virtual void setUseHeloIPEnabled(bool enabled); + virtual bool useHeloIPEnabled(); + + virtual void connect(ErrorCode * pError); + virtual void disconnect(); + + virtual void login(ErrorCode * pError); + + virtual void checkAccount(Address * from, ErrorCode * pError); + + virtual void sendMessage(Data * messageData, SMTPProgressCallback * callback, ErrorCode * pError); + virtual void sendMessage(Address * from, Array * /* Address */ recipients, Data * messageData, + SMTPProgressCallback * callback, ErrorCode * pError); + + virtual void setConnectionLogger(ConnectionLogger * logger); + virtual ConnectionLogger * connectionLogger(); + + virtual void noop(ErrorCode * pError); + + private: + String * mHostname; + unsigned int mPort; + String * mUsername; + String * mPassword; + String * mOAuth2Token; + AuthType mAuthType; + ConnectionType mConnectionType; + time_t mTimeout; + bool mCheckCertificateEnabled; + bool mUseHeloIPEnabled; + bool mShouldDisconnect; + + mailsmtp * mSmtp; + SMTPProgressCallback * mProgressCallback; + int mState; + String * mLastSMTPResponse; + int mLastLibetpanError; + int mLastSMTPResponseCode; + + ConnectionLogger * mConnectionLogger; + + void init(); + Data * dataWithFilteredBcc(Data * data); + static void body_progress(size_t current, size_t maximum, void * context); + void bodyProgress(unsigned int current, unsigned int maximum); + void setup(); + void unsetup(); + void connectIfNeeded(ErrorCode * pError); + void loginIfNeeded(ErrorCode * pError); + bool checkCertificate(); + + void sendMessage(MessageBuilder * msg, SMTPProgressCallback * callback, ErrorCode * pError); + + public: // private + virtual bool isDisconnected(); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCSet.h b/MailCore.framework/Versions/A/Headers/MCSet.h new file mode 100644 index 0000000..334310a --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCSet.h @@ -0,0 +1,49 @@ +#ifndef MAILCORE_CSET_H + +#define MAILCORE_CSET_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class String; + class Array; + class HashMap; + + class Set : public Object { + public: + Set(); + Set(Set * o); + + static Set * set(); + static Set * setWithArray(Array * objects); + + virtual unsigned int count(); + virtual void addObject(Object * obj); + virtual void removeObject(Object * obj); + virtual bool containsObject(Object * obj); + virtual Object * member(Object * obj); + + virtual Array * allObjects(); + virtual void removeAllObjects(); + virtual void addObjectsFromArray(Array * objects); + + public: // subclass behavior + virtual ~Set(); + virtual String * description(); + virtual Object * copy(); + virtual HashMap * serializable(); + virtual void importSerializable(HashMap * serializable); + + private: + HashMap * mHash; + void init(); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCSizeFormatter.h b/MailCore.framework/Versions/A/Headers/MCSizeFormatter.h new file mode 100644 index 0000000..8c139f6 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCSizeFormatter.h @@ -0,0 +1,30 @@ +// +// MCSizeFormatter.h +// testUI +// +// Created by DINH Viêt Hoà on 1/29/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MCSIZEFORMATTER_H + +#define MAILCORE_MCSIZEFORMATTER_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class String; + + class SizeFormatter : public Object { + public: + static String * stringWithSize(unsigned int size); + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCString.h b/MailCore.framework/Versions/A/Headers/MCString.h new file mode 100644 index 0000000..25439cf --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCString.h @@ -0,0 +1,145 @@ +#ifndef MAILCORE_MCSTR_H + +#define MAILCORE_MCSTR_H + +#include +#include +#include + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class Data; + class Array; + + class String : public Object { + public: + String(const UChar * unicodeChars = NULL); + String(const UChar * unicodeChars, unsigned int length); + String(const char * UTF8Characters); + String(Data * data, const char * charset); + String(const char * bytes, unsigned int length, const char * charset = NULL); + virtual ~String(); + + static String * string(); + static String * stringWithUTF8Format(const char * format, ...); + static String * stringWithVUTF8Format(const char * format, va_list ap); + static String * stringWithUTF8Characters(const char * UTF8Characters); + static String * stringWithCharacters(const UChar * characters); + static String * stringWithCharacters(const UChar * characters, unsigned int length); + static String * stringWithData(Data * data, const char * charset = NULL); + + virtual const UChar * unicodeCharacters(); + virtual const char * UTF8Characters(); + virtual unsigned int length(); + + virtual void appendString(String * otherString); + virtual void appendUTF8Format(const char * format, ...); + virtual void appendCharacters(const UChar * unicodeCharacters); + virtual void appendCharactersLength(const UChar * unicodeCharacters, unsigned int length); + virtual void appendUTF8Characters(const char * UTF8Characters); + virtual void setString(String * otherString); + virtual void setUTF8Characters(const char * UTF8Characters); + virtual void setCharacters(const UChar * unicodeCharacters); + + virtual String * stringByAppendingString(String * otherString); + virtual String * stringByAppendingUTF8Format(const char * format, ...); + virtual String * stringByAppendingUTF8Characters(const char * UTF8Characters); + virtual String * stringByAppendingCharacters(const UChar * unicodeCharacters); + virtual String * stringByAppendingPathComponent(String * component); + virtual String * stringByDeletingLastPathComponent(); + + virtual int compare(String * otherString); + virtual int caseInsensitiveCompare(String * otherString); + virtual String * lowercaseString(); + virtual String * uppercaseString(); + + virtual UChar characterAtIndex(unsigned int idx); + virtual void deleteCharactersInRange(Range range); + virtual unsigned int replaceOccurrencesOfString(String * occurrence, String * replacement); + virtual int locationOfString(String * occurrence); + + virtual Array * componentsSeparatedByString(String * separator); + + virtual bool isEqualCaseInsensitive(String * otherString); + + // Additions + static String * stringByDecodingMIMEHeaderValue(const char * phrase); + virtual Data * encodedAddressDisplayNameValue(); + virtual Data * encodedMIMEHeaderValue(); + virtual Data * encodedMIMEHeaderValueForSubject(); + virtual String * extractedSubject(); + virtual String * extractedSubjectAndKeepBracket(bool keepBracket); + static String * uuidString(); + + virtual bool hasSuffix(String * suffix); + virtual bool hasPrefix(String * prefix); + + virtual String * substringFromIndex(unsigned int idx); + virtual String * substringToIndex(unsigned int idx); + virtual String * substringWithRange(Range range); + + virtual String * flattenHTML(); + virtual String * flattenHTMLAndShowBlockquote(bool showBlockquote); + virtual String * flattenHTMLAndShowBlockquoteAndLink(bool showBlockquote, bool showLink); + + virtual String * stripWhitespace(); + + virtual String * lastPathComponent(); + virtual String * pathExtension(); + virtual Data * dataUsingEncoding(const char * charset = NULL); + + virtual const char * fileSystemRepresentation(); + static String * stringWithFileSystemRepresentation(const char * filename); + + int intValue(); + unsigned int unsignedIntValue(); + long longValue(); + unsigned long unsignedLongValue(); + long long longLongValue(); + unsigned long long unsignedLongLongValue(); + double doubleValue(); + + virtual Data * mUTF7EncodedData(); + static String * stringWithMUTF7Data(Data * data); + virtual String * mUTF7EncodedString(); + virtual String * mUTF7DecodedString(); + + virtual String * htmlEncodedString(); + virtual String * cleanedHTMLString(); + virtual String * htmlMessageContent(); + + virtual Data * decodedBase64Data(); + + public: // private + static String * uniquedStringWithUTF8Characters(const char * UTF8Characters); + + public: // subclass behavior + String(String * otherString); + virtual String * description(); + virtual Object * copy(); + virtual bool isEqual(Object * otherObject); + virtual unsigned int hash(); + virtual HashMap * serializable(); + virtual void importSerializable(HashMap * serializable); + + private: + UChar * mUnicodeChars; + unsigned int mLength; + unsigned int mAllocated; + void allocate(unsigned int length); + void reset(); + int compareWithCaseSensitive(String * otherString, bool caseSensitive); + void appendBytes(const char * bytes, unsigned int length, const char * charset); + void appendUTF8CharactersLength(const char * UTF8Characters, unsigned int length); + }; + + void setICUDataDirectory(String * directory); +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCUtils.h b/MailCore.framework/Versions/A/Headers/MCUtils.h new file mode 100644 index 0000000..ad9c4db --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCUtils.h @@ -0,0 +1,41 @@ +#ifndef MAILCORE_MCUTILS_H + +#define MAILCORE_MCUTILS_H + +#ifdef __cplusplus + +#define MC_SAFE_RETAIN(o) ((o) != NULL ? (o)->retain() : NULL) +#define MC_SAFE_COPY(o) ((o) != NULL ? (o)->copy() : NULL) + +#define MC_SAFE_RELEASE(o) \ + do { \ + if ((o) != NULL) { \ + (o)->release(); \ + (o) = NULL; \ + } \ + } while (0) + +#define MC_SAFE_REPLACE_RETAIN(type, mField, value) \ + do { \ + MC_SAFE_RELEASE(mField); \ + mField = (type *) MC_SAFE_RETAIN(value); \ + } while (0) + +#define MC_SAFE_REPLACE_COPY(type, mField, value) \ + do { \ + MC_SAFE_RELEASE(mField); \ + mField = (type *) MC_SAFE_COPY(value); \ + } while (0) + +#define MCSTR(str) mailcore::String::uniquedStringWithUTF8Characters("" str "") + +#define MCUTF8(str) MCUTF8DESC(str) +#define MCUTF8DESC(obj) ((obj) != NULL ? (obj)->description()->UTF8Characters() : NULL ) + +#define MCLOCALIZEDSTRING(key) key + +#define MCISKINDOFCLASS(instance, class) (dynamic_cast(instance) != NULL) + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MCValue.h b/MailCore.framework/Versions/A/Headers/MCValue.h new file mode 100644 index 0000000..7de1a0d --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MCValue.h @@ -0,0 +1,111 @@ +#ifndef MAILCORE_MCVALUE_H + +#define MAILCORE_MCVALUE_H + +#include + +#ifdef __cplusplus + +namespace mailcore { + + class String; + + enum { + ValueTypeNone, + ValueTypeBool, + ValueTypeChar, + ValueTypeUnsignedChar, + ValueTypeShort, + ValueTypeUnsignedShort, + ValueTypeInt, + ValueTypeUnsignedInt, + ValueTypeLong, + ValueTypeUnsignedLong, + ValueTypeLongLong, + ValueTypeUnsignedLongLong, + ValueTypeFloat, + ValueTypeDouble, + ValueTypePointer, + ValueTypeData, + }; + + class Value : public Object { + public: + virtual ~Value(); + + static Value * valueWithBoolValue(bool value); + static Value * valueWithCharValue(char value); + static Value * valueWithUnsignedCharValue(unsigned char value); + static Value * valueWithIntValue(int value); + static Value * valueWithUnsignedIntValue(unsigned int value); + static Value * valueWithLongValue(long value); + static Value * valueWithUnsignedLongValue(unsigned long value); + static Value * valueWithLongLongValue(long long value); + static Value * valueWithUnsignedLongLongValue(unsigned long long value); + static Value * valueWithFloatValue(float value); + static Value * valueWithDoubleValue(double value); + static Value * valueWithPointerValue(void * value); + static Value * valueWithData(const char * value, int length); + + virtual bool boolValue(); + virtual char charValue(); + virtual unsigned char unsignedCharValue(); + virtual short shortValue(); + virtual unsigned short unsignedShortValue(); + virtual int intValue(); + virtual unsigned int unsignedIntValue(); + virtual long longValue(); + virtual unsigned long unsignedLongValue(); + virtual long long longLongValue(); + virtual unsigned long long unsignedLongLongValue(); + virtual float floatValue(); + virtual double doubleValue(); + virtual void * pointerValue(); + virtual void dataValue(const char ** p_value, int * p_length); + + public: // subclass behavior + Value(Value * other); + virtual String * description(); + virtual bool isEqual(Object * otherObject); + virtual unsigned int hash(); + Object * copy(); + virtual HashMap * serializable(); + virtual void importSerializable(HashMap * serializable); + + public: // private + static void * createObject(); + + private: + int mType; + union { + bool boolValue; + char charValue; + unsigned char unsignedCharValue; + short shortValue; + unsigned short unsignedShortValue; + int intValue; + unsigned int unsignedIntValue; + long longValue; + unsigned long unsignedLongValue; + long long longLongValue; + unsigned long long unsignedLongLongValue; + float floatValue; + double doubleValue; + void * pointerValue; + struct { + char * data; + int length; + } dataValue; + } mValue; + Value(); + + public: // private + virtual int type(); + + }; + +} + +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/MailCore.h b/MailCore.framework/Versions/A/Headers/MailCore.h new file mode 100644 index 0000000..8b0897f --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/MailCore.h @@ -0,0 +1,17 @@ +// +// mailcore.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/10/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_MAILCORE_H + +#define MAILCORE_MAILCORE_H + +#include +#include +#include + +#endif diff --git a/MailCore.framework/Versions/A/Headers/NSArray+MCO.h b/MailCore.framework/Versions/A/Headers/NSArray+MCO.h new file mode 100644 index 0000000..fd0cc6a --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/NSArray+MCO.h @@ -0,0 +1,31 @@ +// +// NSArray+MCO.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/29/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_NSARRAY_MCO_H + +#define MAILCORE_NSARRAY_MCO_H + +#import + +#ifdef __cplusplus +namespace mailcore { + class Array; +} +#endif + +@interface NSArray (MCO) + +#ifdef __cplusplus ++ (NSArray *) mco_arrayWithMCArray:(mailcore::Array *)array; + +- (mailcore::Array *) mco_mcArray; +#endif + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/NSData+MCO.h b/MailCore.framework/Versions/A/Headers/NSData+MCO.h new file mode 100644 index 0000000..ddb0959 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/NSData+MCO.h @@ -0,0 +1,31 @@ +// +// NSData+MCO.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/21/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_NSDATA_MCO_H + +#define MAILCORE_NSDATA_MCO_H + +#import + +#ifdef __cplusplus +namespace mailcore { + class Data; +} +#endif + +@interface NSData (MCO) + +#ifdef __cplusplus ++ (NSData *) mco_dataWithMCData:(mailcore::Data *)cppData; + +- (mailcore::Data *) mco_mcData; +#endif + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/NSDictionary+MCO.h b/MailCore.framework/Versions/A/Headers/NSDictionary+MCO.h new file mode 100644 index 0000000..3479830 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/NSDictionary+MCO.h @@ -0,0 +1,31 @@ +// +// NSDictionary+MCO.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/29/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_NSDICTIONARY_MCO_H + +#define MAILCORE_NSDICTIONARY_MCO_H + +#import + +#ifdef __cplusplus +namespace mailcore { + class HashMap; +} +#endif + +@interface NSDictionary (MCO) + +#ifdef __cplusplus ++ (NSDictionary *) mco_dictionaryWithMCHashMap:(mailcore::HashMap *)hashmap; + +- (mailcore::HashMap *) mco_mcHashMap; +#endif + +@end + +#endif \ No newline at end of file diff --git a/MailCore.framework/Versions/A/Headers/NSError+MCO.h b/MailCore.framework/Versions/A/Headers/NSError+MCO.h new file mode 100644 index 0000000..027796e --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/NSError+MCO.h @@ -0,0 +1,19 @@ +// +// Created by mronge on 1/31/13. +// + +#ifndef MAILCORE_NSERROR_MCO_H + +#define MAILCORE_NSERROR_MCO_H + +#import + +#import + +@interface NSError (MCO) +#ifdef __cplusplus ++ (NSError *) mco_errorWithErrorCode:(mailcore::ErrorCode)code; +#endif +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/NSIndexSet+MCO.h b/MailCore.framework/Versions/A/Headers/NSIndexSet+MCO.h new file mode 100644 index 0000000..66aa522 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/NSIndexSet+MCO.h @@ -0,0 +1,18 @@ +// +// NSIndexSet+MCO.h +// mailcore2 +// +// Created by Hoa V. DINH on 9/10/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#import + +@class MCOIndexSet; + +@interface NSIndexSet (MCO) + +/** Returns a MCOIndexSet from an NSIndexSet */ +- (MCOIndexSet *) mcoIndexSet; + +@end diff --git a/MailCore.framework/Versions/A/Headers/NSObject+MCO.h b/MailCore.framework/Versions/A/Headers/NSObject+MCO.h new file mode 100644 index 0000000..923cc26 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/NSObject+MCO.h @@ -0,0 +1,109 @@ +// +// NSObject+MCO.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/29/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_NSOBJECT_MCO_H + +#define MAILCORE_NSOBJECT_MCO_H + +#import + +#ifdef __cplusplus +#include +#endif + +#ifdef __cplusplus +namespace mailcore { + class Object; +} +#endif + +#define MCO_NATIVE_INSTANCE ((nativeType *) [self mco_mcObject]) + +#define MCO_TO_OBJC(mcValue) \ + [NSObject mco_objectWithMCObject:((mailcore::Object *) (mcValue))] + +#define MCO_FROM_OBJC(type, objcValue) \ + ((type *) [(objcValue) mco_mcObject]) + +#define MCO_OBJC_BRIDGE_SET(setter, mcValueType, objcValue) \ + MCO_NATIVE_INSTANCE->setter((mcValueType *) [(objcValue) mco_mcObject]) + +#define MCO_OBJC_BRIDGE_GET(getter) \ + [NSObject mco_objectWithMCObject:MCO_NATIVE_INSTANCE->getter()] + +#define MCO_OBJC_SYNTHESIZE_TYPE(objcType, mcType, setter, getter) \ +- (objcType *) getter \ +{ \ +return MCO_OBJC_BRIDGE_GET(getter); \ +} \ +\ +- (void) setter:(objcType *)getter \ +{ \ +MCO_OBJC_BRIDGE_SET(setter, mcType, getter); \ +} + +#define MCO_OBJC_SYNTHESIZE(type, setter, getter) \ + MCO_OBJC_SYNTHESIZE_TYPE(MCO ## type, mailcore::type, setter, getter) + +#define MCO_OBJC_SYNTHESIZE_SCALAR(objcType, mcType, setter, getter) \ +- (objcType) getter \ +{ \ +return (objcType) MCO_NATIVE_INSTANCE->getter(); \ +} \ +\ +- (void) setter:(objcType)getter \ +{ \ +MCO_NATIVE_INSTANCE->setter((mcType) getter); \ +} + +#define MCO_OBJC_SYNTHESIZE_STRING(setter, getter) MCO_OBJC_SYNTHESIZE_TYPE(NSString, mailcore::String, setter, getter) +#define MCO_OBJC_SYNTHESIZE_ARRAY(setter, getter) MCO_OBJC_SYNTHESIZE_TYPE(NSArray, mailcore::Array, setter, getter) +#define MCO_OBJC_SYNTHESIZE_DATA(setter, getter) MCO_OBJC_SYNTHESIZE_TYPE(NSData, mailcore::Data, setter, getter) +#define MCO_OBJC_SYNTHESIZE_HASHMAP(setter, getter) MCO_OBJC_SYNTHESIZE_TYPE(NSDictionary, mailcore::HashMap, setter, getter) +#define MCO_OBJC_SYNTHESIZE_BOOL(setter, getter) MCO_OBJC_SYNTHESIZE_SCALAR(BOOL, bool, setter, getter) + +#define MCO_OBJC_SYNTHESIZE_DATE(setter, getter) \ +- (NSDate *) getter \ +{ \ + return [NSDate dateWithTimeIntervalSince1970:MCO_NATIVE_INSTANCE->getter()]; \ +} \ +\ +- (void) setter:(NSDate *)getter \ +{ \ + MCO_NATIVE_INSTANCE->setter([getter timeIntervalSince1970]); \ +} + +#define MCO_SYNTHESIZE_NSCODING \ +- (id) initWithCoder:(NSCoder *)coder \ +{ \ + mailcore::HashMap * serializable = MCO_FROM_OBJC(mailcore::HashMap, [coder decodeObjectForKey:@"info"]); \ + self = MCO_TO_OBJC(mailcore::Object::objectWithSerializable(serializable)); \ + [self retain]; \ + return self; \ +} \ +\ +- (void) encodeWithCoder:(NSCoder *)coder \ +{ \ + [coder encodeObject:MCO_TO_OBJC(MCO_FROM_OBJC(nativeType, self)->serializable()) forKey:@"info"]; \ +} + +@interface NSObject (MCO) + +#ifdef __cplusplus ++ (id) mco_objectWithMCObject:(mailcore::Object *)object; + +- (mailcore::Object *) mco_mcObject; +#endif + +@end + +#ifdef __cplusplus +extern void MCORegisterClass(Class aClass, const std::type_info * info); +#endif + +#endif diff --git a/MailCore.framework/Versions/A/Headers/NSString+MCO.h b/MailCore.framework/Versions/A/Headers/NSString+MCO.h new file mode 100644 index 0000000..71e99a4 --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/NSString+MCO.h @@ -0,0 +1,41 @@ +// +// NSString+MCO.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 1/21/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_NSSTRING_MCO_H + +#define MAILCORE_NSSTRING_MCO_H + +#import + +#ifdef __cplusplus +namespace mailcore { + class String; + class Object; +} +#endif + +@interface NSString (MCO) + +#ifdef __cplusplus ++ (NSString *) mco_stringWithMCString:(mailcore::String *)cppString; ++ (NSString *) mco_stringWithMCObject:(mailcore::Object *)object; + +- (mailcore::String *) mco_mcString; +#endif + +- (NSString *) mco_flattenHTML; +- (NSString *) mco_flattenHTMLAndShowBlockquote:(BOOL)showBlockquote; +- (NSString *) mco_flattenHTMLAndShowBlockquote:(BOOL)showBlockquote showLink:(BOOL)showLink; + +- (NSString *) mco_htmlEncodedString; +- (NSString *) mco_cleanedHTMLString; +- (NSString *) mco_strippedWhitespace; + +@end + +#endif diff --git a/MailCore.framework/Versions/A/Headers/NSValue+MCO.h b/MailCore.framework/Versions/A/Headers/NSValue+MCO.h new file mode 100644 index 0000000..007662b --- /dev/null +++ b/MailCore.framework/Versions/A/Headers/NSValue+MCO.h @@ -0,0 +1,31 @@ +// +// NSValue+MCO.h +// mailcore2 +// +// Created by DINH Viêt Hoà on 3/21/13. +// Copyright (c) 2013 MailCore. All rights reserved. +// + +#ifndef MAILCORE_NSVALUE_MCO_H + +#define MAILCORE_NSVALUE_MCO_H + +#import + +#ifdef __cplusplus +namespace mailcore { + class Value; +} +#endif + +@interface NSValue (MCO) + +#ifdef __cplusplus ++ (NSValue *) mco_valueWithMCValue:(mailcore::Value *)value; + +- (mailcore::Value *) mco_mcValue; +#endif + +@end + +#endif diff --git a/MailCore.framework/Versions/A/MailCore b/MailCore.framework/Versions/A/MailCore new file mode 100755 index 0000000..d1ad861 Binary files /dev/null and b/MailCore.framework/Versions/A/MailCore differ diff --git a/MailCore.framework/Versions/A/Resources/Info.plist b/MailCore.framework/Versions/A/Resources/Info.plist new file mode 100644 index 0000000..24854ef --- /dev/null +++ b/MailCore.framework/Versions/A/Resources/Info.plist @@ -0,0 +1,42 @@ + + + + + BuildMachineOSBuild + 13E28 + CFBundleDevelopmentRegion + English + CFBundleExecutable + MailCore + CFBundleIdentifier + com.libmailcore.MailCore + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + MailCore + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 5B1008 + DTPlatformVersion + GM + DTSDKBuild + 13C64 + DTSDKName + macosx10.9 + DTXcode + 0511 + DTXcodeBuild + 5B1008 + NSHumanReadableCopyright + Copyright © 2013 MailCore. All rights reserved. + + diff --git a/MailCore.framework/Versions/A/Resources/providers.json b/MailCore.framework/Versions/A/Resources/providers.json new file mode 100644 index 0000000..b53e617 --- /dev/null +++ b/MailCore.framework/Versions/A/Resources/providers.json @@ -0,0 +1,1022 @@ +{ + "mobileme":{ + "servers":{ + "imap":[ + { + "port":993, + "hostname":"mail.me.com", + "ssl":true + }, + { + "port":143, + "hostname":"mail.me.com", + "starttls":true + } + ], + "smtp":[ + { + "port":587, + "hostname":"smtp.me.com", + "starttls":true + } + ] + }, + "domain-match":[ + "me\\.com", + "mac\\.com", + "icloud\\.com" + ], + "mailboxes":{ + "drafts":"Drafts", + "allmail":"Archive", + "spam":"Junk", + "sentmail":"Sent Messages", + "trash":"Deleted Messages" + } + }, + "dreamhost":{ + "servers":{ + "imap":[ + { + "port":993, + "hostname":"mail.{domain}", + "ssl":true + }, + { + "port":143, + "hostname":"mail.{domain}", + "starttls":true + } + ], + "smtp":[ + { + "port":465, + "hostname":"mail.{domain}", + "ssl":true + }, + { + "port":587, + "hostname":"mail.{domain}", + "starttls":true + }, + { + "port":25, + "hostname":"mail.{domain}", + "starttls":true + } + ] + }, + "mx-match":[ + "mx1\\.sub3\\.homie\\.mail\\.dreamhost\\.com", + "mx2\\.sub3\\.homie\\.mail\\.dreamhost\\.com", + "mx1\\.sub4\\.homie\\.mail\\.dreamhost\\.com", + "mx2\\.sub4\\.homie\\.mail\\.dreamhost\\.com", + "mx1\\.sub5\\.homie\\.mail\\.dreamhost\\.com", + "mx2\\.sub5\\.homie\\.mail\\.dreamhost\\.com", + "mx1\\.balanced\\.homie\\.mail\\.dreamhost\\.com", + "mx2\\.balanced\\.homie\\.mail\\.dreamhost\\.com" + ], + "mailboxes":{ + "drafts":"Drafts", + "allmail":"Archive", + "spam":"Junk", + "sentmail":"Sent Messages", + "trash":"Deleted Messages" + } + }, + "insecure-default":{ + "servers":{ + "imap":[ + { + "port":143, + "starttls":true + }, + { + "port":143 + } + ], + "smtp":[ + { + "port":587, + "starttls":true + }, + { + "port":25, + "starttls":true + }, + { + "port":587 + }, + { + "port":25 + } + ] + }, + "mailboxes":{ + "drafts":"Drafts", + "allmail":"Archive", + "spam":"Junk", + "sentmail":"Sent Messages", + "trash":"Deleted Messages" + } + }, + "euro-apple":{ + "servers":{ + "imap":[ + { + "port":993, + "hostname":"phonehome.euro.apple.com", + "ssl":true + } + ], + "smtp":[ + { + "port":587, + "hostname":"phonehome.apple.com", + "starttls":true + } + ] + }, + "domain-match":[ + "euro\\.apple\\.com" + ], + "mailboxes":{ + "drafts":"Drafts", + "allmail":"Archive", + "spam":"Junk", + "sentmail":"Sent Messages", + "trash":"Deleted Messages" + } + }, + "default":{ + "servers":{ + "imap":[ + { + "port":993, + "ssl":true + }, + { + "port":143, + "starttls":true + } + ], + "smtp":[ + { + "port":465, + "ssl":true + }, + { + "port":587, + "starttls":true + }, + { + "port":25, + "starttls":true + } + ] + }, + "mailboxes":{ + "drafts":"Drafts", + "allmail":"Archive", + "spam":"Junk", + "sentmail":"Sent Messages", + "trash":"Deleted Messages" + } + }, + "insecure-fixed-port":{ + "servers":{ + "imap":[ + { + "starttls":true + }, + { + + } + ], + "smtp":[ + { + "starttls":true + }, + { + + } + ] + }, + "mailboxes":{ + "drafts":"Drafts", + "allmail":"Archive", + "spam":"Junk", + "sentmail":"Sent Messages", + "trash":"Deleted Messages" + } + }, + "aol":{ + "servers":{ + "imap":[ + { + "port":993, + "hostname":"imap.aol.com", + "ssl":true + }, + { + "port":143, + "hostname":"imap.aol.com", + "starttls":true + } + ], + "smtp":[ + { + "port":587, + "hostname":"smtp.aol.com", + "starttls":true + }, + { + "port":465, + "hostname":"smtp.aol.com", + "ssl":true + }, + { + "port":25, + "hostname":"smtp.aol.com", + "starttls":true + } + ] + }, + "domain-match":[ + "aim\\.com", + "aol\\..*", + "jp\\.aol\\.com" + ], + "mailboxes":{ + "drafts":"Drafts", + "allmail":"Saved", + "spam":"Spam", + "sentmail":"Sent", + "trash":"Trash" + } + }, + "yahoo.co.jp":{ + "servers":{ + "imap":[ + { + "port":993, + "hostname":"imap.mail.yahoo.co.jp", + "ssl":true + } + ], + "smtp":[ + { + "port":465, + "hostname":"smtp.mail.yahoo.co.jp", + "ssl":true + } + ] + }, + "domain-match":[ + "yahoo\\.co\\.jp" + ], + "mailboxes":{ + "drafts":"Draft", + "allmail":"Archive", + "spam":"Bulk Mail", + "sentmail":"Sent", + "trash":"Trash" + } + }, + "yahoo":{ + "servers":{ + "imap":[ + { + "port":993, + "hostname":"imap.mail.yahoo.com", + "ssl":true + }, + { + "port":143, + "hostname":"imap.mail.yahoo.com", + "starttls":true + } + ], + "smtp":[ + { + "port":465, + "hostname":"smtp.mail.yahoo.com", + "ssl":true + } + ] + }, + "mx-match":[ + "mta5\\.am0\\.yahoodns\\.net", + "mta6\\.am0\\.yahoodns\\.net", + "mta7\\.am0\\.yahoodns\\.net" + ], + "domain-match":[ + "yahoo\\..*", + "ymail\\.com", + "rocketmail\\.com", + "xtra\\.co\\.nz" + ], + "domain-exclude":[ + "yahoo\\.co\\.jp" + ], + "mailboxes":{ + "drafts":"Draft", + "allmail":"Archive", + "spam":"Bulk Mail", + "sentmail":"Sent", + "trash":"Trash" + } + }, + "gmail":{ + "servers":{ + "imap":[ + { + "port":993, + "hostname":"imap.gmail.com", + "ssl":true + } + ], + "smtp":[ + { + "port":587, + "hostname":"smtp.gmail.com", + "starttls":true + }, + { + "port":465, + "hostname":"smtp.gmail.com", + "ssl":true + }, + { + "port":25, + "hostname":"smtp.gmail.com", + "starttls":true + } + ] + }, + "mx-match":[ + "aspmx2\\.googlemail\\.com", + "aspmx\\.l\\.google\\.com", + "aspmx3\\.googlemail\\.com", + "alt1\\.aspmx\\.l\\.google\\.com", + "alt2\\.aspmx\\.l\\.google\\.com", + "alt1\\.gmail-smtp-in\\.l\\.google\\.com", + "alt2\\.gmail-smtp-in\\.l\\.google\\.com", + "alt3\\.gmail-smtp-in\\.l\\.google\\.com", + "alt4\\.gmail-smtp-in\\.l\\.google\\.com", + "gmail-smtp-in\\.l\\.google\\.com" + ], + "domain-match":[ + "googlemail\\.com", + "gmail\\.com" + ], + "mailboxes":{ + "sentmail":"[Gmail]/Sent Mail", + "allmail":"[Gmail]/All Mail", + "starred":"[Gmail]/Starred", + "trash":"[Gmail]/Trash", + "drafts":"[Gmail]/Drafts", + "spam":"[Gmail]/Spam", + "important":"[Gmail]/Important" + } + }, + "gmx":{ + "servers":{ + "imap":[ + { + "port":993, + "hostname":"imap.gmx.com", + "ssl":true + }, + { + "port":143, + "hostname":"imap.gmx.com", + "starttls":true + } + ], + "smtp":[ + { + "port":587, + "hostname":"mail.gmx.com", + "starttls":true + }, + { + "port":465, + "hostname":"mail.gmx.com", + "ssl":true + }, + { + "port":25, + "hostname":"mail.gmx.com", + "starttls":true + } + ] + }, + "domain-match":[ + "gmx\\..*", + "caramail\\..*" + ], + "mailboxes":{ + "drafts":"Drafts", + "allmail":"Archive", + "spam":"Spam", + "sentmail":"Sent", + "trash":"Trash" + } + }, + "fastmail":{ + "servers":{ + "imap":[ + { + "port":993, + "hostname":"mail.messagingengine.com", + "ssl":true + }, + { + "port":143, + "hostname":"mail.messagingengine.com", + "starttls":true + } + ], + "smtp":[ + { + "port":587, + "hostname":"mail.messagingengine.com", + "starttls":true + }, + { + "port":465, + "hostname":"mail.messagingengine.com", + "ssl":true + }, + { + "port":25, + "hostname - 2":"mail.messagingengine.com", + "starttls":true + } + ] + }, + "domain-match":[ + "123mail\\.org", + "fastmail\\..*", + "airpost\\.net", + "eml\\.cc", + "fmail\\.co\\.uk", + "fmgirl\\.com", + "fmguy\\.com", + "mailbolt\\.com", + "mailcan\\.com", + "mailhaven\\.com", + "mailmight\\.com", + "ml1\\.net", + "mm\\.st", + "myfastmail\\.com", + "proinbox\\.com", + "promessage\\.com", + "rushpost\\.com", + "sent\\.as", + "sent\\.at", + "sent\\.com", + "speedymail\\.org", + "warpmail\\.net", + "xsmail\\.com", + "150mail\\.com", + "150ml\\.com", + "16mail\\.com", + "2-mail\\.com", + "4email\\.net", + "50mail\\.com", + "allmail\\.net", + "bestmail\\.us", + "cluemail\\.com", + "elitemail\\.org", + "emailcorner\\.net", + "emailengine\\.net", + "emailengine\\.org", + "emailgroups\\.net", + "emailplus\\.org", + "emailuser\\.net", + "f-m\\.fm", + "fast-email\\.com", + "fast-mail\\.org", + "fastem\\.com", + "fastemail\\.us", + "fastemailer\\.com", + "fastest\\.cc", + "fastimap\\.com", + "fastmailbox\\.net", + "fastmessaging\\.com", + "fea\\.st", + "fmailbox\\.com", + "ftml\\.net", + "h-mail\\.us", + "hailmail\\.net", + "imap-mail\\.com", + "imap\\.cc", + "imapmail\\.org", + "inoutbox\\.com", + "internet-e-mail\\.com", + "internet-mail\\.org", + "internetemails\\.net", + "internetmailing\\.net", + "jetemail\\.net", + "justemail\\.net", + "letterboxes\\.org", + "mail-central\\.com", + "mail-page\\.com", + "mailandftp\\.com", + "mailas\\.com", + "mailc\\.net", + "mailforce\\.net", + "mailftp\\.com", + "mailingaddress\\.org", + "mailite\\.com", + "mailnew\\.com", + "mailsent\\.net", + "mailservice\\.ms", + "mailup\\.net", + "mailworks\\.org", + "mymacmail\\.com", + "nospammail\\.net", + "ownmail\\.net", + "petml\\.com", + "postinbox\\.com", + "postpro\\.net", + "realemail\\.net", + "reallyfast\\.biz", + "reallyfast\\.info", + "speedpost\\.net", + "ssl-mail\\.com", + "swift-mail\\.com", + "the-fastest\\.net", + "the-quickest\\.com", + "theinternetemail\\.com", + "veryfast\\.biz", + "veryspeedy\\.net", + "yepmail\\.net", + "your-mail\\.com", + "operamail\\.com" + ], + "mailboxes":{ + "drafts":"Drafts", + "allmail":"Archive", + "spam":"Junk Mail", + "sentmail":"Sent Items", + "trash":"Trash" + } + }, + "apple":{ + "servers":{ + "imap":[ + { + "port":993, + "hostname":"phonehome.apple.com", + "ssl":true + } + ], + "smtp":[ + { + "port":465, + "tls":true, + "hostname":"phonehome.apple.com" + }, + { + "port":587, + "hostname":"phonehome.apple.com", + "starttls":true + } + ] + }, + "domain-match":[ + "apple\\.com" + ], + "mailboxes":{ + "drafts":"Drafts", + "allmail":"Archive", + "spam":"Junk", + "sentmail":"Sent Messages", + "trash":"Deleted Messages" + } + }, + "asia-apple":{ + "servers":{ + "imap":[ + { + "port":993, + "hostname":"phonehome.asia.apple.com", + "ssl":true + } + ], + "smtp":[ + { + "port":465, + "tls":true, + "hostname":"phonehome.asia.apple.com" + }, + { + "port":587, + "hostname":"phonehome.asia.apple.com", + "starttls":true + } + ] + }, + "domain-match":[ + "asia\\.apple\\.com" + ], + "mailboxes":{ + "drafts":"Drafts", + "allmail":"Archive", + "spam":"Junk", + "sentmail":"Sent Messages", + "trash":"Deleted Messages" + } + }, + "rackspace":{ + "servers":{ + "imap":[ + { + "port":993, + "hostname":"secure.emailsrvr.com", + "ssl":true + }, + { + "port":143, + "hostname":"secure.emailsrvr.com", + "starttls":true + }, + { + "port":143, + "hostname":"secure.emailsrvr.com" + } + ], + "smtp":[ + { + "port":465, + "hostname":"secure.emailsrvr.com", + "ssl":true + }, + { + "port":587, + "hostname":"secure.emailsrvr.com", + "starttls":true + }, + { + "port":25, + "hostname":"secure.emailsrvr.com", + "starttls":true + }, + { + "port":587, + "hostname":"secure.emailsrvr.com" + }, + { + "port":25, + "hostname":"secure.emailsrvr.com" + } + ] + }, + "mx-match":[ + "mx1\\.emailsrvr\\.com", + "mx2\\.emailsrvr\\.com" + ], + "mailboxes":{ + "drafts":"Drafts", + "allmail":"Archive", + "spam":"Junk", + "sentmail":"Sent Messages", + "trash":"Deleted Messages" + } + }, + "zimbra":{ + "servers":{ + "imap":[ + { + "port":993, + "ssl":true + }, + { + "port":143, + "starttls":true + } + ], + "smtp":[ + { + "port":587, + "starttls":true + }, + { + "port":465, + "ssl":true + }, + { + "port":25, + "starttls":true + } + ] + }, + "mailboxes":{ + "drafts":"Drafts", + "allmail":"Archive", + "spam":"Junk", + "sentmail":"Sent", + "trash":"Trash" + } + }, + "ovh":{ + "servers":{ + "imap":[ + { + "port":993, + "hostname":"mail.{domain}", + "ssl":true + }, + { + "port":143, + "hostname":"mail.{domain}" + } + ], + "smtp":[ + { + "port":465, + "hostname":"mail.{domain}", + "ssl":true + }, + { + "port":587, + "hostname":"mail.{domain}" + }, + { + "port":25, + "hostname":"mail.{domain}" + } + ] + }, + "mx-match":[ + "mx\\d\\.ovh\\.net" + ], + "mailboxes":{ + "drafts":"Drafts", + "allmail":"Archive", + "spam":"Junk", + "sentmail":"Sent Messages", + "trash":"Deleted Messages" + } + }, + "fixed-port":{ + "servers":{ + "imap":[ + { + "ssl":true + }, + { + "starttls":true + } + ], + "smtp":[ + { + "starttls":true + }, + { + "ssl":true + } + ] + }, + "mailboxes":{ + "drafts":"Drafts", + "allmail":"Archive", + "spam":"Junk", + "sentmail":"Sent Messages", + "trash":"Deleted Messages" + } + }, + "outlook":{ + "servers":{ + "imap":[ + { + "port":993, + "hostname":"imap-mail.outlook.com", + "ssl":true + } + ], + "smtp":[ + { + "port":25, + "hostname":"smtp-mail.outlook.com", + "starttls":true + } + ] + }, + "mx-match":[ + ".*\\.mail\\.outlook\\.com" + ], + "domain-match":[ + "outlook\\.com", + "outlook\\.com\\.ar", + "outlook\\.com\\.au", + "outlook\\.at", + "outlook\\.be", + "outlook\\.com\\.br", + "outlook\\.cl", + "outlook\\.cz", + "outlook\\.dk", + "outlook\\.fr", + "outlook\\.de", + "outlook\\.com\\.gr", + "outlook\\.co\\.id", + "outlook\\.ie", + "outlook\\.it", + "outlook\\.hu", + "outlook\\.jp", + "outlook\\.kr", + "outlook\\.lv", + "outlook\\.my", + "outlook\\.co\\.nz", + "outlook\\.com\\.pe", + "outlook\\.ph", + "outlook\\.pt", + "outlook\\.sa", + "outlook\\.sg", + "outlook\\.sk", + "outlook\\.es", + "outlook\\.co\\.th", + "outlook\\.com\\.tr", + "outlook\\.com\\.vn", + "hotmail\\.com", + "hotmail\\.co\\.uk", + "hotmail\\.fr", + "hotmail\\.de", + "hotmail\\.be", + "hotmail\\.com\\.ar", + "hotmail\\.es", + "hotmail\\.com\\.mx", + "hotmail\\.com", + "live\\.com", + "live\\.fr", + "live\\.de", + "live\\.be", + "live\\.com\\.ar", + "live\\.com\\.mx" + ], + "mailboxes":{ + "drafts":"Drafts", + "allmail":"Archive", + "spam":"Junk", + "sentmail":"Sent Messages", + "trash":"Deleted Messages" + } + }, + "qq": { + "servers": { + "imap": [ + { + "port": 993, + "hostname": "imap.exmail.qq.com", + "ssl": true + } + ], + "smtp": [ + { + "port": 465, + "hostname": "smtp.exmail.qq.com", + "ssl": true + } + ] + }, + "domain-match": [ + "qq\\.com" + ], + "mailboxes": { + "drafts": "Drafts", + "spam": "Junk", + "sentmail": "Sent Messages", + "trash": "Deleted Messages" + } + }, + "openmailbox": { + "servers": { + "imap": [ + { + "port": 143, + "hostname": "imap.openmailbox.org", + "starttls": true + } + ], + "smtp": [ + { + "port": 587, + "hostname": "smtp.openmailbox.org", + "starttls": true + } + ] + }, + "domain-match": [ + "openmailbox\\.org" + ], + "mailboxes": { + "drafts": "Drafts", + "allmail": "Archive", + "spam": "Spam", + "sentmail": "Sent", + "trash": "Trash" + } + }, + "mailru": { + "servers": { + "imap": [ + { + "port": 143, + "hostname": "imap.mail.ru", + "starttls": true + }, + { + "port": 993, + "hostname": "imap.mail.ru", + "ssl": true + } + ], + "smtp": [ + { + "port": 465, + "hostname": "smtp.mail.ru", + "ssl": true + } + ] + + }, + "domain-match": [ + "mail\\.ru", + "inbox\\.ru", + "list\\.ru", + "bk\\.ru", + "mail\\.ua" + ], + "mailboxes": { + "drafts": "Черновики", + "spam": "Спам", + "sentmail": "Отправленные", + "trash": "Корзина" + } + }, + "comcast": { + "servers": { + "pop": [{ + "port": 995, + "hostname": "mail.comcast.net", + "ssl": true + }, { + "port": 110, + "hostname": "mail.comcast.net", + "ssl": true + }], + "smtp": [{ + "port": 587, + "hostname": "smtp.comcast.net", + "starttls": true + }, { + "port": 465, + "hostname": "smtp.comcast.net", + "ssl": true + }] + }, + "mx-match": [ + "mx1\\.comcast\\.net", + "mx2\\.comcast\\.net" + ] + }, + "verizon": { + "servers": { + "pop": [{ + "port": 995, + "hostname": "pop.verizon.net", + "ssl": true + }], + "smtp": [{ + "port": 465, + "hostname": "smtp.verizon.net", + "ssl": true + }] + + }, + "mx-match": [ + "relay\\.verizon\\.net" + ] + }, + "rcn": { + "servers": { + "pop": [{ + "port": 110, + "hostname": "pop.rcn.com", + "ssl": true + }], + "smtp": [{ + "port": 25, + "hostname": "smtp.rcn.com", + "ssl": true + }] + + }, + "mx-match": [ + "mx\\.rcn\\.com" + ] + } +} diff --git a/MailCore.framework/Versions/Current b/MailCore.framework/Versions/Current new file mode 120000 index 0000000..8c7e5a6 --- /dev/null +++ b/MailCore.framework/Versions/Current @@ -0,0 +1 @@ +A \ No newline at end of file diff --git a/MailCore2 b/MailCore2 new file mode 160000 index 0000000..d3781ee --- /dev/null +++ b/MailCore2 @@ -0,0 +1 @@ +Subproject commit d3781eeee6c4f633cc1decfd1324a439f8633240 diff --git a/build b/build new file mode 120000 index 0000000..2ae4896 --- /dev/null +++ b/build @@ -0,0 +1 @@ +/Users/grmrgecko/Library/Developer/Xcode/DerivedData/EmailScheduler-alawimlfsywsooccpxhjyokcvpjg/Build/Products \ No newline at end of file diff --git a/com.mrgeckosmedia.EmailScheduler.plist b/com.mrgeckosmedia.EmailScheduler.plist new file mode 100644 index 0000000..a3c550e --- /dev/null +++ b/com.mrgeckosmedia.EmailScheduler.plist @@ -0,0 +1,16 @@ + + + + + KeepAlive + + Label + com.mrgeckosmedia.EmailScheduler + ProgramArguments + + /EmailScheduler/EmailScheduler + + RunAtLoad + + + diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..4f4d708 --- /dev/null +++ b/readme.md @@ -0,0 +1,6 @@ +#EmailScheduler +This was designed for my server since I use an ISP which blocks port 25 and thus I had to write a work around to send email. + +To use, set the dictionary ``emailAddresses`` up with passwords/email addresses and if you want to setup a secure email where the email is removed from gmail after sending, find ``password@birdim.com`` and read the comment. + +Use ``com.mrgeckosmedia.EmailScheduler.plist`` to auto start at boot. \ No newline at end of file