Compare commits
	
		
			46 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| c2f4de822f | |||
| ffd4c03d9c | |||
| 2e08ac06ca | |||
| 6d739972de | |||
| e36fd43f9b | |||
| 35bbc6c61b | |||
| 987c704730 | |||
| 9669f2aa0b | |||
| 99139e360d | |||
| 696a92096d | |||
| f125c23fb9 | |||
| c50d6c4bfe | |||
| 5edea74333 | |||
| 1882a94e65 | |||
| 1309293705 | |||
| d24c3d4895 | |||
| 5e9fcc09c8 | |||
| fb7f1dd3a5 | |||
| 2f4fe0a55f | |||
| a3fc9092e3 | |||
| 6eb48bf72f | |||
| 40aa6c8917 | |||
| 24febefba4 | |||
| 57d9b4d324 | |||
| 3ca73e3221 | |||
| 27cf4cf0c0 | |||
| ef6b680b7e | |||
| 188ca7e679 | |||
| b8f1b26aba | |||
| ac768524ee | |||
| a5008ab455 | |||
| 9436dcd43e | |||
| f543347b1c | |||
| 582854878b | |||
| 642ee5a485 | |||
| 19b20daded | |||
| 270e6a9397 | |||
| ef5351a075 | |||
| 01ac021c7e | |||
| 47aeaff66e | |||
| d18a5fd272 | |||
| 3a0566ca0a | |||
| 36f62dd502 | |||
| 5b1a94c735 | |||
| 75c3a98f33 | |||
| e9fbfd0277 | 
							
								
								
									
										9
									
								
								.hgtags
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								.hgtags
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					e2250a7fd29052ea767f18e1459cabea4cd7efd3 release-1.0.0
 | 
				
			||||||
 | 
					b8975b9e75648a7c2a5003c67db92cf2216e01c0 release-1.0.1
 | 
				
			||||||
 | 
					c7b699105bd166e7a01aa0e678d34624680bf81e release-1.1.0
 | 
				
			||||||
 | 
					c7b699105bd166e7a01aa0e678d34624680bf81e release-1.1.0
 | 
				
			||||||
 | 
					0000000000000000000000000000000000000000 release-1.1.0
 | 
				
			||||||
 | 
					0000000000000000000000000000000000000000 release-1.1.0
 | 
				
			||||||
 | 
					cfb1e028fd0627614aa01184893f9f29f20a347e release-1.1.0
 | 
				
			||||||
 | 
					cfb1e028fd0627614aa01184893f9f29f20a347e release-1.1.0
 | 
				
			||||||
 | 
					0000000000000000000000000000000000000000 release-1.1.0
 | 
				
			||||||
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							@@ -2,7 +2,7 @@
 | 
				
			|||||||
# Makefile for contented
 | 
					# Makefile for contented
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VERSION:=1.0.0
 | 
					VERSION:=1.1.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SOURCES:=Makefile \
 | 
					SOURCES:=Makefile \
 | 
				
			||||||
	static \
 | 
						static \
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										25
									
								
								Server.go
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								Server.go
									
									
									
									
									
								
							@@ -20,9 +20,11 @@ type ServerPublicProperties struct {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type ServerOptions struct {
 | 
					type ServerOptions struct {
 | 
				
			||||||
	DataDirectory  string
 | 
						DataDirectory      string
 | 
				
			||||||
	DBPath         string
 | 
						DBPath             string
 | 
				
			||||||
	BandwidthLimit int64
 | 
						BandwidthLimit     int64
 | 
				
			||||||
 | 
						TrustXForwardedFor bool
 | 
				
			||||||
 | 
						EnableHomepage     bool
 | 
				
			||||||
	ServerPublicProperties
 | 
						ServerPublicProperties
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -75,7 +77,13 @@ func (this *Server) handleAbout(w http.ResponseWriter) {
 | 
				
			|||||||
	this.serveJsonObject(w, this.opts.ServerPublicProperties)
 | 
						this.serveJsonObject(w, this.opts.ServerPublicProperties)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func remoteIP(r *http.Request) string {
 | 
					func (this *Server) remoteIP(r *http.Request) string {
 | 
				
			||||||
 | 
						if this.opts.TrustXForwardedFor {
 | 
				
			||||||
 | 
							if xff := r.Header.Get("X-Forwarded-For"); len(xff) > 0 {
 | 
				
			||||||
 | 
								return xff
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return strings.TrimRight(strings.TrimRight(r.RemoteAddr, "0123456789"), ":")
 | 
						return strings.TrimRight(strings.TrimRight(r.RemoteAddr, "0123456789"), ":")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -86,6 +94,7 @@ const (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (this *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 | 
					func (this *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
	w.Header().Set(`Server`, SERVER_HEADER)
 | 
						w.Header().Set(`Server`, SERVER_HEADER)
 | 
				
			||||||
 | 
						w.Header().Set(`Access-Control-Allow-Origin`, `*`) // Blanket allow CORS
 | 
				
			||||||
	if this.opts.MaxUploadBytes > 0 {
 | 
						if this.opts.MaxUploadBytes > 0 {
 | 
				
			||||||
		r.Body = http.MaxBytesReader(w, r.Body, this.opts.MaxUploadBytes)
 | 
							r.Body = http.MaxBytesReader(w, r.Body, this.opts.MaxUploadBytes)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -108,11 +117,13 @@ func (this *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 | 
				
			|||||||
		this.handleUpload(w, r)
 | 
							this.handleUpload(w, r)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	} else if r.Method == "OPTIONS" {
 | 
						} else if r.Method == "OPTIONS" {
 | 
				
			||||||
		// Blanket allow
 | 
							// Blanket allow (headers already set)
 | 
				
			||||||
		w.Header().Set(`Access-Control-Allow-Origin`, `*`)
 | 
					 | 
				
			||||||
		w.WriteHeader(200)
 | 
							w.WriteHeader(200)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	} else if static, err := Asset(r.URL.Path[1:]); err == nil && r.Method == "GET" {
 | 
						} else if r.Method == "GET" && r.URL.Path == `/` && this.opts.EnableHomepage {
 | 
				
			||||||
 | 
							http.Redirect(w, r, `/index.html`, http.StatusFound)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						} else if static, err := Asset(r.URL.Path[1:]); err == nil && r.Method == "GET" && (this.opts.EnableHomepage || r.URL.Path != `/index.html`) {
 | 
				
			||||||
		http.ServeContent(w, r, r.URL.Path[1:], this.startTime, bytes.NewReader(static))
 | 
							http.ServeContent(w, r, r.URL.Path[1:], this.startTime, bytes.NewReader(static))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										4
									
								
								TODO.txt
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								TODO.txt
									
									
									
									
									
								
							@@ -8,6 +8,6 @@ TODO
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
- Nicer preview page after uploading
 | 
					- Nicer preview page after uploading
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Option to disable manual uploading from the landing page
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
- Gallery preview (multiple element hashid)
 | 
					- Gallery preview (multiple element hashid)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Prevent selecting around the toggle buttons (firefox for android)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,9 +6,11 @@ You can use contented as a standalone upload server, or you can use the SDK to e
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
=FEATURES=
 | 
					=FEATURES=
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- Drag and drop uploader, or fallback classic uploader, or pastebin-style uploader
 | 
					- Drag and drop upload
 | 
				
			||||||
- Multiple files upload
 | 
					- Multiple files upload
 | 
				
			||||||
- Pastebin upload
 | 
					- Pastebin upload
 | 
				
			||||||
 | 
					- Custom drawing upload ([url=https://github.com/Leimi/drawingboard.js]via[/url])
 | 
				
			||||||
 | 
					- Ctrl-V upload
 | 
				
			||||||
- SDK-oriented design for embedding, including CORS support
 | 
					- SDK-oriented design for embedding, including CORS support
 | 
				
			||||||
- Mobile friendly HTML interface
 | 
					- Mobile friendly HTML interface
 | 
				
			||||||
- Preserves uploaded filename and content-type metadata
 | 
					- Preserves uploaded filename and content-type metadata
 | 
				
			||||||
@@ -24,6 +26,8 @@ You can use contented as a standalone upload server, or you can use the SDK to e
 | 
				
			|||||||
        Directory for stored content (default "")
 | 
					        Directory for stored content (default "")
 | 
				
			||||||
  -db string
 | 
					  -db string
 | 
				
			||||||
        Path for metadata database (default "contented.db")
 | 
					        Path for metadata database (default "contented.db")
 | 
				
			||||||
 | 
					  -enableHomepage
 | 
				
			||||||
 | 
					        Enable homepage (disable for embedded use only) (default true)
 | 
				
			||||||
  -listen string
 | 
					  -listen string
 | 
				
			||||||
         (default "127.0.0.1:80")
 | 
					         (default "127.0.0.1:80")
 | 
				
			||||||
  -max int
 | 
					  -max int
 | 
				
			||||||
@@ -32,8 +36,12 @@ You can use contented as a standalone upload server, or you can use the SDK to e
 | 
				
			|||||||
        Maximum upload speed in bytes/sec (set zero for unlimited)
 | 
					        Maximum upload speed in bytes/sec (set zero for unlimited)
 | 
				
			||||||
  -title string
 | 
					  -title string
 | 
				
			||||||
        Title used in web interface (default "contented")
 | 
					        Title used in web interface (default "contented")
 | 
				
			||||||
 | 
					  -trustXForwardedFor
 | 
				
			||||||
 | 
					        Trust X-Forwarded-For reverse proxy headers
 | 
				
			||||||
`
 | 
					`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you are hosting behind a reverse proxy, remember to set its post body size parameter appropriately (e.g. `client_max_body_size` for nginx).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
=USAGE (HTTP)=
 | 
					=USAGE (HTTP)=
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The server responds on the following URLs:
 | 
					The server responds on the following URLs:
 | 
				
			||||||
@@ -44,18 +52,31 @@ The server responds on the following URLs:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
=USAGE (EMBEDDING FOR WEB)=
 | 
					=USAGE (EMBEDDING FOR WEB)=
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Your webpage should load the SDK from the contented server, then call the `contented.init` function to display the upload widget over the top of an existing DOM element.
 | 
					Your webpage should load the SDK from the contented server, then call the `contented.init` function to display the upload widget over the top of an existing DOM element. Your callback will be passed an array of file IDs of any uploaded items.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The SDK will run your callback, passing it the file IDs of any uploaded items.
 | 
					`<script type="text/javascript" src="SERVER_ADDR/sdk.js"></script>
 | 
				
			||||||
 | 
					 | 
				
			||||||
The SDK depends on jQuery.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
`
 | 
					 | 
				
			||||||
<script type="text/javascript" src="SERVER_ADDR/sdk.js"></script>
 | 
					 | 
				
			||||||
contented.init("#target", function(/* String[] */ items) {});
 | 
					contented.init("#target", function(/* String[] */ items) {});
 | 
				
			||||||
`
 | 
					`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
=CHANGELOG=
 | 
					=CHANGELOG=
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2017-10-15: 1.1.0
 | 
				
			||||||
 | 
					- Feature: Drawing mode
 | 
				
			||||||
 | 
					- Feature: Ctrl+V image upload
 | 
				
			||||||
 | 
					- Feature: Option to trust X-Forwarded-For headers when using a reverse proxy
 | 
				
			||||||
 | 
					- Feature: Add `getDownloadURL`, `getInfoJSONURL`, `getPreviewURL` SDK methods
 | 
				
			||||||
 | 
					- Feature: Option to disable uploading via the homepage
 | 
				
			||||||
 | 
					- Feature: Add button to repeat when uploading from homepage
 | 
				
			||||||
 | 
					- Enhancement: Automatically load library dependencies
 | 
				
			||||||
 | 
					- Enhancement: Display homepage widget using the full screen size
 | 
				
			||||||
 | 
					- Include drawingboard.js 0.4.6 (MIT license)
 | 
				
			||||||
 | 
					- Fix a cosmetic issue with javascript console output
 | 
				
			||||||
 | 
					- Fix a cosmetic issue with error messages if an upload failed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					2017-10-08: 1.0.1
 | 
				
			||||||
 | 
					- Fix an issue with CORS preflight requests
 | 
				
			||||||
 | 
					- Fix an issue with index URLs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
2017-10-08: 1.0.0
 | 
					2017-10-08: 1.0.0
 | 
				
			||||||
- Initial public release
 | 
					- Initial public release
 | 
				
			||||||
 | 
					- Include jQuery 1.12.4 (MIT license)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										
											BIN
										
									
								
								_dist/image1.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								_dist/image1.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 7.2 KiB  | 
@@ -18,13 +18,17 @@ func main() {
 | 
				
			|||||||
	appTitle := flag.String("title", "contented", "Title used in web interface")
 | 
						appTitle := flag.String("title", "contented", "Title used in web interface")
 | 
				
			||||||
	maxUploadMb := flag.Int("max", 8, "Maximum size of uploaded files in MiB (set zero for unlimited)")
 | 
						maxUploadMb := flag.Int("max", 8, "Maximum size of uploaded files in MiB (set zero for unlimited)")
 | 
				
			||||||
	maxUploadSpeed := flag.Int("speed", 0, "Maximum upload speed in bytes/sec (set zero for unlimited)")
 | 
						maxUploadSpeed := flag.Int("speed", 0, "Maximum upload speed in bytes/sec (set zero for unlimited)")
 | 
				
			||||||
 | 
						trustXForwardedFor := flag.Bool("trustXForwardedFor", false, "Trust X-Forwarded-For reverse proxy headers")
 | 
				
			||||||
 | 
						enableHomepage := flag.Bool("enableHomepage", true, "Enable homepage (disable for embedded use only)")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	flag.Parse()
 | 
						flag.Parse()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	svr, err := contented.NewServer(&contented.ServerOptions{
 | 
						svr, err := contented.NewServer(&contented.ServerOptions{
 | 
				
			||||||
		DataDirectory:  *dataDir,
 | 
							DataDirectory:      *dataDir,
 | 
				
			||||||
		DBPath:         *dbPath,
 | 
							DBPath:             *dbPath,
 | 
				
			||||||
		BandwidthLimit: int64(*maxUploadSpeed),
 | 
							BandwidthLimit:     int64(*maxUploadSpeed),
 | 
				
			||||||
 | 
							TrustXForwardedFor: *trustXForwardedFor,
 | 
				
			||||||
 | 
							EnableHomepage:     *enableHomepage,
 | 
				
			||||||
		ServerPublicProperties: contented.ServerPublicProperties{
 | 
							ServerPublicProperties: contented.ServerPublicProperties{
 | 
				
			||||||
			AppTitle:       *appTitle,
 | 
								AppTitle:       *appTitle,
 | 
				
			||||||
			MaxUploadBytes: int64(*maxUploadMb) * 1024 * 1024,
 | 
								MaxUploadBytes: int64(*maxUploadMb) * 1024 * 1024,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,7 +10,7 @@ import (
 | 
				
			|||||||
func (this *Server) handleView(w http.ResponseWriter, r *http.Request, fileID string) {
 | 
					func (this *Server) handleView(w http.ResponseWriter, r *http.Request, fileID string) {
 | 
				
			||||||
	err := this.handleViewInternal(w, r, r.URL.Path[len(downloadUrlPrefix):])
 | 
						err := this.handleViewInternal(w, r, r.URL.Path[len(downloadUrlPrefix):])
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Printf("%s View failed: %s\n", r.RemoteAddr, err.Error())
 | 
							log.Printf("%s View failed: %s\n", this.remoteIP(r), err.Error())
 | 
				
			||||||
		if os.IsNotExist(err) {
 | 
							if os.IsNotExist(err) {
 | 
				
			||||||
			http.Error(w, "File not found", 404)
 | 
								http.Error(w, "File not found", 404)
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										5
									
								
								static/drawingboard-0.4.6.min.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								static/drawingboard-0.4.6.min.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										4
									
								
								static/drawingboard-0.4.6.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								static/drawingboard-0.4.6.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@@ -7,9 +7,23 @@
 | 
				
			|||||||
		<style type="text/css">
 | 
							<style type="text/css">
 | 
				
			||||||
html, body {
 | 
					html, body {
 | 
				
			||||||
	font-family: sans-serif;
 | 
						font-family: sans-serif;
 | 
				
			||||||
 | 
						margin:0;
 | 
				
			||||||
 | 
						width:100%;
 | 
				
			||||||
 | 
						height:100%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#padder {
 | 
				
			||||||
 | 
						height:100%;
 | 
				
			||||||
 | 
						position:relative;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#surrogate-area {
 | 
					#surrogate-area {
 | 
				
			||||||
    height:300px;
 | 
					    position:absolute;
 | 
				
			||||||
 | 
					    top:10px;
 | 
				
			||||||
 | 
					    bottom:10px;
 | 
				
			||||||
 | 
					    left:10px;
 | 
				
			||||||
 | 
					    right:10px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					button.again {
 | 
				
			||||||
 | 
						margin-top:2em;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
/* hide close button */
 | 
					/* hide close button */
 | 
				
			||||||
.contented-close {
 | 
					.contented-close {
 | 
				
			||||||
@@ -18,9 +32,11 @@ html, body {
 | 
				
			|||||||
		</style>
 | 
							</style>
 | 
				
			||||||
	</head>
 | 
						</head>
 | 
				
			||||||
	<body>
 | 
						<body>
 | 
				
			||||||
        <div id="surrogate-area">
 | 
							<div id="padder">
 | 
				
			||||||
            Loading...
 | 
								<div id="surrogate-area">
 | 
				
			||||||
        </div>
 | 
									Loading...
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        <script type="text/javascript" src="/jquery-1.12.4.min.js"></script>
 | 
					        <script type="text/javascript" src="/jquery-1.12.4.min.js"></script>
 | 
				
			||||||
		<script type="text/javascript" src="/sdk.js"></script>
 | 
							<script type="text/javascript" src="/sdk.js"></script>
 | 
				
			||||||
@@ -45,11 +61,16 @@ contented.init("#surrogate-area", function(items) {
 | 
				
			|||||||
    for (var i = 0; i < items.length; ++i) {
 | 
					    for (var i = 0; i < items.length; ++i) {
 | 
				
			||||||
        $table.append($("<tr>").append([
 | 
					        $table.append($("<tr>").append([
 | 
				
			||||||
            $("<td>").text(items[i]),
 | 
					            $("<td>").text(items[i]),
 | 
				
			||||||
            $("<td>").html("<a target='_blank' href='/get/" + items[i] + "'>get</a>"),
 | 
					            $("<td>").html("<a target='_blank' href='" + contented.getDownloadURL(items[i]) + "'>get</a>"),
 | 
				
			||||||
            $("<td>").html("<a target='_blank' href='/info/" + items[i] + "'>info</a>")
 | 
					            $("<td>").html("<a target='_blank' href='" + contented.getInfoJSONURL(items[i]) + "'>info</a>"),
 | 
				
			||||||
        ]))
 | 
					        ]))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    $("#surrogate-area").html($table);
 | 
					    $("#surrogate-area").html([
 | 
				
			||||||
 | 
							$table,
 | 
				
			||||||
 | 
							$("<button>").addClass("again").text("Again...").click(function() {
 | 
				
			||||||
 | 
								window.location.href = window.location.href;
 | 
				
			||||||
 | 
							}),
 | 
				
			||||||
 | 
						]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
		</script>
 | 
							</script>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										639
									
								
								static/sdk.js
									
									
									
									
									
								
							
							
						
						
									
										639
									
								
								static/sdk.js
									
									
									
									
									
								
							@@ -1,214 +1,29 @@
 | 
				
			|||||||
;
 | 
					;
 | 
				
			||||||
var contented = (function ($, currentScriptPath) {
 | 
					 | 
				
			||||||
    "use strict";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var baseURL = currentScriptPath.replace('sdk.js', '');
 | 
					//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var formatBytes = function(bytes) {
 | 
					var contented = (function() {
 | 
				
			||||||
        if (bytes < 1024) {
 | 
						"use strict";
 | 
				
			||||||
            return bytes + " B";
 | 
					 | 
				
			||||||
        } else if (bytes < (1024*1024)) {
 | 
					 | 
				
			||||||
            return (bytes / 1024).toFixed(1) + " KiB";
 | 
					 | 
				
			||||||
        } else if (bytes < (1024*1024*1024)) {
 | 
					 | 
				
			||||||
            return (bytes / (1024*1024)).toFixed(1) + " MiB";
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            return (bytes / (1024*1024*1024)).toFixed(1) + " GiB";
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
    /**
 | 
						// @ref https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob 
 | 
				
			||||||
     * supportsDrop returns whether drag-and-drop is supported by this browser.
 | 
						if (!HTMLCanvasElement.prototype.toBlob) {
 | 
				
			||||||
     *
 | 
							Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
 | 
				
			||||||
     * @return bool
 | 
								value: function (callback, type, quality) {
 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    var supportsDrop = function () {
 | 
					 | 
				
			||||||
        return ('ondrop' in window && 'FormData' in window && 'FileReader' in window);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
									var binStr = atob( this.toDataURL(type, quality).split(',')[1] ),
 | 
				
			||||||
     * initArea shows the contented upload widget over the top of a target DOM element.
 | 
										len = binStr.length,
 | 
				
			||||||
     *
 | 
										arr = new Uint8Array(len);
 | 
				
			||||||
     * @param any        element       Drop target (string selector / DOMElement / jQuery)
 | 
					 | 
				
			||||||
     * @param Function   onUploaded    Called with an array of upload IDs
 | 
					 | 
				
			||||||
     * @param Function   onClose       Called when the widget is being destroyed
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    var initArea = function (elementSelector, onUploaded, onClose) {
 | 
					 | 
				
			||||||
        onUploaded = onUploaded || function () { };
 | 
					 | 
				
			||||||
        onClose = onClose || function () { };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ($(elementSelector).length != 1) {
 | 
									for (var i = 0; i < len; i++ ) {
 | 
				
			||||||
            return; // should only find one element
 | 
										arr[i] = binStr.charCodeAt(i);
 | 
				
			||||||
        }
 | 
									}
 | 
				
			||||||
        var element = $(elementSelector)[0];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // <input type="hidden" name="MAX_FILE_SIZE" value="` + ret.MaxUploadBytes + `" /> 
 | 
									callback( new Blob( [arr], {type: type || 'image/png'} ) );
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
        // Create a new div for ourselves on top of the existing area
 | 
							});
 | 
				
			||||||
        $.get(baseURL + "about", function (ret) {
 | 
						}
 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            var extraText = "";
 | 
					 | 
				
			||||||
            if (ret.MaxUploadBytes > 0) {
 | 
					 | 
				
			||||||
                extraText = " (max " + formatBytes(ret.MaxUploadBytes) + ")";
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            $.get(baseURL + "widget.html", function (widgetHtml) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                var $f = $("<div>").html(widgetHtml);
 | 
					 | 
				
			||||||
                $f.find(".contented-extratext").text(extraText);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                var ourClose = function () {
 | 
					 | 
				
			||||||
                    $f.remove(); // remove from dom
 | 
					 | 
				
			||||||
                    onClose(); // upstream close
 | 
					 | 
				
			||||||
                };
 | 
					 | 
				
			||||||
                $f.find(".contented-close").click(function () {
 | 
					 | 
				
			||||||
                    ourClose();
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                var setType = function (type) {
 | 
					 | 
				
			||||||
                    $f.find(".contented-upload-type").removeClass("contented-upload-type-active");
 | 
					 | 
				
			||||||
                    $f.find(".contented-upload-type[data-upload-type=" + type + "]").addClass("contented-upload-type-active");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    $f.find(".contented-upload-if").removeClass("contented-active");
 | 
					 | 
				
			||||||
                    $f.find(".contented-if-" + type).addClass("contented-active");
 | 
					 | 
				
			||||||
                };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                $f.find(".contented-upload-type").click(function () {
 | 
					 | 
				
			||||||
                    setType($(this).attr('data-upload-type'));
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if (!supportsDrop()) {
 | 
					 | 
				
			||||||
                    // switch default
 | 
					 | 
				
			||||||
                    setType('file');
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                //
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                var $element = $(element);
 | 
					 | 
				
			||||||
                var offset = $element.offset();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                $f.css({
 | 
					 | 
				
			||||||
                    'position': 'absolute',
 | 
					 | 
				
			||||||
                    'left': offset.left + "px",
 | 
					 | 
				
			||||||
                    'top': offset.top + "px",
 | 
					 | 
				
			||||||
                    'width': $element.width() + "px",
 | 
					 | 
				
			||||||
                    'min-width': $element.width() + "px",
 | 
					 | 
				
			||||||
                    'max-width': $element.width() + "px",
 | 
					 | 
				
			||||||
                    'height': $element.height() + "px",
 | 
					 | 
				
			||||||
                    'min-height': $element.height() + "px",
 | 
					 | 
				
			||||||
                    'max-height': $element.height() + "px"
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                $f.find('.contented').on('dragover dragenter', function (e) {
 | 
					 | 
				
			||||||
                    e.preventDefault();
 | 
					 | 
				
			||||||
                    e.stopPropagation();
 | 
					 | 
				
			||||||
                    $(this).addClass('is-dragging');
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                $f.find('.contented').on('dragleave dragend', function (e) {
 | 
					 | 
				
			||||||
                    e.preventDefault();
 | 
					 | 
				
			||||||
                    e.stopPropagation();
 | 
					 | 
				
			||||||
                    $(this).removeClass('is-dragging');
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                $f.find('.contented').on('drop', function (e) {
 | 
					 | 
				
			||||||
                    e.preventDefault();
 | 
					 | 
				
			||||||
                    e.stopPropagation();
 | 
					 | 
				
			||||||
                    handleUploadFrom(e.originalEvent.dataTransfer.files);
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                $f.find('.contented-file-upload').on('click', function(e) {
 | 
					 | 
				
			||||||
                    e.preventDefault();
 | 
					 | 
				
			||||||
                    e.stopPropagation();
 | 
					 | 
				
			||||||
                    handleUploadFrom($(".contented-file-selector")[0].files);
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                $f.find('.contented-paste-upload').on('click', function(e) {
 | 
					 | 
				
			||||||
                    e.preventDefault();
 | 
					 | 
				
			||||||
                    e.stopPropagation();
 | 
					 | 
				
			||||||
                    var blob = new Blob([$(".contented-if-paste textarea").val()], {type : 'text/plain'});
 | 
					 | 
				
			||||||
                    handleUploadFrom([blob]);
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                $("body").append($f);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                var setProgressCaption = function(message) {
 | 
					 | 
				
			||||||
                    $f.find(".contented-if-progress label").text(message);
 | 
					 | 
				
			||||||
                };
 | 
					 | 
				
			||||||
                var setProgressPercentage = function(frc) {
 | 
					 | 
				
			||||||
                    $f.find(".contented-progress-element").css('width', (frc * 100) + "%");
 | 
					 | 
				
			||||||
                };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                var handleUploadFrom = function (files) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    setProgressCaption("Uploading, please wait...");
 | 
					 | 
				
			||||||
                    setProgressPercentage(0);
 | 
					 | 
				
			||||||
                    setType("progress");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    $f.find(".contented-upload-type-selector").hide();
 | 
					 | 
				
			||||||
                    $f.find(".contented").removeClass('is-dragging');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    // Ajax uploader
 | 
					 | 
				
			||||||
                    var ajaxData = new FormData();
 | 
					 | 
				
			||||||
                    for (var i = 0; i < files.length; ++i) {
 | 
					 | 
				
			||||||
                        ajaxData.append("f", files[i]);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    // ajax request
 | 
					 | 
				
			||||||
                    $.ajax({
 | 
					 | 
				
			||||||
                        url: baseURL + "upload",
 | 
					 | 
				
			||||||
                        type: "POST",
 | 
					 | 
				
			||||||
                        data: ajaxData,
 | 
					 | 
				
			||||||
                        dataType: 'json', // response type
 | 
					 | 
				
			||||||
                        cache: false,
 | 
					 | 
				
			||||||
                        contentType: false,
 | 
					 | 
				
			||||||
                        processData: false,
 | 
					 | 
				
			||||||
                        xhr: function() {
 | 
					 | 
				
			||||||
                            var xhr = $.ajaxSettings.xhr();
 | 
					 | 
				
			||||||
                            xhr.upload.addEventListener(
 | 
					 | 
				
			||||||
                                'progress',
 | 
					 | 
				
			||||||
                                function(ev) {
 | 
					 | 
				
			||||||
                                    console.log([ev.lengthComputable, ev.loaded, ev.total]);
 | 
					 | 
				
			||||||
                                    if (ev.lengthComputable) {
 | 
					 | 
				
			||||||
                                        setProgressCaption("Uploading (" + formatBytes(ev.loaded) + " / " + formatBytes(ev.total) + ")...");
 | 
					 | 
				
			||||||
                                        setProgressPercentage(ev.total == 0 ? 0 : ev.loaded / ev.total);
 | 
					 | 
				
			||||||
                                    }
 | 
					 | 
				
			||||||
                                },
 | 
					 | 
				
			||||||
                                false
 | 
					 | 
				
			||||||
                            );
 | 
					 | 
				
			||||||
                            return xhr;
 | 
					 | 
				
			||||||
                        },
 | 
					 | 
				
			||||||
                        complete: function () {
 | 
					 | 
				
			||||||
                            setProgressCaption("Upload complete.");
 | 
					 | 
				
			||||||
                            setProgressPercentage(1);
 | 
					 | 
				
			||||||
                        },
 | 
					 | 
				
			||||||
                        success: function (data) {
 | 
					 | 
				
			||||||
                            onUploaded(data);
 | 
					 | 
				
			||||||
                            ourClose();
 | 
					 | 
				
			||||||
                        },
 | 
					 | 
				
			||||||
                        error: function () {
 | 
					 | 
				
			||||||
                            setProgressCaption("Upload failed.");
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    //
 | 
					 | 
				
			||||||
    return {
 | 
					 | 
				
			||||||
        'supportsDrop': supportsDrop,
 | 
					 | 
				
			||||||
        'init': initArea
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
})(
 | 
					 | 
				
			||||||
    jQuery,
 | 
					 | 
				
			||||||
    (function () {
 | 
					 | 
				
			||||||
        "use strict";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var getCurrentScriptPath = function () {
 | 
				
			||||||
        // Determine current script path
 | 
					        // Determine current script path
 | 
				
			||||||
        // @ref https://stackoverflow.com/a/26023176
 | 
					        // @ref https://stackoverflow.com/a/26023176
 | 
				
			||||||
        var scripts = document.querySelectorAll('script[src]');
 | 
					        var scripts = document.querySelectorAll('script[src]');
 | 
				
			||||||
@@ -217,5 +32,419 @@ var contented = (function ($, currentScriptPath) {
 | 
				
			|||||||
        var currentScriptFile = currentScriptChunks[currentScriptChunks.length - 1];
 | 
					        var currentScriptFile = currentScriptChunks[currentScriptChunks.length - 1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return currentScript.replace(currentScriptFile, '');
 | 
					        return currentScript.replace(currentScriptFile, '');
 | 
				
			||||||
    })()
 | 
					    };
 | 
				
			||||||
);
 | 
						
 | 
				
			||||||
 | 
						var currentScriptPath = getCurrentScriptPath();
 | 
				
			||||||
 | 
						var baseURL = currentScriptPath.replace('sdk.js', '');
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						return {
 | 
				
			||||||
 | 
							"loaded": false,
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							"baseURL": baseURL,
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							"__preInit": [],
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							* initArea shows the contented upload widget over the top of a target DOM element.
 | 
				
			||||||
 | 
							*
 | 
				
			||||||
 | 
							* @param any        element       Drop target (string selector / DOMElement / jQuery)
 | 
				
			||||||
 | 
							* @param Function   onUploaded    Called with an array of upload IDs
 | 
				
			||||||
 | 
							* @param Function   onClose       Called when the widget is being destroyed
 | 
				
			||||||
 | 
							*/
 | 
				
			||||||
 | 
							"init": function(elementSelector, onUploaded, onClose) {
 | 
				
			||||||
 | 
								contented.__preInit.push([elementSelector, onUploaded, onClose]);
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							/**
 | 
				
			||||||
 | 
							* supportsDrop returns whether drag-and-drop is supported by this browser.
 | 
				
			||||||
 | 
							*
 | 
				
			||||||
 | 
							* @return bool
 | 
				
			||||||
 | 
							*/
 | 
				
			||||||
 | 
							"supportsDrop": function() {
 | 
				
			||||||
 | 
								return ('ondrop' in window && 'FormData' in window && 'FileReader' in window);
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							"getPreviewURL": function(id) {
 | 
				
			||||||
 | 
								return baseURL + "get/" + id; // n.b. there's no better preview URL yet
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"getDownloadURL": function(id) {
 | 
				
			||||||
 | 
								return baseURL + "get/" + id;
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"getInfoJSONURL": function(id) {
 | 
				
			||||||
 | 
								return baseURL + "info/" + id;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
					})();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					;(function() {
 | 
				
			||||||
 | 
						"use strict";
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						var loadScript = function(url, onLoad) {
 | 
				
			||||||
 | 
							var script = document.createElement('script');
 | 
				
			||||||
 | 
							script.onload = onLoad;
 | 
				
			||||||
 | 
							script.src = url;
 | 
				
			||||||
 | 
							document.head.appendChild(script);
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						var loadScripts = function(urls, onLoad) {
 | 
				
			||||||
 | 
							// load sequentially
 | 
				
			||||||
 | 
							var i = 0;
 | 
				
			||||||
 | 
							var loadNext = function() {
 | 
				
			||||||
 | 
								if (i === urls.length) {
 | 
				
			||||||
 | 
									onLoad();
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								var url = urls[i];
 | 
				
			||||||
 | 
								i += 1;
 | 
				
			||||||
 | 
								loadScript(url, loadNext);
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
							loadNext();
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
					    var formatBytes = function(bytes) {
 | 
				
			||||||
 | 
							var k = 1024, m = (1024*1024), g = (1024*1024*1024);
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
					        if (bytes < k) {
 | 
				
			||||||
 | 
					            return bytes + " B";
 | 
				
			||||||
 | 
					        } else if (bytes < m) {
 | 
				
			||||||
 | 
					            return (bytes / k).toFixed(1) + " KiB";
 | 
				
			||||||
 | 
					        } else if (bytes < g) {
 | 
				
			||||||
 | 
					            return (bytes / m).toFixed(1) + " MiB";
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            return (bytes / g).toFixed(1) + " GiB";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						// @ref https://stackoverflow.com/a/2117523
 | 
				
			||||||
 | 
						var guid = function uuidv4() {
 | 
				
			||||||
 | 
							return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
 | 
				
			||||||
 | 
								var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
 | 
				
			||||||
 | 
								return v.toString(16);
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var afterScriptsLoaded = function() {		
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							var initArea = function (elementSelector, onUploaded, onClose) {
 | 
				
			||||||
 | 
								onUploaded = onUploaded || function () { };
 | 
				
			||||||
 | 
								onClose = onClose || function () { };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if ($(elementSelector).length != 1) {
 | 
				
			||||||
 | 
									return; // should only find one element
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								var element = $(elementSelector)[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// <input type="hidden" name="MAX_FILE_SIZE" value="` + ret.MaxUploadBytes + `" /> 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Create a new div for ourselves on top of the existing area
 | 
				
			||||||
 | 
								$.get(contented.baseURL + "about", function (ret) {
 | 
				
			||||||
 | 
									
 | 
				
			||||||
 | 
									var extraText = "";
 | 
				
			||||||
 | 
									if (ret.MaxUploadBytes > 0) {
 | 
				
			||||||
 | 
										extraText = " (max " + formatBytes(ret.MaxUploadBytes) + ")";
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									$.get(contented.baseURL + "widget.html", function (widgetHtml) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										var $f = $("<div>").html(widgetHtml);
 | 
				
			||||||
 | 
										$f.find(".contented-extratext").text(extraText);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										// Tab buttons
 | 
				
			||||||
 | 
										
 | 
				
			||||||
 | 
										var hasSetupDrawingBoardYet = false;
 | 
				
			||||||
 | 
										var setType = function (type) {
 | 
				
			||||||
 | 
											$f.find(".contented-upload-type").removeClass("contented-upload-type-active");
 | 
				
			||||||
 | 
											$f.find(".contented-upload-type[data-upload-type=" + type + "]").addClass("contented-upload-type-active");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											$f.find(".contented-upload-if").removeClass("contented-active");
 | 
				
			||||||
 | 
											$f.find(".contented-if-" + type).addClass("contented-active");
 | 
				
			||||||
 | 
											
 | 
				
			||||||
 | 
											if (type == "drag") {
 | 
				
			||||||
 | 
												enablePasteHandler();
 | 
				
			||||||
 | 
											} else {
 | 
				
			||||||
 | 
												disablePasteHandler();
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											
 | 
				
			||||||
 | 
											if (type == "drawing" && !hasSetupDrawingBoardYet) {
 | 
				
			||||||
 | 
												setupDrawingBoard();
 | 
				
			||||||
 | 
												hasSetupDrawingBoardYet = true;
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										$f.find(".contented-upload-type").click(function () {
 | 
				
			||||||
 | 
											setType($(this).attr('data-upload-type'));
 | 
				
			||||||
 | 
										});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										// Widget positioning
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										var $element = $(element);
 | 
				
			||||||
 | 
										var offset = $element.offset();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										$f.css({
 | 
				
			||||||
 | 
											'position': 'absolute',
 | 
				
			||||||
 | 
											'left': offset.left + "px",
 | 
				
			||||||
 | 
											'top': offset.top + "px",
 | 
				
			||||||
 | 
											'width': $element.width() + "px",
 | 
				
			||||||
 | 
											'min-width': $element.width() + "px",
 | 
				
			||||||
 | 
											'max-width': $element.width() + "px",
 | 
				
			||||||
 | 
											'height': $element.height() + "px",
 | 
				
			||||||
 | 
											'min-height': $element.height() + "px",
 | 
				
			||||||
 | 
											'max-height': $element.height() + "px"
 | 
				
			||||||
 | 
										});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										// Drag and drop support
 | 
				
			||||||
 | 
										
 | 
				
			||||||
 | 
										$f.find('.contented').on('dragover dragenter', function (e) {
 | 
				
			||||||
 | 
											e.preventDefault();
 | 
				
			||||||
 | 
											e.stopPropagation();
 | 
				
			||||||
 | 
											$(this).addClass('is-dragging');
 | 
				
			||||||
 | 
										});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										$f.find('.contented').on('dragleave dragend', function (e) {
 | 
				
			||||||
 | 
											e.preventDefault();
 | 
				
			||||||
 | 
											e.stopPropagation();
 | 
				
			||||||
 | 
											$(this).removeClass('is-dragging');
 | 
				
			||||||
 | 
										});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										$f.find('.contented').on('drop', function (e) {
 | 
				
			||||||
 | 
											e.preventDefault();
 | 
				
			||||||
 | 
											e.stopPropagation();
 | 
				
			||||||
 | 
											handleUploadFrom(e.originalEvent.dataTransfer.files);
 | 
				
			||||||
 | 
										});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										$f.find('.contented-file-upload').on('click', function(e) {
 | 
				
			||||||
 | 
											e.preventDefault();
 | 
				
			||||||
 | 
											e.stopPropagation();
 | 
				
			||||||
 | 
											handleUploadFrom($(".contented-file-selector")[0].files);
 | 
				
			||||||
 | 
										});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										// Pastebin
 | 
				
			||||||
 | 
										
 | 
				
			||||||
 | 
										$f.find('.contented-paste-upload').on('click', function(e) {
 | 
				
			||||||
 | 
											e.preventDefault();
 | 
				
			||||||
 | 
											e.stopPropagation();
 | 
				
			||||||
 | 
											var blob = new Blob([$(".contented-if-paste textarea").val()], {type : 'text/plain'});
 | 
				
			||||||
 | 
											handleUploadFrom([blob]);
 | 
				
			||||||
 | 
										});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										// Ctrl+V uploads
 | 
				
			||||||
 | 
										
 | 
				
			||||||
 | 
										var pasteHandler = function(e) {
 | 
				
			||||||
 | 
											e.preventDefault();
 | 
				
			||||||
 | 
											e.stopPropagation();
 | 
				
			||||||
 | 
											
 | 
				
			||||||
 | 
											var items = (e.clipboardData || e.originalEvent.clipboardData).items;
 | 
				
			||||||
 | 
											var items_length = items.length;
 | 
				
			||||||
 | 
											var blobs = [];
 | 
				
			||||||
 | 
											var handled = 0;
 | 
				
			||||||
 | 
											var haveHandled = function() {
 | 
				
			||||||
 | 
												handled += 1;
 | 
				
			||||||
 | 
												if (handled == items_length) {
 | 
				
			||||||
 | 
													
 | 
				
			||||||
 | 
													if (blobs.length > 0) {
 | 
				
			||||||
 | 
														handleUploadFrom( blobs );
 | 
				
			||||||
 | 
													} else {
 | 
				
			||||||
 | 
														// alert("Pasted 0 files");
 | 
				
			||||||
 | 
													}
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
											};
 | 
				
			||||||
 | 
											
 | 
				
			||||||
 | 
											for (var i = 0; i < items.length; ++i) {
 | 
				
			||||||
 | 
												var item = items[i];
 | 
				
			||||||
 | 
												var mimeType = item.type;
 | 
				
			||||||
 | 
												if (item.kind === 'file') {
 | 
				
			||||||
 | 
													blobs.push(item.getAsFile());
 | 
				
			||||||
 | 
													haveHandled();
 | 
				
			||||||
 | 
													
 | 
				
			||||||
 | 
												} else if (item.kind === 'string') {
 | 
				
			||||||
 | 
													item.getAsString(function(s) {
 | 
				
			||||||
 | 
														blobs.push( new Blob([s], {type : mimeType}) );
 | 
				
			||||||
 | 
														haveHandled();
 | 
				
			||||||
 | 
													});
 | 
				
			||||||
 | 
													
 | 
				
			||||||
 | 
												} else {
 | 
				
			||||||
 | 
													// file|string are the only supported types in
 | 
				
			||||||
 | 
													// all browsers at the time of writing
 | 
				
			||||||
 | 
													// Ignore future possibilities
 | 
				
			||||||
 | 
													haveHandled();
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										};
 | 
				
			||||||
 | 
										var enablePasteHandler = function() {
 | 
				
			||||||
 | 
											document.addEventListener('paste', pasteHandler);
 | 
				
			||||||
 | 
										};
 | 
				
			||||||
 | 
										var disablePasteHandler = function() {
 | 
				
			||||||
 | 
											document.removeEventListener('paste', pasteHandler);
 | 
				
			||||||
 | 
										};
 | 
				
			||||||
 | 
										
 | 
				
			||||||
 | 
										// Embed in DOM, load default area
 | 
				
			||||||
 | 
										
 | 
				
			||||||
 | 
										$("body").append($f);
 | 
				
			||||||
 | 
										if (!contented.supportsDrop()) {
 | 
				
			||||||
 | 
											setType('file');
 | 
				
			||||||
 | 
										} else {
 | 
				
			||||||
 | 
											setType('drag');
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										
 | 
				
			||||||
 | 
										// Drawing board
 | 
				
			||||||
 | 
										
 | 
				
			||||||
 | 
										var setupDrawingBoard = function() {
 | 
				
			||||||
 | 
											
 | 
				
			||||||
 | 
											$("head").append(
 | 
				
			||||||
 | 
												'<link rel="stylesheet" type="text/css" href="' + contented.baseURL + 'drawingboard-0.4.6.min.css">'
 | 
				
			||||||
 | 
											);
 | 
				
			||||||
 | 
											
 | 
				
			||||||
 | 
											var db_id = "contented-drawing-area-" + guid();
 | 
				
			||||||
 | 
											var $db = $("<div>").attr('id', db_id);
 | 
				
			||||||
 | 
											
 | 
				
			||||||
 | 
											DrawingBoard.Control.ContentedUpload = DrawingBoard.Control.extend({
 | 
				
			||||||
 | 
												name: 'upload',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												initialize: function() {
 | 
				
			||||||
 | 
													var $el = this.$el;
 | 
				
			||||||
 | 
													
 | 
				
			||||||
 | 
													$el.append('<button class="contented-drawingboard-upload">Upload</button>');
 | 
				
			||||||
 | 
													$el.on('click', '.contented-drawingboard-upload', $.proxy(function(e) {
 | 
				
			||||||
 | 
														e.preventDefault();
 | 
				
			||||||
 | 
														e.stopPropagation();
 | 
				
			||||||
 | 
														
 | 
				
			||||||
 | 
														$el.prop('disabled', true);
 | 
				
			||||||
 | 
														$el.text('Saving...');
 | 
				
			||||||
 | 
														
 | 
				
			||||||
 | 
														$db.find("canvas")[0].toBlob(function(theBlob) {
 | 
				
			||||||
 | 
															handleUploadFrom([ theBlob ]);
 | 
				
			||||||
 | 
														});
 | 
				
			||||||
 | 
													}, this));
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
											});
 | 
				
			||||||
 | 
											
 | 
				
			||||||
 | 
											$db.css({
 | 
				
			||||||
 | 
												//'width': $f.find(".contented-content-area").width(),
 | 
				
			||||||
 | 
												'height': $f.find(".contented-content-area").height(),
 | 
				
			||||||
 | 
												'overflow': 'hidden'
 | 
				
			||||||
 | 
											});
 | 
				
			||||||
 | 
											
 | 
				
			||||||
 | 
											$f.find(".contented-drawing-area").append($db);
 | 
				
			||||||
 | 
											var db = new DrawingBoard.Board(db_id, {
 | 
				
			||||||
 | 
												'controls': [
 | 
				
			||||||
 | 
													'Color',
 | 
				
			||||||
 | 
													'Size',
 | 
				
			||||||
 | 
													'DrawingMode',
 | 
				
			||||||
 | 
													'Navigation',
 | 
				
			||||||
 | 
													'ContentedUpload'
 | 
				
			||||||
 | 
												],
 | 
				
			||||||
 | 
												'controlsPosition': 'center',
 | 
				
			||||||
 | 
												'enlargeYourContainer': false,
 | 
				
			||||||
 | 
												'webStorage': false,
 | 
				
			||||||
 | 
												'droppable': false // don't mess with existing drop support
 | 
				
			||||||
 | 
											});
 | 
				
			||||||
 | 
											
 | 
				
			||||||
 | 
										};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										// Close button
 | 
				
			||||||
 | 
										
 | 
				
			||||||
 | 
										var ourClose = function () {
 | 
				
			||||||
 | 
											$f.remove(); // remove from dom
 | 
				
			||||||
 | 
											disablePasteHandler();
 | 
				
			||||||
 | 
											onClose(); // upstream close
 | 
				
			||||||
 | 
										};
 | 
				
			||||||
 | 
										$f.find(".contented-close").click(function () {
 | 
				
			||||||
 | 
											ourClose();
 | 
				
			||||||
 | 
										})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										// Progress bar
 | 
				
			||||||
 | 
										
 | 
				
			||||||
 | 
										var setProgressCaption = function(message) {
 | 
				
			||||||
 | 
											$f.find(".contented-if-progress label").text(message);
 | 
				
			||||||
 | 
										};
 | 
				
			||||||
 | 
										var setProgressPercentage = function(frc) {
 | 
				
			||||||
 | 
											$f.find(".contented-progress-element").css('width', (frc * 100) + "%");
 | 
				
			||||||
 | 
										};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										// Common upload handler
 | 
				
			||||||
 | 
										
 | 
				
			||||||
 | 
										var handleUploadFrom = function(files) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											setProgressCaption("Uploading, please wait...");
 | 
				
			||||||
 | 
											setProgressPercentage(0);
 | 
				
			||||||
 | 
											setType("progress");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											$f.find(".contented-upload-type-selector").hide();
 | 
				
			||||||
 | 
											$f.find(".contented").removeClass('is-dragging');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											// Ajax uploader
 | 
				
			||||||
 | 
											var ajaxData = new FormData();
 | 
				
			||||||
 | 
											for (var i = 0; i < files.length; ++i) {
 | 
				
			||||||
 | 
												ajaxData.append("f", files[i]);
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
											// ajax request
 | 
				
			||||||
 | 
											$.ajax({
 | 
				
			||||||
 | 
												url: contented.baseURL + "upload",
 | 
				
			||||||
 | 
												type: "POST",
 | 
				
			||||||
 | 
												data: ajaxData,
 | 
				
			||||||
 | 
												dataType: 'json', // response type
 | 
				
			||||||
 | 
												cache: false,
 | 
				
			||||||
 | 
												contentType: false,
 | 
				
			||||||
 | 
												processData: false,
 | 
				
			||||||
 | 
												xhr: function() {
 | 
				
			||||||
 | 
													var xhr = $.ajaxSettings.xhr();
 | 
				
			||||||
 | 
													xhr.upload.addEventListener(
 | 
				
			||||||
 | 
														'progress',
 | 
				
			||||||
 | 
														function(ev) {
 | 
				
			||||||
 | 
															if (ev.lengthComputable) {
 | 
				
			||||||
 | 
																setProgressCaption("Uploading (" + formatBytes(ev.loaded) + " / " + formatBytes(ev.total) + ")...");
 | 
				
			||||||
 | 
																setProgressPercentage(ev.total == 0 ? 0 : ev.loaded / ev.total);
 | 
				
			||||||
 | 
															}
 | 
				
			||||||
 | 
														},
 | 
				
			||||||
 | 
														false
 | 
				
			||||||
 | 
													);
 | 
				
			||||||
 | 
													return xhr;
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
												complete: function () {
 | 
				
			||||||
 | 
													setProgressPercentage(1);
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
												success: function (data) {
 | 
				
			||||||
 | 
													setProgressCaption("Upload completed successfully.");
 | 
				
			||||||
 | 
													onUploaded(data);
 | 
				
			||||||
 | 
													ourClose();
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
 | 
												error: function () {
 | 
				
			||||||
 | 
													setProgressCaption("Upload failed!");
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
											});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										
 | 
				
			||||||
 | 
										// .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							// Update fields in global variable
 | 
				
			||||||
 | 
							contented.init = initArea;
 | 
				
			||||||
 | 
							contented.loaded = true;
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							// Call initArea for all pre-initialised elements
 | 
				
			||||||
 | 
							for (var i = 0; i < contented.__preInit.length; ++i) {
 | 
				
			||||||
 | 
								initArea(contented.__preInit[i][0], contented.__preInit[i][1], contented.__preInit[i][2]);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
						// Load scripts
 | 
				
			||||||
 | 
						var needScripts = [];
 | 
				
			||||||
 | 
						if (typeof jQuery === "undefined") {
 | 
				
			||||||
 | 
							needScripts.push(contented.baseURL + "jquery-1.12.4.min.js");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (typeof DrawingBoard === "undefined") {
 | 
				
			||||||
 | 
							needScripts.push(contented.baseURL + "drawingboard-0.4.6.min.js");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						loadScripts(needScripts, afterScriptsLoaded);
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
					})()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,6 +24,7 @@
 | 
				
			|||||||
.contented .contented-upload-type-selector {
 | 
					.contented .contented-upload-type-selector {
 | 
				
			||||||
    display:block;
 | 
					    display:block;
 | 
				
			||||||
    margin-bottom: 1em;
 | 
					    margin-bottom: 1em;
 | 
				
			||||||
 | 
					    -webkit-user-select: none;
 | 
				
			||||||
    user-select: none; 
 | 
					    user-select: none; 
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.contented .contented-upload-type {
 | 
					.contented .contented-upload-type {
 | 
				
			||||||
@@ -66,7 +67,7 @@
 | 
				
			|||||||
.contented-upload-if {
 | 
					.contented-upload-if {
 | 
				
			||||||
    display:none;
 | 
					    display:none;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.contented-if-paste {
 | 
					.contented-if-paste, .contented-if-drawing {
 | 
				
			||||||
    height:100%;
 | 
					    height:100%;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.contented-upload-if.contented-active {
 | 
					.contented-upload-if.contented-active {
 | 
				
			||||||
@@ -87,12 +88,14 @@
 | 
				
			|||||||
    border-radius:8px;
 | 
					    border-radius:8px;
 | 
				
			||||||
    background:lightgrey;
 | 
					    background:lightgrey;
 | 
				
			||||||
    position:relative;
 | 
					    position:relative;
 | 
				
			||||||
 | 
					    overflow:hidden;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.contented-progress-element {
 | 
					.contented-progress-element {
 | 
				
			||||||
    position:absolute;
 | 
					    position:absolute;
 | 
				
			||||||
    background:darkgreen;
 | 
					    background:darkgreen;
 | 
				
			||||||
    left:0;
 | 
					    left:0;
 | 
				
			||||||
    width:0%;
 | 
					    width:0%;
 | 
				
			||||||
 | 
					    height:100%;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
<div class="contented">
 | 
					<div class="contented">
 | 
				
			||||||
@@ -122,11 +125,17 @@
 | 
				
			|||||||
                <path fill="#000000" d="M19,20H5V4H7V7H17V4H19M12,2A1,1 0 0,1 13,3A1,1 0 0,1 12,4A1,1 0 0,1 11,3A1,1 0 0,1 12,2M19,2H14.82C14.4,0.84 13.3,0 12,0C10.7,0 9.6,0.84 9.18,2H5A2,2 0 0,0 3,4V20A2,2 0 0,0 5,22H19A2,2 0 0,0 21,20V4A2,2 0 0,0 19,2Z" />
 | 
					                <path fill="#000000" d="M19,20H5V4H7V7H17V4H19M12,2A1,1 0 0,1 13,3A1,1 0 0,1 12,4A1,1 0 0,1 11,3A1,1 0 0,1 12,2M19,2H14.82C14.4,0.84 13.3,0 12,0C10.7,0 9.6,0.84 9.18,2H5A2,2 0 0,0 3,4V20A2,2 0 0,0 5,22H19A2,2 0 0,0 21,20V4A2,2 0 0,0 19,2Z" />
 | 
				
			||||||
            </svg>
 | 
					            </svg>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        <div class="contented-upload-type" data-upload-type="drawing" title="Drawing">
 | 
				
			||||||
 | 
								<svg viewBox="0 0 24 24">
 | 
				
			||||||
 | 
									<path fill="#000000" d="M16.84,2.73C16.45,2.73 16.07,2.88 15.77,3.17L13.65,5.29L18.95,10.6L21.07,8.5C21.67,7.89 21.67,6.94 21.07,6.36L17.9,3.17C17.6,2.88 17.22,2.73 16.84,2.73M12.94,6L4.84,14.11L7.4,14.39L7.58,16.68L9.86,16.85L10.15,19.41L18.25,11.3M4.25,15.04L2.5,21.73L9.2,19.94L8.96,17.78L6.65,17.61L6.47,15.29" />
 | 
				
			||||||
 | 
								</svg>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    <div class="contented-content-area">
 | 
					    <div class="contented-content-area">
 | 
				
			||||||
        <div class="contented-upload-if contented-if-drag contented-active">
 | 
					        <div class="contented-upload-if contented-if-drag contented-active">
 | 
				
			||||||
            <label>Drop files to upload <span class="contented-extratext"></span></label>
 | 
					            <label>Drop files or Ctrl-V to upload <span class="contented-extratext"></span></label>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <div class="contented-upload-if contented-if-file">
 | 
					        <div class="contented-upload-if contented-if-file">
 | 
				
			||||||
@@ -140,6 +149,10 @@
 | 
				
			|||||||
            <button class="contented-paste-upload">Upload »</button>
 | 
					            <button class="contented-paste-upload">Upload »</button>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <div class="contented-upload-if contented-if-drawing">
 | 
				
			||||||
 | 
								<div class="contented-drawing-area"></div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
        <div class="contented-upload-if contented-if-progress">
 | 
					        <div class="contented-upload-if contented-if-progress">
 | 
				
			||||||
            <label>...</label>
 | 
					            <label>...</label>
 | 
				
			||||||
            <div class="contented-progress-bar"><div class="contented-progress-element"></div></div>
 | 
					            <div class="contented-progress-bar"><div class="contented-progress-element"></div></div>
 | 
				
			||||||
 
 | 
				
			|||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										14
									
								
								upload.go
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								upload.go
									
									
									
									
									
								
							@@ -18,15 +18,17 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (this *Server) handleUpload(w http.ResponseWriter, r *http.Request) {
 | 
					func (this *Server) handleUpload(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						remoteIP := this.remoteIP(r)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err := r.ParseMultipartForm(this.opts.MaxUploadBytes * 2)
 | 
						err := r.ParseMultipartForm(this.opts.MaxUploadBytes * 2)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Printf("%s Invalid request: %s\n", r.RemoteAddr, err.Error())
 | 
							log.Printf("%s Invalid request: %s\n", remoteIP, err.Error())
 | 
				
			||||||
		http.Error(w, "Invalid request", 400)
 | 
							http.Error(w, "Invalid request", 400)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if r.MultipartForm == nil || r.MultipartForm.File == nil || len(r.MultipartForm.File["f"]) < 1 {
 | 
						if r.MultipartForm == nil || r.MultipartForm.File == nil || len(r.MultipartForm.File["f"]) < 1 {
 | 
				
			||||||
		log.Printf("%s Invalid request: no multipart content\n", r.RemoteAddr)
 | 
							log.Printf("%s Invalid request: no multipart content\n", remoteIP)
 | 
				
			||||||
		http.Error(w, "Invalid request", 400)
 | 
							http.Error(w, "Invalid request", 400)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -36,14 +38,14 @@ func (this *Server) handleUpload(w http.ResponseWriter, r *http.Request) {
 | 
				
			|||||||
	for _, fhs := range r.MultipartForm.File["f"] {
 | 
						for _, fhs := range r.MultipartForm.File["f"] {
 | 
				
			||||||
		f, err := fhs.Open()
 | 
							f, err := fhs.Open()
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			log.Printf("%s Internal error: %s\n", r.RemoteAddr, err.Error())
 | 
								log.Printf("%s Internal error: %s\n", remoteIP, err.Error())
 | 
				
			||||||
			http.Error(w, "Internal error", 500)
 | 
								http.Error(w, "Internal error", 500)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		path, err := this.handleUploadFile(f, fhs, remoteIP(r))
 | 
							path, err := this.handleUploadFile(f, fhs, remoteIP)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			log.Printf("%s Upload failed: %s\n", r.RemoteAddr, err.Error())
 | 
								log.Printf("%s Upload failed: %s\n", remoteIP, err.Error())
 | 
				
			||||||
			http.Error(w, "Upload failed", 500)
 | 
								http.Error(w, "Upload failed", 500)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -52,7 +54,7 @@ func (this *Server) handleUpload(w http.ResponseWriter, r *http.Request) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	jb, err := json.Marshal(ret)
 | 
						jb, err := json.Marshal(ret)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Printf("%s Internal error: %s\n", r.RemoteAddr, err.Error())
 | 
							log.Printf("%s Internal error: %s\n", remoteIP, err.Error())
 | 
				
			||||||
		http.Error(w, "Internal error", 500)
 | 
							http.Error(w, "Internal error", 500)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user