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