mirror of
https://github.com/swisspol/GCDWebServer.git
synced 2026-02-11 00:00:07 +08:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
467830e4de | ||
|
|
030c28eb93 | ||
|
|
e4702059c8 | ||
|
|
877813ed0f | ||
|
|
ccfb4f0b54 | ||
|
|
e27fd601a8 | ||
|
|
7c7f561f90 | ||
|
|
689cb5f26a | ||
|
|
1e4c508737 | ||
|
|
ef08ab5516 | ||
|
|
18ad23f503 | ||
|
|
d68687af62 | ||
|
|
0cdf441830 |
@@ -42,6 +42,11 @@
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.column-move {
|
||||
width: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.column-delete {
|
||||
width: 40px;
|
||||
text-align: center;
|
||||
@@ -64,6 +69,16 @@
|
||||
float: right;
|
||||
}
|
||||
|
||||
#create-input {
|
||||
width: 50%;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
#move-input {
|
||||
width: 80%;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
/* Bootstrap overrides */
|
||||
|
||||
.btn:focus {
|
||||
|
||||
@@ -95,12 +95,54 @@
|
||||
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="create-modal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h4 class="modal-title">Create Folder</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Please enter the name of the folder to be created:</p>
|
||||
<form onsubmit="return false">
|
||||
<input type="text" autocomplete="off" id="create-input">
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
||||
<button type="button" class="btn btn-primary" id="create-confirm">Create Folder</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal fade" id="move-modal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h4 class="modal-title">Move Item</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Please enter the new location for this item:</p>
|
||||
<form onsubmit="return false">
|
||||
<input type="text" autocomplete="off" id="move-input">
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
||||
<button type="button" class="btn btn-primary" id="move-confirm">Move Item</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/x-tmpl" id="template-listing">
|
||||
<tr class="row-file" data-path="{%=o.path%}" data-name="{%=o.name%}">
|
||||
<td class="column-icon">
|
||||
{% if (o.size != null) { %}
|
||||
<button type="button" class="btn btn-default btn-xs button-download">
|
||||
<span class="glyphicon glyphicon-download"></span>
|
||||
<span class="glyphicon glyphicon-download-alt"></span>
|
||||
</button>
|
||||
{% } else { %}
|
||||
<button type="button" class="btn btn-default btn-xs button-open">
|
||||
@@ -114,6 +156,11 @@
|
||||
<p>{%=formatFileSize(o.size)%}</p>
|
||||
{% } %}
|
||||
</td>
|
||||
<td class="column-move">
|
||||
<button type="button" class="btn btn-default btn-xs button-move">
|
||||
<span class="glyphicon glyphicon glyphicon-share-alt"></span>
|
||||
</button>
|
||||
</td>
|
||||
<td class="column-delete">
|
||||
<button type="button" class="btn btn-danger btn-xs button-delete">
|
||||
<span class="glyphicon glyphicon-trash"></span>
|
||||
@@ -132,7 +179,7 @@
|
||||
<td class="column-path"><p>{%=o.path%}</p></td>
|
||||
<td class="column-progress">
|
||||
<div class="progress">
|
||||
<div class="progress-bar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" id="progress-bar"></div>
|
||||
<div class="progress-bar" id="progress-bar"></div>
|
||||
</div>
|
||||
</ts>
|
||||
</tr>
|
||||
@@ -140,7 +187,7 @@
|
||||
|
||||
<script type="text/x-tmpl" id="template-alert">
|
||||
<div class="alert alert-{%=o.level%} alert-dismissable">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
|
||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||
<strong>{%=o.title%}</strong>{%=o.description%}
|
||||
</div>
|
||||
</script>
|
||||
|
||||
@@ -122,6 +122,16 @@ function _reload(path) {
|
||||
_reload(path);
|
||||
});
|
||||
|
||||
$(".button-move").click(function(event) {
|
||||
var path = $(this).parent().parent().attr("data-path");
|
||||
if (path[path.length - 1] == "/") {
|
||||
path = path.slice(0, path.length - 1);
|
||||
}
|
||||
$("#move-input").attr("data-path", path);
|
||||
$("#move-input").val(path);
|
||||
$("#move-modal").modal("show");
|
||||
});
|
||||
|
||||
$(".button-delete").click(function(event) {
|
||||
var path = $(this).parent().parent().attr("data-path");
|
||||
$.ajax({
|
||||
@@ -202,9 +212,20 @@ $(document).ready(function() {
|
||||
|
||||
});
|
||||
|
||||
$("#create-modal").on("shown.bs.modal", function(event) {
|
||||
$("#create-input").focus();
|
||||
$("#create-input").select();
|
||||
})
|
||||
|
||||
$("#create-folder").click(function(event) {
|
||||
var name = prompt("Please enter folder name:", "Untitled folder");
|
||||
if ((name != null) && (name != "")) {
|
||||
$("#create-input").val("Untitled folder");
|
||||
$("#create-modal").modal("show");
|
||||
});
|
||||
|
||||
$("#create-confirm").click(function(event) {
|
||||
$("#create-modal").modal("hide");
|
||||
var name = $("#create-input").val();
|
||||
if (name != "") {
|
||||
$.ajax({
|
||||
url: 'create',
|
||||
type: 'POST',
|
||||
@@ -218,6 +239,29 @@ $(document).ready(function() {
|
||||
}
|
||||
});
|
||||
|
||||
$("#move-modal").on("shown.bs.modal", function(event) {
|
||||
$("#move-input").focus();
|
||||
$("#move-input").select();
|
||||
})
|
||||
|
||||
$("#move-confirm").click(function(event) {
|
||||
$("#move-modal").modal("hide");
|
||||
var oldPath = $("#move-input").attr("data-path");
|
||||
var newPath = $("#move-input").val();
|
||||
if ((newPath != "") && (newPath[0] == "/") && (newPath != oldPath)) {
|
||||
$.ajax({
|
||||
url: 'move',
|
||||
type: 'POST',
|
||||
data: {oldPath: oldPath, newPath: newPath},
|
||||
dataType: 'json'
|
||||
}).fail(function(jqXHR, textStatus, errorThrown) {
|
||||
_showError("Failed moving \"" + oldPath + "\" to \"" + newPath + "\"", textStatus, errorThrown);
|
||||
}).always(function() {
|
||||
_reload(_path);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$("#reload").click(function(event) {
|
||||
_reload(_path);
|
||||
});
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
@property(nonatomic, copy) NSString* title; // Default is application name (must be HTML escaped)
|
||||
@property(nonatomic, copy) NSString* header; // Default is same as title (must be HTML escaped)
|
||||
@property(nonatomic, copy) NSString* prologue; // Default is mini help (must be raw HTML)
|
||||
@property(nonatomic, copy) NSString* epilogue; // Default is mini help (must be raw HTML)
|
||||
@property(nonatomic, copy) NSString* epilogue; // Default is nothing (must be raw HTML)
|
||||
@property(nonatomic, copy) NSString* footer; // Default is application name and version (must be HTML escaped)
|
||||
- (id)initWithUploadDirectory:(NSString*)path;
|
||||
@end
|
||||
|
||||
@@ -88,7 +88,11 @@
|
||||
return nil;
|
||||
}
|
||||
_uploadDirectory = [[path stringByStandardizingPath] copy];
|
||||
GCDWebUploader* __unsafe_unretained uploader = self; // Avoid retain-cycles with self
|
||||
#if __has_feature(objc_arc)
|
||||
__unsafe_unretained GCDWebUploader* uploader = self;
|
||||
#else
|
||||
__block GCDWebUploader* uploader = self;
|
||||
#endif
|
||||
|
||||
// Resource files
|
||||
[self addGETHandlerForBasePath:@"/" directoryPath:[siteBundle resourcePath] indexFilename:nil cacheAge:3600 allowRangeRequests:NO];
|
||||
@@ -108,6 +112,11 @@
|
||||
NSString* title = uploader.title;
|
||||
if (title == nil) {
|
||||
title = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];
|
||||
#if !TARGET_OS_IPHONE
|
||||
if (title == nil) {
|
||||
title = [[NSProcessInfo processInfo] processName];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
NSString* header = uploader.header;
|
||||
if (header == nil) {
|
||||
@@ -123,9 +132,15 @@
|
||||
}
|
||||
NSString* footer = uploader.footer;
|
||||
if (footer == nil) {
|
||||
footer = [NSString stringWithFormat:[siteBundle localizedStringForKey:@"FOOTER_FORMAT" value:@"" table:nil],
|
||||
[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"],
|
||||
[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]];
|
||||
NSString* name = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];
|
||||
NSString* version = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
|
||||
#if !TARGET_OS_IPHONE
|
||||
if (!name && !version) {
|
||||
name = @"OS X";
|
||||
version = [[NSProcessInfo processInfo] operatingSystemVersionString];
|
||||
}
|
||||
#endif
|
||||
footer = [NSString stringWithFormat:[siteBundle localizedStringForKey:@"FOOTER_FORMAT" value:@"" table:nil], name, version];
|
||||
}
|
||||
return [GCDWebServerDataResponse responseWithHTMLTemplate:[siteBundle pathForResource:@"index" ofType:@"html"]
|
||||
variables:@{
|
||||
|
||||
@@ -10,6 +10,9 @@ GCDWebServer is a lightweight GCD based HTTP 1.1 server designed to be embedded
|
||||
* No dependencies on third-party source code
|
||||
* Available under a friendly [New BSD License](LICENSE)
|
||||
|
||||
Included extensions:
|
||||
* [GCDWebUploader](GCDWebUploader/GCDWebUploader.h): subclass of GCDWebServer that implements an interface for uploading and downloading files from an iOS app's sandbox using a web browser
|
||||
|
||||
What's not available out of the box but can be implemented on top of the API:
|
||||
* Authentication like [Basic Authentication](https://en.wikipedia.org/wiki/Basic_access_authentication)
|
||||
* Web forms submitted using "multipart/mixed"
|
||||
@@ -70,6 +73,7 @@ Simply instantiate and run a GCDWebUploader instance then visit http://{YOUR-IOS
|
||||
NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
|
||||
GCDWebUploader* webUploader = [[GCDWebUploader alloc] initWithUploadDirectory:documentsPath];
|
||||
[webUploader start];
|
||||
NSLog(@"Visit %@ in your web browser", webUploader.serverURL);
|
||||
return YES;
|
||||
}
|
||||
```
|
||||
@@ -222,4 +226,4 @@ Final Example: File Downloads and Uploads From iOS App
|
||||
|
||||
GCDWebServer was originally written for the [ComicFlow](http://itunes.apple.com/us/app/comicflow/id409290355?mt=8) comic reader app for iPad. It uses it to provide a web server for people to upload and download comic files directly over WiFi to and from the app.
|
||||
|
||||
ComicFlow is [entirely open-source](https://github.com/swisspol/ComicFlow) and you can see how it uses GCDWebServer in the [WebServer.m](https://github.com/swisspol/ComicFlow/blob/master/Classes/WebServer.m) file.
|
||||
ComicFlow is [entirely open-source](https://github.com/swisspol/ComicFlow) and you can see how it uses GCDWebUploader in the [WebServer.m](https://github.com/swisspol/ComicFlow/blob/master/Classes/WebServer.m) file.
|
||||
|
||||
Reference in New Issue
Block a user