1/************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24#import "OOoSpotlightImporter.h" 25#import "OOoMetaDataParser.h" 26#import "OOoContentDataParser.h" 27 28#define CASESENSITIVITY (0) 29#define BUFFER_SIZE (4096) 30 31/* a dictionary to hold the UTIs */ 32static NSDictionary *uti2kind; 33 34@implementation OOoSpotlightImporter 35 36/* initialize is only called once the first time this class is loaded */ 37+ (void)initialize 38{ 39 static BOOL isInitialized = NO; 40 if (isInitialized == NO) { 41 NSMutableDictionary *temp = [NSMutableDictionary new]; 42 [temp setObject:@"OpenOffice.org 1.0 Text" forKey:@"org.openoffice.text"]; 43 [temp setObject:@"OpenDocument Text" forKey:@"org.oasis.opendocument.text"]; 44 [temp setObject:@"OpenOffice.org 1.0 Spreadsheet" forKey:@"org.openoffice.spreadsheet"]; 45 [temp setObject:@"OpenDocument Spreadsheet" forKey:@"org.oasis.opendocument.spreadsheet"]; 46 [temp setObject:@"OpenOffice.org 1.0 Presentation" forKey:@"org.openoffice.presentation"]; 47 [temp setObject:@"OpenDocument Presentation" forKey:@"org.oasis.opendocument.presentation"]; 48 [temp setObject:@"OpenOffice.org 1.0 Drawing" forKey:@"org.openoffice.graphics"]; 49 [temp setObject:@"OpenDocument Drawing" forKey:@"org.oasis.opendocument.graphics"]; 50 [temp setObject:@"OpenOffice.org 1.0 Master" forKey:@"org.openoffice.text-master"]; 51 [temp setObject:@"OpenDocument Master" forKey:@"org.oasis.opendocument.text-master"]; 52 [temp setObject:@"OpenOffice.org 1.0 Formula" forKey:@"org.openoffice.formula"]; 53 [temp setObject:@"OpenDocument Formula" forKey:@"org.oasis.opendocument.formula"]; 54 [temp setObject:@"OpenOffice.org 1.0 Text Template" forKey:@"org.openoffice.text-template"]; 55 [temp setObject:@"OpenDocument Text Template" forKey:@"org.oasis.opendocument.text-template"]; 56 [temp setObject:@"OpenOffice.org 1.0 Spreadsheet Template" forKey:@"org.openoffice.spreadsheet-template"]; 57 [temp setObject:@"OpenDocument Spreadsheet Template" forKey:@"org.oasis.opendocument.spreadsheet-template"]; 58 [temp setObject:@"OpenOffice.org 1.0 Presentation Template" forKey:@"org.openoffice.presentation-template"]; 59 [temp setObject:@"OpenDocument Presentation Template" forKey:@"org.oasis.opendocument.presentation-template"]; 60 [temp setObject:@"OpenOffice.org 1.0 Drawing Template" forKey:@"org.openoffice.graphics-template"]; 61 [temp setObject:@"OpenDocument Drawing Template" forKey:@"org.oasis.opendocument.graphics-template"]; 62 [temp setObject:@"OpenOffice.org 1.0 Database" forKey:@"org.openoffice.database"]; 63 [temp setObject:@"OpenDocument Chart" forKey:@"org.oasis.opendocument.chart"]; 64 65 uti2kind = [[NSDictionary dictionaryWithDictionary:temp] retain]; 66 [temp release]; 67 68 isInitialized = YES; 69 } 70} 71 72/* importDocument is the real starting point for our plugin */ 73- (BOOL)importDocument:(NSString*)pathToFile contentType:(NSString*)contentTypeUTI attributes:(NSMutableDictionary*)attributes 74{ 75 //NSLog(contentTypeUTI); 76 //NSLog(pathToFile); 77 78 NSString *itemKind = [uti2kind objectForKey:contentTypeUTI]; 79 if (itemKind != nil) { 80 [attributes setObject:itemKind forKey:(NSString*)kMDItemKind]; 81 } 82 83 //first check to see if this is a valid zipped file that contains a file "meta.xml" 84 unzFile unzipFile = [self openZipFileAtPath:pathToFile]; 85 86 // 87 if (unzipFile == nil) { 88 //NSLog(@"zip file not open"); 89 return YES; 90 } 91 92 //first get the metadata 93 NSData *metaData = [self metaDataFileFromZip:unzipFile]; 94 if (metaData == nil) { 95 unzClose(unzipFile); 96 return YES; 97 } 98 99 [metaData retain]; 100 101 OOoMetaDataParser *parser = [OOoMetaDataParser new]; 102 if (parser != nil) { 103 //parse and extract the data 104 [parser parseXML:metaData intoDictionary:attributes]; 105 } 106 107 [metaData release]; 108 [parser release]; 109 110 //and now get the content 111 NSData *contentData = [self contentDataFileFromZip:unzipFile]; 112 if (contentData == nil) { 113 unzClose(unzipFile); 114 return YES; 115 } 116 117 [contentData retain]; 118 119 OOoContentDataParser *parser2 = [OOoContentDataParser new]; 120 if (parser2 != nil) { 121 //parse and extract the data 122 [parser2 parseXML:contentData intoDictionary:attributes]; 123 } 124 125 [contentData release]; 126 [parser2 release]; 127 128 unzClose(unzipFile); 129 130 return YES; 131} 132 133/* openZipFileAtPath returns the file as a valid data structure or nil otherwise*/ 134- (unzFile)openZipFileAtPath:(NSString*)pathToFile 135{ 136 unzFile unzipFile = nil; 137 138 const char *zipfilename = [pathToFile UTF8String]; 139 140 if (zipfilename != nil) 141 { 142 unzipFile = unzOpen(zipfilename); 143 } 144 145 if (unzipFile == nil) 146 { 147 //NSLog(@"Cannot open %s",zipfilename); 148 return nil; 149 } 150 151 //NSLog(@"%s opened",zipfilename); 152 153 return unzipFile; 154} 155 156/* metaDataFileFromZip extracts the file meta.xml from the zip file and returns it as an NSData* structure 157 or nil if the metadata is not present */ 158- (NSData*) metaDataFileFromZip:(unzFile)unzipFile 159{ 160 //search and set the cursor to meta.xml 161 if (unzLocateFile(unzipFile, "meta.xml", CASESENSITIVITY) != UNZ_OK) { 162 //we hit an error, do cleanup 163 unzCloseCurrentFile(unzipFile); 164 return nil; 165 } 166 167 //open the current file 168 if (unzOpenCurrentFile(unzipFile) != UNZ_OK) { 169 //we hit an error, do cleanup 170 unzCloseCurrentFile(unzipFile); 171 unzClose(unzipFile); 172 return nil; 173 } 174 175 NSMutableData *data = [NSMutableData new]; 176 177 unsigned buffer[BUFFER_SIZE]; 178 int bytesRead = 0; 179 while ((bytesRead = unzReadCurrentFile(unzipFile, buffer, sizeof(buffer))) > 0) { 180 //append the data until we are finished 181 [data appendData:[NSData dataWithBytes:(const void *)buffer length:bytesRead]]; 182 } 183 184 //we no longer need the file, so close it 185 unzCloseCurrentFile(unzipFile); 186 187 NSData *returnValue = [NSData dataWithData:data]; 188 [data release]; 189 190 return returnValue; 191} 192 193/* contentDataFileFromZip extracts the file content.xml from the zip file and returns it as an NSData* structure 194 or nil if the metadata is not present */ 195- (NSData*) contentDataFileFromZip:(unzFile)unzipFile 196{ 197 //search and set the cursor to content.xml 198 if (unzLocateFile(unzipFile, "content.xml", CASESENSITIVITY) != UNZ_OK) { 199 //we hit an error, do cleanup 200 unzCloseCurrentFile(unzipFile); 201 return nil; 202 } 203 204 //open the current file 205 if (unzOpenCurrentFile(unzipFile) != UNZ_OK) { 206 //we hit an error, do cleanup 207 unzCloseCurrentFile(unzipFile); 208 unzClose(unzipFile); 209 return nil; 210 } 211 212 NSMutableData *data = [NSMutableData new]; 213 214 unsigned buffer[BUFFER_SIZE]; 215 int bytesRead = 0; 216 while ((bytesRead = unzReadCurrentFile(unzipFile, buffer, sizeof(buffer))) > 0) { 217 //append the data 218 [data appendData:[NSData dataWithBytes:(const void *)buffer length:bytesRead]]; 219 } 220 221 //we no longer need the file, so close it 222 unzCloseCurrentFile(unzipFile); 223 224 NSData *returnValue = [NSData dataWithData:data]; 225 [data release]; 226 227 return returnValue; 228} 229 230 231@end 232