uwa_files 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/uwa_files/config.rb +20 -0
- data/lib/uwa_files/widget.rb +109 -0
- data/resources/ajax.gif +0 -0
- data/resources/del.png +0 -0
- data/resources/parent.gif +0 -0
- data/resources/rename.png +0 -0
- data/resources/script.js +201 -0
- data/resources/sha1.js +99 -0
- data/resources/style.css +82 -0
- data/resources/upload.js +46 -0
- metadata +63 -0
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'uwa'
|
2
|
+
require 'digest/sha1'
|
3
|
+
require 'json'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
module UWA
|
7
|
+
module Widget
|
8
|
+
class Files < UWA::Handler
|
9
|
+
NAME = 'uwa_files'
|
10
|
+
VERSION = '0.1'
|
11
|
+
COPYRIGHT = 'Copyright (C) 2007 Florent Solt'
|
12
|
+
DESC = 'UWA Files widget'
|
13
|
+
AUTHOR = 'Florent Solt'
|
14
|
+
EMAIL = 'florent@solt.biz'
|
15
|
+
HOMEPAGE = 'http://gnetvibes.rubyforge.org'
|
16
|
+
LICENSE = 'BSD'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'uwa_files/config'
|
2
|
+
|
3
|
+
module UWA
|
4
|
+
module Widget
|
5
|
+
class Files
|
6
|
+
def initialize
|
7
|
+
super
|
8
|
+
@author = AUTHOR
|
9
|
+
@title = 'My Files'
|
10
|
+
@icon = 'http://www.netvibes.com/img/icons/folder.gif'
|
11
|
+
@tokens = {}
|
12
|
+
@preferences << {:name => :login, :type => :text, :label => 'Login'}
|
13
|
+
@preferences << {:name => :password, :type => :text, :label => 'Password'}
|
14
|
+
@start = '/tmp'
|
15
|
+
@users = {}
|
16
|
+
end
|
17
|
+
|
18
|
+
def login_token
|
19
|
+
token = new_token
|
20
|
+
@tokens[token] = {:login => query['login'], :auth => false, :files => {}}
|
21
|
+
self << token
|
22
|
+
end
|
23
|
+
|
24
|
+
def login
|
25
|
+
token = query['token']
|
26
|
+
login = @tokens[token][:login]
|
27
|
+
if Digest::SHA1.new(token + @users[login].to_s).hexdigest == query['digest']
|
28
|
+
UWA::Server.log(:info, "Login successful for \"#{login}\"")
|
29
|
+
self << token
|
30
|
+
@tokens[token][:auth] = true
|
31
|
+
else
|
32
|
+
UWA::Server.log(:warning, "Login failed for \"#{login}\"")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def files
|
37
|
+
return unless auth?
|
38
|
+
answer = {:type => nil, :data => []}
|
39
|
+
target = @token[:files][query['target']] || @start
|
40
|
+
|
41
|
+
if File.directory?(target)
|
42
|
+
@token[:files] = {} # Security: remove all unused tokens
|
43
|
+
answer[:type] = :dir
|
44
|
+
files = Dir[File.join(target, '*')].sort
|
45
|
+
files.unshift(File.join(target, '..'))
|
46
|
+
files.unshift(File.join(target, '.'))
|
47
|
+
files.each do |f|
|
48
|
+
ftoken = new_token
|
49
|
+
@token[:files][ftoken] = File.expand_path(f)
|
50
|
+
answer[:data] << {
|
51
|
+
:name => File.basename(f),
|
52
|
+
:type => File.directory?(f) ? :dir : :file,
|
53
|
+
:token => ftoken }
|
54
|
+
answer[:data].last[:path] = File.expand_path(f) if f[-1] == 46 # the dot dir
|
55
|
+
end
|
56
|
+
end
|
57
|
+
self << JSON.unparse(answer)
|
58
|
+
end
|
59
|
+
|
60
|
+
def download
|
61
|
+
return unless auth?
|
62
|
+
target = @token[:files][query['target']]
|
63
|
+
unless target.nil?
|
64
|
+
send_file(target)
|
65
|
+
else
|
66
|
+
response.status = '403'
|
67
|
+
self << 'Forbidden'
|
68
|
+
end
|
69
|
+
@token[:files].delete(query['target']) # Security: remove used file token
|
70
|
+
end
|
71
|
+
|
72
|
+
def upload
|
73
|
+
return unless auth?
|
74
|
+
target = @token[:files][query['target']]
|
75
|
+
File.open(File.join(target, query['file']['filename'] ), 'w') do |fd|
|
76
|
+
fd.write query['file']['tempfile'].read
|
77
|
+
end
|
78
|
+
self << "File #{query['file']['filename'].inspect} uploaded"
|
79
|
+
end
|
80
|
+
|
81
|
+
def delete
|
82
|
+
return unless auth?
|
83
|
+
target = @token[:files][query['target']]
|
84
|
+
FileUtils.rm_rf(target)
|
85
|
+
end
|
86
|
+
|
87
|
+
def rename
|
88
|
+
return unless auth?
|
89
|
+
target = @token[:files][query['target']]
|
90
|
+
new = query['new']
|
91
|
+
File.rename(target, File.join(File.dirname(target), File.basename(new)))
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def auth?
|
97
|
+
@token = query['token']
|
98
|
+
@token = @tokens[@token]
|
99
|
+
auth = @token[:auth] rescue false
|
100
|
+
UWA::Server.log(:warning, "Auth failed for token #{query['token'].inspect}") if not auth
|
101
|
+
auth
|
102
|
+
end
|
103
|
+
|
104
|
+
def new_token
|
105
|
+
Digest::SHA1.new(Time.now.to_s + rand(0xffffffff).to_s).hexdigest
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
data/resources/ajax.gif
ADDED
Binary file
|
data/resources/del.png
ADDED
Binary file
|
Binary file
|
Binary file
|
data/resources/script.js
ADDED
@@ -0,0 +1,201 @@
|
|
1
|
+
|
2
|
+
widget.onLoad = function() {
|
3
|
+
widget.files = widget.createElement('ul');
|
4
|
+
widget.files.className = 'uwa_files_list';
|
5
|
+
widget.footer = widget.createElement('div');
|
6
|
+
widget.footer.className = 'uwa_files_footer';
|
7
|
+
|
8
|
+
// Form creation
|
9
|
+
widget.form = widget.createElement('form');
|
10
|
+
widget.form.method = 'POST';
|
11
|
+
widget.form.enctype = 'multipart/form-data';
|
12
|
+
widget.form.onsubmit = function() {
|
13
|
+
this.action = this.url + '&target=' + widget.current;
|
14
|
+
return Uploader.submit(this, {
|
15
|
+
onStart : widget.setFooterUpload,
|
16
|
+
onComplete : function(msg) {
|
17
|
+
widget.setFooterForm(msg);
|
18
|
+
widget.onRefresh();
|
19
|
+
}});
|
20
|
+
}.bind(widget.form);
|
21
|
+
widget.file = widget.createElement('input');
|
22
|
+
widget.file.type = 'file';
|
23
|
+
widget.file.name = 'file';
|
24
|
+
widget.form.appendChild(widget.file);
|
25
|
+
var submit = widget.createElement('input');
|
26
|
+
submit.type = 'submit';
|
27
|
+
submit.value = 'Upload';
|
28
|
+
widget.form.appendChild(submit);
|
29
|
+
widget.footer.appendChild(widget.form);
|
30
|
+
|
31
|
+
// Message creation
|
32
|
+
widget.indicator = widget.createElement('img');
|
33
|
+
widget.indicator.src = widget.remoteUrl + 'resources/ajax.gif';
|
34
|
+
widget.footer.appendChild(widget.indicator);
|
35
|
+
widget.message = widget.createElement('div');
|
36
|
+
widget.message.className = 'uwa_files_message';
|
37
|
+
widget.message.setStyle('display', 'none');
|
38
|
+
widget.footer.appendChild(widget.message);
|
39
|
+
|
40
|
+
login = widget.getValue('login');
|
41
|
+
widget.remoteText('login_token?login=' + encodeURIComponent(login),
|
42
|
+
widget.onLoginToken);
|
43
|
+
}
|
44
|
+
|
45
|
+
widget.onLoginToken = function(token) {
|
46
|
+
digest = sha1(token + sha1(widget.getValue('password')));
|
47
|
+
widget.remoteText('login?token=' + token + '&digest=' + digest,
|
48
|
+
widget.onLogin);
|
49
|
+
}
|
50
|
+
|
51
|
+
widget.onLogin = function(token) {
|
52
|
+
if (token) {
|
53
|
+
widget.token = token;
|
54
|
+
widget.setBody(widget.files);
|
55
|
+
widget.body.appendChild(widget.footer);
|
56
|
+
widget.form.url = widget.remoteUrl + 'upload?token=' + widget.token;
|
57
|
+
widget.setFooterForm(null);
|
58
|
+
widget.refreshDir(null);
|
59
|
+
widget.onRefresh = function() {
|
60
|
+
widget.refreshDir(widget.current);
|
61
|
+
};
|
62
|
+
} else {
|
63
|
+
widget.setBody('Login failed !')
|
64
|
+
}
|
65
|
+
}
|
66
|
+
|
67
|
+
widget.setFooterForm = function(msg) {
|
68
|
+
widget.file.value = '';
|
69
|
+
widget.form.setStyle('display', 'block');
|
70
|
+
widget.indicator.setStyle('display', 'none');
|
71
|
+
if (msg) {
|
72
|
+
widget.message.setText(msg);
|
73
|
+
widget.message.setStyle('display', 'block');
|
74
|
+
} else {
|
75
|
+
widget.message.setStyle('display', 'none');
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
widget.setFooterUpload = function() {
|
80
|
+
widget.form.setStyle('display', 'none');
|
81
|
+
var filename = widget.file.value.split(/[\/\\]/);
|
82
|
+
widget.message.setText('Uploading ' + filename[filename.length-1]);
|
83
|
+
widget.message.setStyle('display', 'block');
|
84
|
+
widget.indicator.setStyle('display', 'block');
|
85
|
+
return true;
|
86
|
+
}
|
87
|
+
|
88
|
+
widget.refreshDir = function(target) {
|
89
|
+
widget.remoteJson('files?token=' + widget.token + '&target=' + encodeURIComponent(target || ''),
|
90
|
+
widget.onFiles);
|
91
|
+
}
|
92
|
+
|
93
|
+
widget.onFiles = function(answer) {
|
94
|
+
switch(answer.type) {
|
95
|
+
case 'dir':
|
96
|
+
widget.files.empty();
|
97
|
+
widget.current = answer.data[0].token;
|
98
|
+
var li = widget.createElement('li');
|
99
|
+
li.className = 'parent';
|
100
|
+
|
101
|
+
var a = widget.createElement('a');
|
102
|
+
a.className = 'parent';
|
103
|
+
a.href = '#';
|
104
|
+
a.token = answer.data[1].token;
|
105
|
+
a.onclick = function() {
|
106
|
+
widget.refreshDir(this.token);
|
107
|
+
return false;
|
108
|
+
}.bind(a);
|
109
|
+
|
110
|
+
var img = widget.createElement('img');
|
111
|
+
img.src = widget.remoteUrl + 'resource/parent.gif';
|
112
|
+
a.appendChild(img);
|
113
|
+
|
114
|
+
li.appendChild(a);
|
115
|
+
li.appendText(answer.data[0].path);
|
116
|
+
widget.files.appendChild(li);
|
117
|
+
|
118
|
+
for (var i = 2; i < answer.data.length; i++) {
|
119
|
+
widget.files.appendChild(widget.printLink(answer.data[i]))
|
120
|
+
}
|
121
|
+
break;
|
122
|
+
|
123
|
+
default:
|
124
|
+
alert('Answer type :' + answer.type + ' not supported');
|
125
|
+
break;
|
126
|
+
}
|
127
|
+
}
|
128
|
+
|
129
|
+
widget.printLink = function(file) {
|
130
|
+
var li = widget.createElement('li');
|
131
|
+
var a = widget.createElement('a');
|
132
|
+
var action = null;
|
133
|
+
var img = null;
|
134
|
+
|
135
|
+
// del action
|
136
|
+
action = widget.createElement('a');
|
137
|
+
action.href = '#';
|
138
|
+
action.className = 'action';
|
139
|
+
img = widget.createElement('img');
|
140
|
+
img.src = widget.remoteUrl + 'resources/del.png';
|
141
|
+
action.appendChild(img);
|
142
|
+
action.onclick = function() {
|
143
|
+
if (confirm('Are you sure you want to delete "' + this.firstChild.nodeValue + '" ? ')) {
|
144
|
+
widget.remoteText('delete?token=' + widget.token + '&target=' + this.token,
|
145
|
+
function() { widget.refreshDir(widget.current); });
|
146
|
+
}
|
147
|
+
return false;
|
148
|
+
}.bind(a);
|
149
|
+
li.appendChild(action);
|
150
|
+
|
151
|
+
// rename action
|
152
|
+
action = widget.createElement('a');
|
153
|
+
action.href = '#';
|
154
|
+
action.className = 'action';
|
155
|
+
img = widget.createElement('img');
|
156
|
+
img.src = widget.remoteUrl + 'resources/rename.png';
|
157
|
+
action.appendChild(img);
|
158
|
+
action.onclick = function() {
|
159
|
+
var li = this.parentNode;
|
160
|
+
var input = widget.createElement('input');
|
161
|
+
input.type = 'text';
|
162
|
+
input.token = this.token;
|
163
|
+
input.value = this.firstChild.nodeValue;
|
164
|
+
Event.observe(input, 'keyup', function(ev) {
|
165
|
+
if (ev.keyCode == 27) { // Esc
|
166
|
+
widget.refreshDir(widget.current);
|
167
|
+
} else if (ev.keyCode == 13) { // Return
|
168
|
+
this.blur();
|
169
|
+
}
|
170
|
+
}.bind(input));
|
171
|
+
input.onblur = function() {
|
172
|
+
widget.remoteText('rename?token=' + widget.token +
|
173
|
+
'&target=' + this.token +
|
174
|
+
'&new=' + encodeURIComponent(this.value),
|
175
|
+
function() { widget.refreshDir(widget.current); });
|
176
|
+
}.bind(input);
|
177
|
+
li.setContent(input);
|
178
|
+
input.focus();
|
179
|
+
}.bind(a);
|
180
|
+
li.appendChild(action);
|
181
|
+
|
182
|
+
// download action
|
183
|
+
a.token = file.token;
|
184
|
+
a.className = 'file';
|
185
|
+
if (file.type == 'dir') {
|
186
|
+
img = 'http://www.netvibes.com/img/icons/folder.gif';
|
187
|
+
a.href = '#';
|
188
|
+
a.onclick = function() {
|
189
|
+
widget.refreshDir(this.token);
|
190
|
+
return false;
|
191
|
+
}.bind(a);
|
192
|
+
} else {
|
193
|
+
img = 'http://www.netvibes.com/img/icons/page_white.gif';
|
194
|
+
a.href = widget.remoteUrl + 'download?token=' + widget.token + '&target=' + file.token;
|
195
|
+
}
|
196
|
+
li.setStyle('backgroundImage', 'url(' + img +')');
|
197
|
+
a.appendText(file.name);
|
198
|
+
li.appendChild(a);
|
199
|
+
return li;
|
200
|
+
}
|
201
|
+
|
data/resources/sha1.js
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
function sha1(msg)
|
2
|
+
{
|
3
|
+
//
|
4
|
+
// function 'f' [4.1.1]
|
5
|
+
//
|
6
|
+
function f(s, x, y, z)
|
7
|
+
{
|
8
|
+
switch (s) {
|
9
|
+
case 0: return (x & y) ^ (~x & z);
|
10
|
+
case 1: return x ^ y ^ z;
|
11
|
+
case 2: return (x & y) ^ (x & z) ^ (y & z);
|
12
|
+
case 3: return x ^ y ^ z;
|
13
|
+
}
|
14
|
+
}
|
15
|
+
|
16
|
+
//
|
17
|
+
// rotate left (circular left shift) value x by n positions [3.2.5]
|
18
|
+
//
|
19
|
+
function ROTL(x, n)
|
20
|
+
{
|
21
|
+
return (x<<n) | (x>>>(32-n));
|
22
|
+
}
|
23
|
+
|
24
|
+
// constants [4.2.1]
|
25
|
+
var K = [0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6];
|
26
|
+
|
27
|
+
// PREPROCESSING
|
28
|
+
|
29
|
+
msg += String.fromCharCode(0x80); // add trailing '1' bit to string [5.1.1]
|
30
|
+
|
31
|
+
// convert string msg into 512-bit/16-integer blocks arrays of ints [5.2.1]
|
32
|
+
var l = Math.ceil(msg.length/4) + 2; // long enough to contain msg plus 2-word length
|
33
|
+
var N = Math.ceil(l/16); // in N 16-int blocks
|
34
|
+
var M = new Array(N);
|
35
|
+
for (var i=0; i<N; i++) {
|
36
|
+
M[i] = new Array(16);
|
37
|
+
for (var j=0; j<16; j++) { // encode 4 chars per integer, big-endian encoding
|
38
|
+
M[i][j] = (msg.charCodeAt(i*64+j*4)<<24) | (msg.charCodeAt(i*64+j*4+1)<<16) |
|
39
|
+
(msg.charCodeAt(i*64+j*4+2)<<8) | (msg.charCodeAt(i*64+j*4+3));
|
40
|
+
}
|
41
|
+
}
|
42
|
+
// add length (in bits) into final pair of 32-bit integers (big-endian) [5.1.1]
|
43
|
+
// note: most significant word would be ((len-1)*8 >>> 32, but since JS converts
|
44
|
+
// bitwise-op args to 32 bits, we need to simulate this by arithmetic operators
|
45
|
+
M[N-1][14] = ((msg.length-1)*8) / Math.pow(2, 32); M[N-1][14] = Math.floor(M[N-1][14])
|
46
|
+
M[N-1][15] = ((msg.length-1)*8) & 0xffffffff;
|
47
|
+
|
48
|
+
// set initial hash value [5.3.1]
|
49
|
+
var H0 = 0x67452301;
|
50
|
+
var H1 = 0xefcdab89;
|
51
|
+
var H2 = 0x98badcfe;
|
52
|
+
var H3 = 0x10325476;
|
53
|
+
var H4 = 0xc3d2e1f0;
|
54
|
+
|
55
|
+
// HASH COMPUTATION [6.1.2]
|
56
|
+
|
57
|
+
var W = new Array(80); var a, b, c, d, e;
|
58
|
+
for (var i=0; i<N; i++) {
|
59
|
+
|
60
|
+
// 1 - prepare message schedule 'W'
|
61
|
+
for (var t=0; t<16; t++) W[t] = M[i][t];
|
62
|
+
for (var t=16; t<80; t++) W[t] = ROTL(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16], 1);
|
63
|
+
|
64
|
+
// 2 - initialise five working variables a, b, c, d, e with previous hash value
|
65
|
+
a = H0; b = H1; c = H2; d = H3; e = H4;
|
66
|
+
|
67
|
+
// 3 - main loop
|
68
|
+
for (var t=0; t<80; t++) {
|
69
|
+
var s = Math.floor(t/20); // seq for blocks of 'f' functions and 'K' constants
|
70
|
+
var T = (ROTL(a,5) + f(s,b,c,d) + e + K[s] + W[t]) & 0xffffffff;
|
71
|
+
e = d;
|
72
|
+
d = c;
|
73
|
+
c = ROTL(b, 30);
|
74
|
+
b = a;
|
75
|
+
a = T;
|
76
|
+
}
|
77
|
+
|
78
|
+
// 4 - compute the new intermediate hash value
|
79
|
+
H0 = (H0+a) & 0xffffffff; // note 'addition modulo 2^32'
|
80
|
+
H1 = (H1+b) & 0xffffffff;
|
81
|
+
H2 = (H2+c) & 0xffffffff;
|
82
|
+
H3 = (H3+d) & 0xffffffff;
|
83
|
+
H4 = (H4+e) & 0xffffffff;
|
84
|
+
}
|
85
|
+
|
86
|
+
return H0.toHexStr() + H1.toHexStr() + H2.toHexStr() + H3.toHexStr() + H4.toHexStr();
|
87
|
+
}
|
88
|
+
|
89
|
+
//
|
90
|
+
// extend Number class with a tailored hex-string method
|
91
|
+
// (note toString(16) is implementation-dependant, and
|
92
|
+
// in IE returns signed numbers when used on full words)
|
93
|
+
//
|
94
|
+
Number.prototype.toHexStr = function()
|
95
|
+
{
|
96
|
+
var s="", v;
|
97
|
+
for (var i=7; i>=0; i--) { v = (this>>>(i*4)) & 0xf; s += v.toString(16); }
|
98
|
+
return s;
|
99
|
+
}
|
data/resources/style.css
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
.uwa_files_list {
|
2
|
+
display: block;
|
3
|
+
margin: 2px;
|
4
|
+
padding: 2px;
|
5
|
+
}
|
6
|
+
|
7
|
+
.uwa_files_list LI {
|
8
|
+
margin: 2px;
|
9
|
+
padding-left: 20px;
|
10
|
+
background-repeat: no-repeat;
|
11
|
+
background-position: left center;
|
12
|
+
line-height: 16px;
|
13
|
+
height: 16px;
|
14
|
+
clear: both;
|
15
|
+
}
|
16
|
+
|
17
|
+
.uwa_files_list LI INPUT {
|
18
|
+
width: 80%;
|
19
|
+
border: 1px inset #999;
|
20
|
+
}
|
21
|
+
|
22
|
+
/* This prevent word wrapping */
|
23
|
+
.uwa_files_list LI A.file {
|
24
|
+
display: block;
|
25
|
+
float: left;
|
26
|
+
overflow: hidden;
|
27
|
+
white-space: nowrap;
|
28
|
+
margin: 0px;
|
29
|
+
padding: 0px;
|
30
|
+
line-height: 16px;
|
31
|
+
}
|
32
|
+
|
33
|
+
.uwa_files_list IMG {
|
34
|
+
vertical-align: bottom;
|
35
|
+
margin-right: 4px;
|
36
|
+
}
|
37
|
+
|
38
|
+
.uwa_files_list LI A.action {
|
39
|
+
display: block;
|
40
|
+
float: right;
|
41
|
+
}
|
42
|
+
|
43
|
+
.uwa_files_list A.action IMG {
|
44
|
+
margin: 0px 2px;
|
45
|
+
padding: 0px;
|
46
|
+
}
|
47
|
+
|
48
|
+
.uwa_files_list A {
|
49
|
+
border: none;
|
50
|
+
}
|
51
|
+
|
52
|
+
.uwa_files_footer {
|
53
|
+
clear: both;
|
54
|
+
background-color: #eee;
|
55
|
+
padding: 4px;
|
56
|
+
}
|
57
|
+
|
58
|
+
.uwa_files_list .parent {
|
59
|
+
display: block;
|
60
|
+
list-style-type: none;
|
61
|
+
background: none;
|
62
|
+
background-color: #eee;
|
63
|
+
line-height: 16px;
|
64
|
+
padding: 2px;
|
65
|
+
}
|
66
|
+
.uwa_files_list .parent A {
|
67
|
+
float: right;
|
68
|
+
display: block;
|
69
|
+
margin: 0px;
|
70
|
+
padding: 0px;
|
71
|
+
}
|
72
|
+
|
73
|
+
.uwa_files_message {
|
74
|
+
font-style: italic;
|
75
|
+
padding: 4px;
|
76
|
+
}
|
77
|
+
|
78
|
+
.uwa_files_footer IMG {
|
79
|
+
display: block;
|
80
|
+
float: right;
|
81
|
+
margin: 3px;
|
82
|
+
}
|
data/resources/upload.js
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
/*
|
2
|
+
* Inpired by http://www.webtoolkit.info/ajax-file-upload.html
|
3
|
+
*/
|
4
|
+
|
5
|
+
Uploader = {}
|
6
|
+
|
7
|
+
Uploader.submit = function(form, options) {
|
8
|
+
var iframe = widget.createElement('iframe');
|
9
|
+
iframe.setStyle('display', 'none');
|
10
|
+
iframe.src = 'about:blank';
|
11
|
+
iframe.id = 'uploader' + Math.floor(Math.random() * 100000);
|
12
|
+
iframe.name = iframe.id;
|
13
|
+
iframe.onload = function() {
|
14
|
+
Uploader.loaded(this);
|
15
|
+
}.bind(iframe);
|
16
|
+
form.appendChild(iframe);
|
17
|
+
if (options && typeof(options.onComplete) == 'function') {
|
18
|
+
iframe.onComplete = options.onComplete;
|
19
|
+
}
|
20
|
+
form.target = iframe.name;
|
21
|
+
|
22
|
+
if (options && typeof(options.onStart) == 'function') {
|
23
|
+
return options.onStart();
|
24
|
+
} else {
|
25
|
+
return true;
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
Uploader.loaded = function(iframe) {
|
30
|
+
if (iframe.contentDocument) {
|
31
|
+
var doc = iframe.contentDocument;
|
32
|
+
} else if (iframe.contentWindow) {
|
33
|
+
var doc = iframe.contentWindow.document;
|
34
|
+
}
|
35
|
+
|
36
|
+
if (doc.location.href == "about:blank") {
|
37
|
+
return;
|
38
|
+
}
|
39
|
+
|
40
|
+
if (typeof(iframe.onComplete) == 'function') {
|
41
|
+
iframe.onComplete(doc.body.innerHTML);
|
42
|
+
}
|
43
|
+
|
44
|
+
// iframe.parentNode.removeChild(iframe);
|
45
|
+
// delete iframe;
|
46
|
+
}
|
metadata
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.2
|
3
|
+
specification_version: 1
|
4
|
+
name: uwa_files
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: "0.1"
|
7
|
+
date: 2007-04-12 00:00:00 +02:00
|
8
|
+
summary: UWA Files widget
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: florent@solt.biz
|
12
|
+
homepage: http://gnetvibes.rubyforge.org
|
13
|
+
rubyforge_project:
|
14
|
+
description:
|
15
|
+
autorequire:
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: false
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Florent Solt
|
31
|
+
files:
|
32
|
+
- lib/uwa_files/widget.rb
|
33
|
+
- lib/uwa_files/config.rb
|
34
|
+
- resources/parent.gif
|
35
|
+
- resources/script.js
|
36
|
+
- resources/sha1.js
|
37
|
+
- resources/style.css
|
38
|
+
- resources/upload.js
|
39
|
+
- resources/ajax.gif
|
40
|
+
- resources/del.png
|
41
|
+
- resources/rename.png
|
42
|
+
test_files: []
|
43
|
+
|
44
|
+
rdoc_options: []
|
45
|
+
|
46
|
+
extra_rdoc_files: []
|
47
|
+
|
48
|
+
executables: []
|
49
|
+
|
50
|
+
extensions: []
|
51
|
+
|
52
|
+
requirements: []
|
53
|
+
|
54
|
+
dependencies:
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: uwa
|
57
|
+
version_requirement:
|
58
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 0.0.0
|
63
|
+
version:
|