33
33
#endif
34
34
35
35
#import " GCDWebUploader.h"
36
+
36
37
#import " GCDWebServerDataRequest.h"
37
38
#import " GCDWebServerMultiPartFormRequest.h"
38
39
#import " GCDWebServerURLEncodedFormRequest.h"
40
+
39
41
#import " GCDWebServerDataResponse.h"
42
+ #import " GCDWebServerErrorResponse.h"
40
43
#import " GCDWebServerFileResponse.h"
41
44
42
45
@interface GCDWebUploader () {
@@ -93,7 +96,7 @@ - (id)initWithUploadDirectory:(NSString*)path {
93
96
return nil ;
94
97
}
95
98
_uploadDirectory = [[path stringByStandardizingPath ] copy ];
96
- GCDWebUploader* __unsafe_unretained uploader = self;
99
+ GCDWebUploader* __unsafe_unretained server = self;
97
100
98
101
// Resource files
99
102
[self addGETHandlerForBasePath: @" /" directoryPath: [siteBundle resourcePath ] indexFilename: nil cacheAge: 3600 allowRangeRequests: NO ];
@@ -110,7 +113,7 @@ - (id)initWithUploadDirectory:(NSString*)path {
110
113
NSString * device = [(id )SCDynamicStoreCopyComputerName (NULL , NULL ) autorelease ];
111
114
#endif
112
115
#endif
113
- NSString * title = uploader .title ;
116
+ NSString * title = server .title ;
114
117
if (title == nil ) {
115
118
title = [[NSBundle mainBundle ] objectForInfoDictionaryKey: @" CFBundleDisplayName" ];
116
119
#if !TARGET_OS_IPHONE
@@ -119,19 +122,19 @@ - (id)initWithUploadDirectory:(NSString*)path {
119
122
}
120
123
#endif
121
124
}
122
- NSString * header = uploader .header ;
125
+ NSString * header = server .header ;
123
126
if (header == nil ) {
124
127
header = title;
125
128
}
126
- NSString * prologue = uploader .prologue ;
129
+ NSString * prologue = server .prologue ;
127
130
if (prologue == nil ) {
128
131
prologue = [siteBundle localizedStringForKey: @" PROLOGUE" value: @" " table: nil ];
129
132
}
130
- NSString * epilogue = uploader .epilogue ;
133
+ NSString * epilogue = server .epilogue ;
131
134
if (epilogue == nil ) {
132
135
epilogue = [siteBundle localizedStringForKey: @" EPILOGUE" value: @" " table: nil ];
133
136
}
134
- NSString * footer = uploader .footer ;
137
+ NSString * footer = server .footer ;
135
138
if (footer == nil ) {
136
139
NSString * name = [[NSBundle mainBundle ] objectForInfoDictionaryKey: @" CFBundleDisplayName" ];
137
140
NSString * version = [[NSBundle mainBundle ] objectForInfoDictionaryKey: @" CFBundleShortVersionString" ];
@@ -159,19 +162,20 @@ - (id)initWithUploadDirectory:(NSString*)path {
159
162
[self addHandlerForMethod: @" GET" path: @" /list" requestClass: [GCDWebServerRequest class ] processBlock: ^GCDWebServerResponse *(GCDWebServerRequest* request) {
160
163
161
164
NSString * relativePath = [[request query ] objectForKey: @" path" ];
162
- NSString * absolutePath = [uploader .uploadDirectory stringByAppendingPathComponent: relativePath];
165
+ NSString * absolutePath = [server .uploadDirectory stringByAppendingPathComponent: relativePath];
163
166
BOOL isDirectory;
164
167
if ([[NSFileManager defaultManager ] fileExistsAtPath: absolutePath isDirectory: &isDirectory]) {
165
168
if (isDirectory) {
166
- BOOL showHidden = uploader.showHiddenFiles ;
167
- NSArray * contents = [[NSFileManager defaultManager ] contentsOfDirectoryAtPath: absolutePath error: NULL ];
169
+ BOOL showHidden = server.showHiddenFiles ;
170
+ NSError * error = nil ;
171
+ NSArray * contents = [[NSFileManager defaultManager ] contentsOfDirectoryAtPath: absolutePath error: &error];
168
172
if (contents) {
169
173
NSMutableArray * array = [NSMutableArray array ];
170
174
for (NSString * item in [contents sortedArrayUsingSelector: @selector (localizedStandardCompare: )]) {
171
175
if (showHidden || ![item hasPrefix: @" ." ]) {
172
176
NSDictionary * attributes = [[NSFileManager defaultManager ] attributesOfItemAtPath: [absolutePath stringByAppendingPathComponent: item] error: NULL ];
173
177
NSString * type = [attributes objectForKey: NSFileType ];
174
- if ([type isEqualToString: NSFileTypeRegular ] && [uploader _checkFileExtension: item]) {
178
+ if ([type isEqualToString: NSFileTypeRegular ] && [server _checkFileExtension: item]) {
175
179
[array addObject: @{
176
180
@" path" : [relativePath stringByAppendingPathComponent: item],
177
181
@" name" : item,
@@ -187,13 +191,13 @@ - (id)initWithUploadDirectory:(NSString*)path {
187
191
}
188
192
return [GCDWebServerDataResponse responseWithJSONObject: array];
189
193
} else {
190
- return [GCDWebServerResponse responseWithStatusCode: 500 ];
194
+ return [GCDWebServerErrorResponse responseWithServerError: kGCDWebServerHTTPStatusCode_InternalServerError underlyingError: error message: @" Failed listing directory \" %@ \" " , relativePath ];
191
195
}
192
196
} else {
193
- return [GCDWebServerResponse responseWithStatusCode: 400 ];
197
+ return [GCDWebServerErrorResponse responseWithClientError: kGCDWebServerHTTPStatusCode_BadRequest message: @" \" %@ \" is not a directory " , relativePath ];
194
198
}
195
199
} else {
196
- return [GCDWebServerResponse responseWithStatusCode: 404 ];
200
+ return [GCDWebServerErrorResponse responseWithClientError: kGCDWebServerHTTPStatusCode_NotFound message: @" \" %@ \" does not exist " , relativePath ];
197
201
}
198
202
199
203
}];
@@ -202,21 +206,21 @@ - (id)initWithUploadDirectory:(NSString*)path {
202
206
[self addHandlerForMethod: @" GET" path: @" /download" requestClass: [GCDWebServerRequest class ] processBlock: ^GCDWebServerResponse *(GCDWebServerRequest* request) {
203
207
204
208
NSString * relativePath = [[request query ] objectForKey: @" path" ];
205
- NSString * absolutePath = [uploader .uploadDirectory stringByAppendingPathComponent: relativePath];
209
+ NSString * absolutePath = [server .uploadDirectory stringByAppendingPathComponent: relativePath];
206
210
BOOL isDirectory;
207
211
if ([[NSFileManager defaultManager ] fileExistsAtPath: absolutePath isDirectory: &isDirectory]) {
208
212
if (isDirectory) {
209
- return [GCDWebServerResponse responseWithStatusCode: 400 ];
213
+ return [GCDWebServerErrorResponse responseWithClientError: kGCDWebServerHTTPStatusCode_BadRequest message: @" \" %@ \" is a directory " , relativePath ];
210
214
} else {
211
- if ([uploader .delegate respondsToSelector: @selector (webUploader:didDownloadFileAtPath: )]) {
215
+ if ([server .delegate respondsToSelector: @selector (webUploader:didDownloadFileAtPath: )]) {
212
216
dispatch_async (dispatch_get_main_queue (), ^{
213
- [uploader .delegate webUploader: uploader didDownloadFileAtPath: absolutePath];
217
+ [server .delegate webUploader: server didDownloadFileAtPath: absolutePath];
214
218
});
215
219
}
216
220
return [GCDWebServerFileResponse responseWithFile: absolutePath isAttachment: YES ];
217
221
}
218
222
} else {
219
- return [GCDWebServerResponse responseWithStatusCode: 404 ];
223
+ return [GCDWebServerErrorResponse responseWithClientError: kGCDWebServerHTTPStatusCode_NotFound message: @" \" %@ \" does not exist " , relativePath ];
220
224
}
221
225
222
226
}];
@@ -229,26 +233,26 @@ - (id)initWithUploadDirectory:(NSString*)path {
229
233
NSString * contentType = (range.location != NSNotFound ? @" application/json" : @" text/plain; charset=utf-8" );
230
234
231
235
GCDWebServerMultiPartFile* file = [[(GCDWebServerMultiPartFormRequest*)request files ] objectForKey: @" files[]" ];
232
- if ((![file.fileName hasPrefix: @" ." ] || uploader .showHiddenFiles ) && [uploader _checkFileExtension: file.fileName]) {
236
+ if ((![file.fileName hasPrefix: @" ." ] || server .showHiddenFiles ) && [server _checkFileExtension: file.fileName]) {
233
237
NSString * relativePath = [(GCDWebServerMultiPartArgument*)[[(GCDWebServerURLEncodedFormRequest*)request arguments ] objectForKey: @" path" ] string ];
234
- NSString * absolutePath = [uploader _uniquePathForPath: [[uploader .uploadDirectory stringByAppendingPathComponent: relativePath] stringByAppendingPathComponent: file.fileName]];
235
- if ([uploader shouldUploadFileAtPath: absolutePath withTemporaryFile: file.temporaryPath]) {
238
+ NSString * absolutePath = [server _uniquePathForPath: [[server .uploadDirectory stringByAppendingPathComponent: relativePath] stringByAppendingPathComponent: file.fileName]];
239
+ if ([server shouldUploadFileAtPath: absolutePath withTemporaryFile: file.temporaryPath]) {
236
240
NSError * error = nil ;
237
241
if ([[NSFileManager defaultManager ] moveItemAtPath: file.temporaryPath toPath: absolutePath error: &error]) {
238
- if ([uploader .delegate respondsToSelector: @selector (webUploader:didUploadFileAtPath: )]) {
242
+ if ([server .delegate respondsToSelector: @selector (webUploader:didUploadFileAtPath: )]) {
239
243
dispatch_async (dispatch_get_main_queue (), ^{
240
- [uploader .delegate webUploader: uploader didUploadFileAtPath: absolutePath];
244
+ [server .delegate webUploader: server didUploadFileAtPath: absolutePath];
241
245
});
242
246
}
243
247
return [GCDWebServerDataResponse responseWithJSONObject: @{} contentType: contentType];
244
248
} else {
245
- return [GCDWebServerResponse responseWithStatusCode: 500 ];
249
+ return [GCDWebServerErrorResponse responseWithServerError: kGCDWebServerHTTPStatusCode_InternalServerError underlyingError: error message: @" Failed moving uploaded file to \" %@ \" " , relativePath ];
246
250
}
247
251
} else {
248
- return [GCDWebServerResponse responseWithStatusCode: 403 ];
252
+ return [GCDWebServerErrorResponse responseWithClientError: kGCDWebServerHTTPStatusCode_Forbidden message: @" Uploading file \" %@ \" to \" %@ \" is not allowed " , file.fileName, relativePath ];
249
253
}
250
254
} else {
251
- return [GCDWebServerResponse responseWithStatusCode: 400 ];
255
+ return [GCDWebServerErrorResponse responseWithClientError: kGCDWebServerHTTPStatusCode_Forbidden message: @" Uploaded file name \" %@ \" is not allowed " , file.fileName ];
252
256
}
253
257
254
258
}];
@@ -257,37 +261,39 @@ - (id)initWithUploadDirectory:(NSString*)path {
257
261
[self addHandlerForMethod: @" POST" path: @" /move" requestClass: [GCDWebServerURLEncodedFormRequest class ] processBlock: ^GCDWebServerResponse *(GCDWebServerRequest* request) {
258
262
259
263
NSString * oldRelativePath = [[(GCDWebServerURLEncodedFormRequest*)request arguments ] objectForKey: @" oldPath" ];
260
- NSString * oldAbsolutePath = [uploader .uploadDirectory stringByAppendingPathComponent: oldRelativePath];
264
+ NSString * oldAbsolutePath = [server .uploadDirectory stringByAppendingPathComponent: oldRelativePath];
261
265
BOOL isDirectory;
262
266
if ([[NSFileManager defaultManager ] fileExistsAtPath: oldAbsolutePath isDirectory: &isDirectory]) {
263
267
NSString * newRelativePath = [[(GCDWebServerURLEncodedFormRequest*)request arguments ] objectForKey: @" newPath" ];
264
- if (!uploader .showHiddenFiles ) {
268
+ if (!server .showHiddenFiles ) {
265
269
for (NSString * component in [newRelativePath pathComponents ]) {
266
270
if ([component hasPrefix: @" ." ]) {
267
- return [GCDWebServerResponse responseWithStatusCode: 400 ];
271
+ return [GCDWebServerErrorResponse responseWithClientError: kGCDWebServerHTTPStatusCode_BadRequest message: @" Item path \" %@ \" is not allowed " , newRelativePath ];
268
272
}
269
273
}
270
274
}
271
- if (!isDirectory && ![uploader _checkFileExtension: newRelativePath]) {
272
- return [GCDWebServerResponse responseWithStatusCode: 400 ];
275
+ if (!isDirectory && ![server _checkFileExtension: newRelativePath]) {
276
+ return [GCDWebServerErrorResponse responseWithClientError: kGCDWebServerHTTPStatusCode_Forbidden message: @" Item path \" %@ \" is not allowed " , newRelativePath ];
273
277
}
274
- NSString * newAbsolutePath = [uploader _uniquePathForPath: [uploader.uploadDirectory stringByAppendingPathComponent: newRelativePath]];
275
- if ([uploader shouldMoveItemFromPath: oldAbsolutePath toPath: newAbsolutePath]) {
276
- if ([[NSFileManager defaultManager ] moveItemAtPath: oldAbsolutePath toPath: newAbsolutePath error: NULL ]) {
277
- if ([uploader.delegate respondsToSelector: @selector (webUploader:didMoveItemFromPath:toPath: )]) {
278
+ NSString * newAbsolutePath = [server _uniquePathForPath: [server.uploadDirectory stringByAppendingPathComponent: newRelativePath]];
279
+ if ([server shouldMoveItemFromPath: oldAbsolutePath toPath: newAbsolutePath]) {
280
+ [[NSFileManager defaultManager ] createDirectoryAtPath: [newAbsolutePath stringByDeletingLastPathComponent ] withIntermediateDirectories: YES attributes: nil error: NULL ];
281
+ NSError * error = nil ;
282
+ if ([[NSFileManager defaultManager ] moveItemAtPath: oldAbsolutePath toPath: newAbsolutePath error: &error]) {
283
+ if ([server.delegate respondsToSelector: @selector (webUploader:didMoveItemFromPath:toPath: )]) {
278
284
dispatch_async (dispatch_get_main_queue (), ^{
279
- [uploader .delegate webUploader: uploader didMoveItemFromPath: oldAbsolutePath toPath: newAbsolutePath];
285
+ [server .delegate webUploader: server didMoveItemFromPath: oldAbsolutePath toPath: newAbsolutePath];
280
286
});
281
287
}
282
288
return [GCDWebServerDataResponse responseWithJSONObject: @{}];
283
289
} else {
284
- return [GCDWebServerResponse responseWithStatusCode: 500 ];
290
+ return [GCDWebServerErrorResponse responseWithServerError: kGCDWebServerHTTPStatusCode_InternalServerError underlyingError: error message: @" Failed moving \" %@ \" to \" %@ \" " , oldRelativePath, newRelativePath ];
285
291
}
286
292
} else {
287
- return [GCDWebServerResponse responseWithStatusCode: 403 ];
293
+ return [GCDWebServerErrorResponse responseWithClientError: kGCDWebServerHTTPStatusCode_Forbidden message: @" Moving \" %@ \" to \" %@ \" is not allowed " , oldRelativePath, newRelativePath ];
288
294
}
289
295
} else {
290
- return [GCDWebServerResponse responseWithStatusCode: 404 ];
296
+ return [GCDWebServerErrorResponse responseWithClientError: kGCDWebServerHTTPStatusCode_NotFound message: @" \" %@ \" does not exist " , oldRelativePath ];
291
297
}
292
298
293
299
}];
@@ -296,20 +302,25 @@ - (id)initWithUploadDirectory:(NSString*)path {
296
302
[self addHandlerForMethod: @" POST" path: @" /delete" requestClass: [GCDWebServerURLEncodedFormRequest class ] processBlock: ^GCDWebServerResponse *(GCDWebServerRequest* request) {
297
303
298
304
NSString * relativePath = [[(GCDWebServerURLEncodedFormRequest*)request arguments ] objectForKey: @" path" ];
299
- NSString * absolutePath = [uploader .uploadDirectory stringByAppendingPathComponent: relativePath];
305
+ NSString * absolutePath = [server .uploadDirectory stringByAppendingPathComponent: relativePath];
300
306
if ([[NSFileManager defaultManager ] fileExistsAtPath: absolutePath]) {
301
- if ([[NSFileManager defaultManager ] removeItemAtPath: absolutePath error: NULL ]) {
302
- if ([uploader.delegate respondsToSelector: @selector (webUploader:didDeleteItemAtPath: )]) {
303
- dispatch_async (dispatch_get_main_queue (), ^{
304
- [uploader.delegate webUploader: uploader didDeleteItemAtPath: absolutePath];
305
- });
307
+ if ([server shouldDeleteItemAtPath: absolutePath]) {
308
+ NSError * error = nil ;
309
+ if ([[NSFileManager defaultManager ] removeItemAtPath: absolutePath error: &error]) {
310
+ if ([server.delegate respondsToSelector: @selector (webUploader:didDeleteItemAtPath: )]) {
311
+ dispatch_async (dispatch_get_main_queue (), ^{
312
+ [server.delegate webUploader: server didDeleteItemAtPath: absolutePath];
313
+ });
314
+ }
315
+ return [GCDWebServerDataResponse responseWithJSONObject: @{}];
316
+ } else {
317
+ return [GCDWebServerErrorResponse responseWithServerError: kGCDWebServerHTTPStatusCode_InternalServerError underlyingError: error message: @" Failed deleting \" %@ \" " , relativePath];
306
318
}
307
- return [GCDWebServerDataResponse responseWithJSONObject: @{}];
308
319
} else {
309
- return [GCDWebServerResponse responseWithStatusCode: 500 ];
320
+ return [GCDWebServerErrorResponse responseWithClientError: kGCDWebServerHTTPStatusCode_Forbidden message: @" Deleting \" %@ \" is not allowed " , relativePath ];
310
321
}
311
322
} else {
312
- return [GCDWebServerResponse responseWithStatusCode: 404 ];
323
+ return [GCDWebServerErrorResponse responseWithClientError: kGCDWebServerHTTPStatusCode_NotFound message: @" \" %@ \" does not exist " , relativePath ];
313
324
}
314
325
315
326
}];
@@ -318,23 +329,28 @@ - (id)initWithUploadDirectory:(NSString*)path {
318
329
[self addHandlerForMethod: @" POST" path: @" /create" requestClass: [GCDWebServerURLEncodedFormRequest class ] processBlock: ^GCDWebServerResponse *(GCDWebServerRequest* request) {
319
330
320
331
NSString * relativePath = [[(GCDWebServerURLEncodedFormRequest*)request arguments ] objectForKey: @" path" ];
321
- if (!uploader .showHiddenFiles ) {
332
+ if (!server .showHiddenFiles ) {
322
333
for (NSString * component in [relativePath pathComponents ]) {
323
334
if ([component hasPrefix: @" ." ]) {
324
- return [GCDWebServerResponse responseWithStatusCode: 400 ];
335
+ return [GCDWebServerErrorResponse responseWithClientError: kGCDWebServerHTTPStatusCode_Forbidden message: @" Directory path \" %@ \" is not allowed " , relativePath ];
325
336
}
326
337
}
327
338
}
328
- NSString * absolutePath = [uploader _uniquePathForPath: [uploader.uploadDirectory stringByAppendingPathComponent: relativePath]];
329
- if ([[NSFileManager defaultManager ] createDirectoryAtPath: absolutePath withIntermediateDirectories: YES attributes: nil error: NULL ]) {
330
- if ([uploader.delegate respondsToSelector: @selector (webUploader:didCreateDirectoryAtPath: )]) {
331
- dispatch_async (dispatch_get_main_queue (), ^{
332
- [uploader.delegate webUploader: uploader didCreateDirectoryAtPath: absolutePath];
333
- });
339
+ NSString * absolutePath = [server _uniquePathForPath: [server.uploadDirectory stringByAppendingPathComponent: relativePath]];
340
+ if ([server shouldCreateDirectoryAtPath: absolutePath]) {
341
+ NSError * error = nil ;
342
+ if ([[NSFileManager defaultManager ] createDirectoryAtPath: absolutePath withIntermediateDirectories: YES attributes: nil error: &error]) {
343
+ if ([server.delegate respondsToSelector: @selector (webUploader:didCreateDirectoryAtPath: )]) {
344
+ dispatch_async (dispatch_get_main_queue (), ^{
345
+ [server.delegate webUploader: server didCreateDirectoryAtPath: absolutePath];
346
+ });
347
+ }
348
+ return [GCDWebServerDataResponse responseWithJSONObject: @{}];
349
+ } else {
350
+ return [GCDWebServerErrorResponse responseWithServerError: kGCDWebServerHTTPStatusCode_InternalServerError underlyingError: error message: @" Failed creating directory \" %@ \" " , relativePath];
334
351
}
335
- return [GCDWebServerDataResponse responseWithJSONObject: @{}];
336
352
} else {
337
- return [GCDWebServerResponse responseWithStatusCode: 500 ];
353
+ return [GCDWebServerErrorResponse responseWithClientError: kGCDWebServerHTTPStatusCode_Forbidden message: @" Creating directory \" %@ \" is not allowed " , relativePath ];
338
354
}
339
355
340
356
}];
@@ -371,4 +387,12 @@ - (BOOL)shouldMoveItemFromPath:(NSString*)fromPath toPath:(NSString*)toPath {
371
387
return YES ;
372
388
}
373
389
390
+ - (BOOL )shouldDeleteItemAtPath : (NSString *)path {
391
+ return YES ;
392
+ }
393
+
394
+ - (BOOL )shouldCreateDirectoryAtPath : (NSString *)path {
395
+ return YES ;
396
+ }
397
+
374
398
@end
0 commit comments