OCXMLParser.m 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. //
  2. // OCXMLParser.m
  3. // webdav
  4. //
  5. // Copyright (C) 2016, ownCloud GmbH. ( http://www.owncloud.org/ )
  6. //
  7. // Permission is hereby granted, free of charge, to any person obtaining a copy
  8. // of this software and associated documentation files (the "Software"), to deal
  9. // in the Software without restriction, including without limitation the rights
  10. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. // copies of the Software, and to permit persons to whom the Software is
  12. // furnished to do so, subject to the following conditions:
  13. // The above copyright notice and this permission notice shall be included in
  14. // all copies or substantial portions of the Software.
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. //
  24. // Add Support for Quota
  25. // quotaUsed and quotaAvailable
  26. //
  27. // Add Support for Favorite
  28. // isFavorite
  29. //
  30. // Author Marino Faggiana <marino.faggiana@nextcloud.com>
  31. //
  32. #import "OCXMLParser.h"
  33. #import "NSString+Encode.h"
  34. NSString *OCCWebDAVContentTypeKey = @"contenttype";
  35. NSString *OCCWebDAVETagKey = @"etag";
  36. NSString *OCCWebDAVHREFKey = @"href";
  37. NSString *OCCWebDAVURIKey = @"uri";
  38. @implementation OCXMLParser
  39. @synthesize directoryList=_directoryList;
  40. @synthesize currentFile=_currentFile;
  41. /*
  42. * Method that init the parse with the xml data from the server
  43. * @data -> XML webDav data from the owncloud server
  44. */
  45. - (void)initParserWithData: (NSData*)data{
  46. _directoryList = [[NSMutableArray alloc]init];
  47. NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
  48. [parser setDelegate:self];
  49. [parser parse];
  50. }
  51. #pragma mark - XML Parser Delegate Methods
  52. /*
  53. * Method that init parse process.
  54. */
  55. - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
  56. if (!_xmlChars) {
  57. _xmlChars = [NSMutableString string];
  58. }
  59. //NSLog(@"_xmlChars: %@", _xmlChars);
  60. [_xmlChars setString:@""];
  61. if ([elementName isEqualToString:@"d:response"]) {
  62. _xmlBucket = [NSMutableDictionary dictionary];
  63. }
  64. }
  65. /*
  66. * Util method to make a NSDate object from a string from xml
  67. * @dateString -> Data string from xml
  68. */
  69. + (NSDate*)parseDateString:(NSString*)dateString {
  70. //Parse the date in all the formats
  71. NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
  72. /*In most cases the best locale to choose is "en_US_POSIX", a locale that's specifically designed to yield US English results regardless of both user and system preferences. "en_US_POSIX" is also invariant in time (if the US, at some point in the future, changes the way it formats dates, "en_US" will change to reflect the new behaviour, but "en_US_POSIX" will not). It will behave consistently for all users.*/
  73. [dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]];
  74. //This is the format for the concret locale used
  75. [dateFormatter setDateFormat:@"EEE, dd MMM y HH:mm:ss zzz"];
  76. NSDate *theDate = nil;
  77. NSError *error = nil;
  78. if (![dateFormatter getObjectValue:&theDate forString:dateString range:nil error:&error]) {
  79. NSLog(@"Date '%@' could not be parsed: %@", dateString, error);
  80. }
  81. return theDate;
  82. }
  83. - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
  84. // NSLog(@"elementName: %@:%@", elementName,_xmlChars);
  85. if ([elementName isEqualToString:@"d:href"]) {
  86. if ([_xmlChars hasPrefix:@"http"]) {
  87. NSURL *junk = [NSURL URLWithString:_xmlChars];
  88. BOOL trailingSlash = [_xmlChars hasSuffix:@"/"];
  89. [_xmlChars setString:[junk path]];
  90. if (trailingSlash) {
  91. [_xmlChars appendString:@"/"];
  92. }
  93. }
  94. //If has lenght, there are an item
  95. if ([_xmlChars length]) {
  96. //Create FileDto
  97. _currentFile = [[OCFileDto alloc] init];
  98. _currentFile.isDirectory = NO;
  99. [_xmlBucket setObject:[_xmlChars copy] forKey:OCCWebDAVURIKey];
  100. NSArray *splitedUrl = [_xmlChars componentsSeparatedByString:@"/"];
  101. //Check if the item is a folder or a file
  102. if([_xmlChars hasSuffix:@"/"]) {
  103. //It's a folder
  104. NSInteger fileNameLenght = [((NSString *)[splitedUrl objectAtIndex:[splitedUrl count]-2]) length];
  105. if ( fileNameLenght > 0) {
  106. //FileDto filepath
  107. _currentFile.filePath = [_xmlChars substringToIndex:[_xmlChars length] - (fileNameLenght+1)];
  108. } else {
  109. _currentFile.filePath = @"/";
  110. }
  111. } else {
  112. //It's a file
  113. NSInteger fileNameLenght = [((NSString *)[splitedUrl objectAtIndex:[splitedUrl count]-1]) length];
  114. if (fileNameLenght > 0) {
  115. _currentFile.filePath = [_xmlChars substringToIndex:[_xmlChars length] - fileNameLenght];
  116. }else {
  117. _currentFile.filePath = @"/";
  118. }
  119. }
  120. NSArray *foo = [_xmlChars componentsSeparatedByString: @"/"];
  121. NSString *lastBit;
  122. if([_xmlChars hasSuffix:@"/"]) {
  123. lastBit = [foo objectAtIndex: [foo count]-2];
  124. lastBit = [NSString stringWithFormat:@"%@/",lastBit];
  125. } else {
  126. lastBit = [foo objectAtIndex: [foo count]-1];
  127. }
  128. //NSString *lastBit = [_xmlChars substringFromIndex:_uriLength];
  129. //NSLog(@"lastBit:- %@",lastBit);
  130. if (isNotFirstFileOfList == YES) {
  131. [_xmlBucket setObject:lastBit forKey:OCCWebDAVHREFKey];
  132. _currentFile.fileName = lastBit;
  133. }
  134. self.currentFile.fileName = [self.currentFile.fileName stringByRemovingPercentEncoding];
  135. self.currentFile.filePath = [self.currentFile.filePath stringByRemovingPercentEncoding];
  136. isNotFirstFileOfList = YES;
  137. // //NSLog(@"1 _xmlBucked :- %@",_xmlBucket);
  138. }
  139. } else if ([elementName isEqualToString:@"d:getlastmodified"]) {
  140. //DATE
  141. // 'Thu, 30 Oct 2008 02:52:47 GMT'
  142. // Monday, 12-Jan-98 09:25:56 GMT
  143. // Value: HTTP-date ; defined in section 3.3.1 of RFC2068
  144. if ([_xmlChars length]) {
  145. NSDate *d = [[self class] parseDateString:_xmlChars];
  146. if (d) {
  147. //FildeDto Date
  148. _currentFile.date = [d timeIntervalSince1970];
  149. NSInteger colIdx = [elementName rangeOfString:@":"].location;
  150. [_xmlBucket setObject:d forKey:[elementName substringFromIndex:colIdx + 1]];
  151. }
  152. else {
  153. NSLog(@"Could not parse date string '%@' for '%@'", _xmlChars, elementName);
  154. }
  155. }
  156. } else if ([elementName isEqualToString:@"oc:id"]) {
  157. _currentFile.ocId = _xmlChars;
  158. } else if ([elementName hasSuffix:@":getetag"] && [_xmlChars length]) {
  159. //ETAG
  160. //NSLog(@"getetag: %@", _xmlChars);
  161. NSString *stringClean = _xmlChars;
  162. stringClean = [_xmlChars stringByReplacingOccurrencesOfString:@"\"" withString:@""];
  163. _currentFile.etag = [stringClean lowercaseString];
  164. } else if ([elementName hasSuffix:@":getcontenttype"] && [_xmlChars length]) {
  165. //CONTENT TYPE
  166. [_xmlBucket setObject:[_xmlChars copy] forKey:OCCWebDAVContentTypeKey];
  167. } else if([elementName hasSuffix:@"d:getcontentlength"] && [_xmlChars length]) {
  168. //SIZE
  169. //FileDto current size
  170. _currentFile.size = (long)[_xmlChars longLongValue];
  171. } else if ([elementName isEqualToString:@"oc:permissions"]) {
  172. _currentFile.permissions = _xmlChars;
  173. } else if ([elementName isEqualToString:@"d:collection"]) {
  174. _currentFile.isDirectory = YES;
  175. } else if ([elementName isEqualToString:@"d:response"]) {
  176. //NSLog(@"2 _xmlBucked :- %@",_xmlBucket);
  177. //Add to directoryList
  178. [_directoryList addObject:_currentFile];
  179. _currentFile = [[OCFileDto alloc] init];
  180. _xmlBucket = nil;
  181. } else if ([elementName isEqualToString:@"oc:favorite"]) {
  182. _currentFile.isFavorite = [_xmlChars boolValue];
  183. } else if ([elementName isEqualToString:@"x1:share-permissions"]) {
  184. _currentFile.permissions = _xmlChars;
  185. } else if ([elementName isEqualToString:@"nc:is-encrypted"]) {
  186. _currentFile.isEncrypted = [_xmlChars boolValue];
  187. }else if ([elementName isEqualToString:@"nc:trashbin-filename"]) {
  188. _currentFile.trashbinFileName = _xmlChars;
  189. }else if ([elementName isEqualToString:@"nc:trashbin-original-location"]) {
  190. _currentFile.trashbinOriginalLocation = _xmlChars;
  191. }else if ([elementName isEqualToString:@"nc:trashbin-deletion-time"]) {
  192. _currentFile.trashbinDeletionTime = (long)[_xmlChars longLongValue];
  193. } else if ([elementName isEqualToString:@"nc:has-preview"] && [_xmlChars length]) {
  194. _currentFile.hasPreview = [_xmlChars boolValue];
  195. }
  196. }
  197. - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
  198. [_xmlChars appendString:string];
  199. }
  200. - (void)parserDidEndDocument:(NSXMLParser *)parser{
  201. NSLog(@"Finish xml directory list parse");
  202. }
  203. @end