InPanel 1.2.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (198) hide show
  1. inpanel/__init__.py +29 -0
  2. inpanel/acme.py +289 -0
  3. inpanel/aliyuncs.py +269 -0
  4. inpanel/app.py +514 -0
  5. inpanel/apt.py +223 -0
  6. inpanel/base.py +200 -0
  7. inpanel/config.py +139 -0
  8. inpanel/data/config.ini +29 -0
  9. inpanel/data/history +5 -0
  10. inpanel/data/runlogs.ini +12 -0
  11. inpanel/data/update_info.ini +4 -0
  12. inpanel/dnf.py +225 -0
  13. inpanel/lib/__init__.py +9 -0
  14. inpanel/lib/async_process.py +98 -0
  15. inpanel/lib/filelock.py +82 -0
  16. inpanel/lib/magic.py +233 -0
  17. inpanel/lib/pxssh.py +310 -0
  18. inpanel/lib/pyDes.py +867 -0
  19. inpanel/mod/__init__.py +0 -0
  20. inpanel/mod/apt.py +316 -0
  21. inpanel/mod/certificate.py +268 -0
  22. inpanel/mod/config.py +372 -0
  23. inpanel/mod/cron.py +315 -0
  24. inpanel/mod/disk.py +322 -0
  25. inpanel/mod/dnf.py +239 -0
  26. inpanel/mod/file.py +722 -0
  27. inpanel/mod/firewall.py +199 -0
  28. inpanel/mod/firewall_base.py +137 -0
  29. inpanel/mod/firewall_firewalld.py +170 -0
  30. inpanel/mod/firewall_iptables.py +176 -0
  31. inpanel/mod/firewall_macos.py +213 -0
  32. inpanel/mod/firewall_ufw.py +128 -0
  33. inpanel/mod/ftp.py +231 -0
  34. inpanel/mod/httpd.py +1205 -0
  35. inpanel/mod/lighttpd.py +26 -0
  36. inpanel/mod/login.py +98 -0
  37. inpanel/mod/mysql.py +577 -0
  38. inpanel/mod/named.py +26 -0
  39. inpanel/mod/nginx.py +2327 -0
  40. inpanel/mod/package.py +33 -0
  41. inpanel/mod/package_apt.py +62 -0
  42. inpanel/mod/package_base.py +77 -0
  43. inpanel/mod/package_dnf.py +62 -0
  44. inpanel/mod/package_map.py +366 -0
  45. inpanel/mod/package_yum.py +64 -0
  46. inpanel/mod/php.py +289 -0
  47. inpanel/mod/process.py +291 -0
  48. inpanel/mod/proftpd.py +26 -0
  49. inpanel/mod/pureftpd.py +26 -0
  50. inpanel/mod/query.py +108 -0
  51. inpanel/mod/server.py +1319 -0
  52. inpanel/mod/service.py +262 -0
  53. inpanel/mod/setting.py +228 -0
  54. inpanel/mod/shell.py +78 -0
  55. inpanel/mod/ssh.py +280 -0
  56. inpanel/mod/system.py +220 -0
  57. inpanel/mod/task.py +1337 -0
  58. inpanel/mod/ufw.py +14 -0
  59. inpanel/mod/user.py +306 -0
  60. inpanel/mod/vsftpd.py +67 -0
  61. inpanel/mod/yum.py +243 -0
  62. inpanel/plugins/__init__.py +10 -0
  63. inpanel/plugins/__pycache__/__init__.cpython-313.pyc +0 -0
  64. inpanel/plugins/acme/static/index.html +10 -0
  65. inpanel/plugins/acme/static/index.js +13 -0
  66. inpanel/plugins/shadowsocks-libev/__pycache__/info.cpython-313.pyc +0 -0
  67. inpanel/plugins/shadowsocks-libev/info.py +73 -0
  68. inpanel/plugins/shadowsocks-libev/static/index.html +70 -0
  69. inpanel/plugins/shadowsocks-libev/static/index.js +18 -0
  70. inpanel/public/css/global.css +138 -0
  71. inpanel/public/favicon.ico +0 -0
  72. inpanel/public/images/alipay.jpg +0 -0
  73. inpanel/public/images/loading.gif +0 -0
  74. inpanel/public/images/weixin.jpg +0 -0
  75. inpanel/public/index.html +94 -0
  76. inpanel/public/js/controllers/controllers.js +566 -0
  77. inpanel/public/js/controllers/database.js +590 -0
  78. inpanel/public/js/controllers/ecs.js +624 -0
  79. inpanel/public/js/controllers/file.js +940 -0
  80. inpanel/public/js/controllers/plugins.js +105 -0
  81. inpanel/public/js/controllers/service.js +1460 -0
  82. inpanel/public/js/controllers/site.js +1241 -0
  83. inpanel/public/js/controllers/utils.js +2319 -0
  84. inpanel/public/js/core.js +221 -0
  85. inpanel/public/js/directives.js +784 -0
  86. inpanel/public/js/filters.js +395 -0
  87. inpanel/public/js/services.js +257 -0
  88. inpanel/public/lib/angular/1.0.2/angular-resource.min.js +10 -0
  89. inpanel/public/lib/angular/1.0.2/angular.min.js +158 -0
  90. inpanel/public/lib/bootstrap/css/bootstrap-theme.css +587 -0
  91. inpanel/public/lib/bootstrap/css/bootstrap-theme.css.map +1 -0
  92. inpanel/public/lib/bootstrap/css/bootstrap-theme.min.css +6 -0
  93. inpanel/public/lib/bootstrap/css/bootstrap-theme.min.css.map +1 -0
  94. inpanel/public/lib/bootstrap/css/bootstrap.css +6757 -0
  95. inpanel/public/lib/bootstrap/css/bootstrap.css.map +1 -0
  96. inpanel/public/lib/bootstrap/css/bootstrap.min.css +6 -0
  97. inpanel/public/lib/bootstrap/css/bootstrap.min.css.map +1 -0
  98. inpanel/public/lib/bootstrap/fonts/glyphicons-halflings-regular.eot +0 -0
  99. inpanel/public/lib/bootstrap/fonts/glyphicons-halflings-regular.svg +288 -0
  100. inpanel/public/lib/bootstrap/fonts/glyphicons-halflings-regular.ttf +0 -0
  101. inpanel/public/lib/bootstrap/fonts/glyphicons-halflings-regular.woff +0 -0
  102. inpanel/public/lib/bootstrap/fonts/glyphicons-halflings-regular.woff2 +0 -0
  103. inpanel/public/lib/bootstrap/img/glyphicons-halflings-white.png +0 -0
  104. inpanel/public/lib/bootstrap/img/glyphicons-halflings.png +0 -0
  105. inpanel/public/lib/bootstrap/js/bootstrap.js +2377 -0
  106. inpanel/public/lib/bootstrap/js/bootstrap.min.js +7 -0
  107. inpanel/public/lib/bootstrap/js/npm.js +13 -0
  108. inpanel/public/lib/codemirror/codemirror-compressed.js +1 -0
  109. inpanel/public/lib/codemirror/codemirror.css +173 -0
  110. inpanel/public/lib/jquery/jquery-1.12.4.min.js +5 -0
  111. inpanel/public/lib/md5/md5.js +379 -0
  112. inpanel/public/lib/md5/md5.min.js +1 -0
  113. inpanel/public/partials/database/index.html +172 -0
  114. inpanel/public/partials/database/mysql/dbedit.html +462 -0
  115. inpanel/public/partials/database/mysql/dbnew.html +348 -0
  116. inpanel/public/partials/database/mysql/useredit.html +310 -0
  117. inpanel/public/partials/database/mysql/usernew.html +97 -0
  118. inpanel/public/partials/directives/message.html +20 -0
  119. inpanel/public/partials/directives/navbar.html +25 -0
  120. inpanel/public/partials/directives/selector.html +57 -0
  121. inpanel/public/partials/directives/srvbase.html +72 -0
  122. inpanel/public/partials/directives/srvext.html +34 -0
  123. inpanel/public/partials/directives/srvfile.html +23 -0
  124. inpanel/public/partials/directives/srvinstall.html +34 -0
  125. inpanel/public/partials/directives/srvlog.html +23 -0
  126. inpanel/public/partials/directives/srvminiop.html +28 -0
  127. inpanel/public/partials/directives/srvuninstall.html +38 -0
  128. inpanel/public/partials/directives/srvupdate.html +30 -0
  129. inpanel/public/partials/ecs/account.html +156 -0
  130. inpanel/public/partials/ecs/ecs.html +198 -0
  131. inpanel/public/partials/ecs/index.html +40 -0
  132. inpanel/public/partials/ecs/setings.html +459 -0
  133. inpanel/public/partials/file/file.html +501 -0
  134. inpanel/public/partials/file/trash.html +95 -0
  135. inpanel/public/partials/ftp.html +36 -0
  136. inpanel/public/partials/log.html +83 -0
  137. inpanel/public/partials/login.html +79 -0
  138. inpanel/public/partials/logout.html +22 -0
  139. inpanel/public/partials/main.html +534 -0
  140. inpanel/public/partials/plugins/index.html +55 -0
  141. inpanel/public/partials/plugins/plugins.html +13 -0
  142. inpanel/public/partials/secure.html +13 -0
  143. inpanel/public/partials/service/apache.html +147 -0
  144. inpanel/public/partials/service/cron.html +71 -0
  145. inpanel/public/partials/service/index.html +293 -0
  146. inpanel/public/partials/service/iptables.html +40 -0
  147. inpanel/public/partials/service/lighttpd.html +63 -0
  148. inpanel/public/partials/service/mariadb.html +113 -0
  149. inpanel/public/partials/service/memcache.html +36 -0
  150. inpanel/public/partials/service/minio.html +44 -0
  151. inpanel/public/partials/service/mongodb.html +44 -0
  152. inpanel/public/partials/service/mysql.html +113 -0
  153. inpanel/public/partials/service/named.html +61 -0
  154. inpanel/public/partials/service/nginx.html +296 -0
  155. inpanel/public/partials/service/ntp.html +40 -0
  156. inpanel/public/partials/service/php.html +250 -0
  157. inpanel/public/partials/service/proftpd.html +59 -0
  158. inpanel/public/partials/service/pureftpd.html +59 -0
  159. inpanel/public/partials/service/redis.html +40 -0
  160. inpanel/public/partials/service/samba.html +58 -0
  161. inpanel/public/partials/service/sendmail.html +40 -0
  162. inpanel/public/partials/service/ssh.html +186 -0
  163. inpanel/public/partials/service/tomcat.html +65 -0
  164. inpanel/public/partials/service/vsftpd.html +195 -0
  165. inpanel/public/partials/setting.html +299 -0
  166. inpanel/public/partials/site/apache/site.html +277 -0
  167. inpanel/public/partials/site/index.html +344 -0
  168. inpanel/public/partials/site/nginx/site.html +558 -0
  169. inpanel/public/partials/sorry.html +19 -0
  170. inpanel/public/partials/storage/autofm.html +103 -0
  171. inpanel/public/partials/storage/backup.html +42 -0
  172. inpanel/public/partials/storage/index.html +360 -0
  173. inpanel/public/partials/storage/migrate.html +93 -0
  174. inpanel/public/partials/storage/movedata.html +98 -0
  175. inpanel/public/partials/storage/remote.html +77 -0
  176. inpanel/public/partials/utils/cron.html +486 -0
  177. inpanel/public/partials/utils/firewall.html +266 -0
  178. inpanel/public/partials/utils/index.html +193 -0
  179. inpanel/public/partials/utils/network.html +118 -0
  180. inpanel/public/partials/utils/process.html +239 -0
  181. inpanel/public/partials/utils/repository.html +373 -0
  182. inpanel/public/partials/utils/shell.html +28 -0
  183. inpanel/public/partials/utils/ssl.html +319 -0
  184. inpanel/public/partials/utils/time.html +109 -0
  185. inpanel/public/partials/utils/user.html +359 -0
  186. inpanel/public/robots.txt +2 -0
  187. inpanel/remote.py +109 -0
  188. inpanel/templates/file/preview.html +34 -0
  189. inpanel/templates/index.html +93 -0
  190. inpanel/utils.py +282 -0
  191. inpanel/web.py +1811 -0
  192. inpanel/yum.py +756 -0
  193. inpanel-1.2.1.dist-info/METADATA +399 -0
  194. inpanel-1.2.1.dist-info/RECORD +198 -0
  195. inpanel-1.2.1.dist-info/WHEEL +5 -0
  196. inpanel-1.2.1.dist-info/entry_points.txt +2 -0
  197. inpanel-1.2.1.dist-info/licenses/LICENSE +30 -0
  198. inpanel-1.2.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,940 @@
1
+ var FileCtrl = [
2
+ '$scope', '$routeParams', 'Module', 'Message', 'Request', 'Backend',
3
+ function($scope, $routeParams, Module, Message, Request, Backend) {
4
+ var module = 'file';
5
+ Module.init(module, '文件管理');
6
+
7
+ var route_path = $routeParams.path;
8
+ var route_file = $routeParams.file;
9
+ var remember_path = true;
10
+ var remember_file = true;
11
+
12
+ $scope.path = $scope.lastpath = '/root';
13
+ $scope.curpath = '';
14
+ $scope.showhidden = false;
15
+ $scope.clipboard = {
16
+ 'srcpath': '',
17
+ 'count': 0,
18
+ 'items': {} // name: copy|cut|link
19
+ };
20
+ $scope.confirm = $scope.cancel = function() {};
21
+ $scope.path_history = [];
22
+
23
+ var parse_path = function() {
24
+ // parse dir to array
25
+ var pathnames = $scope.curpath.split('/');
26
+ var pathinfos = [];
27
+ for (var i = 1; i < pathnames.length; i++) {
28
+ if (!pathnames[i]) continue;
29
+ var fullpath = pathnames[i - 1] + '/' + pathnames[i];
30
+ pathinfos.push({
31
+ 'name': pathnames[i],
32
+ 'path': fullpath
33
+ });
34
+ pathnames[i] = fullpath;
35
+ }
36
+ $scope.pathinfos = pathinfos;
37
+ };
38
+
39
+ var set_history_path = function(p) {
40
+ Request.post('/api/operation/file', {
41
+ 'action': 'add_history',
42
+ 'path': p
43
+ }, function(data) {
44
+ if (data.code == 0) {
45
+ $scope.path_history = data.data;
46
+ }
47
+ }, false, true);
48
+ };
49
+ var get_history_path = function() {
50
+ Request.post('/api/operation/file', {
51
+ 'action': 'history'
52
+ }, function(data) {
53
+ if (data.code == 0) {
54
+ $scope.path_history = data.data;
55
+ }
56
+ }, false, true);
57
+ };
58
+
59
+ $scope.loaded = false;
60
+ $scope.load = function() {
61
+ get_history_path();
62
+ if (route_path || route_file) { // load the specified path and file
63
+ $scope.loaded = true;
64
+ remember_path = false;
65
+ remember_file = false;
66
+ if (route_file) {
67
+ route_path = route_file.split('/')
68
+ route_file = route_path.pop()
69
+ route_path = route_path.join('/');
70
+ if (!route_path) route_path = '/';
71
+ }
72
+ $scope.listdir(route_path, true, function() {
73
+ if (route_file) $scope.editfile(route_file);
74
+ });
75
+ } else { // load from history
76
+ Request.post('/api/operation/file', {
77
+ 'action': 'last'
78
+ }, function(data) {
79
+ if (data.code == 0) {
80
+ $scope.loaded = true;
81
+ var lastfile = data.data['lastfile'];
82
+ var lastdir = data.data['lastdir'];
83
+ $scope.listdir(lastdir, true, function() {
84
+ if (lastfile && lastfile.indexOf(lastdir) === 0) {
85
+ lastfile = lastfile.replace(lastdir + '/', '')
86
+ if (lastfile.indexOf('/') == -1) $scope.editfile(lastfile);
87
+ }
88
+ });
89
+ }
90
+ }, false, true);
91
+ }
92
+ };
93
+
94
+ $scope.fileloading = false;
95
+ $scope.listdir = function(path, clearselect, callback) {
96
+ if (path) $scope.path = path;
97
+ if ($scope.path == '') {
98
+ $scope.path = '/root';
99
+ } else if ($scope.path != '/' && $scope.path.substr(-1) == '/') {
100
+ $scope.path = $scope.path.substr(0, $scope.path.length - 1);
101
+ }
102
+ $scope.path = $scope.path.replace('//', '/');
103
+
104
+ var curpath = $scope.path;
105
+ $scope.fileloading = true;
106
+ Request.post('/api/operation/file', {
107
+ 'action': 'listdir',
108
+ 'path': curpath,
109
+ 'showhidden': $scope.showhidden,
110
+ 'remember': remember_path
111
+ }, function(data) {
112
+ if (data.code == 0) {
113
+ $scope.items = data.data;
114
+ for (var i = 0; i < $scope.items.length; i++) {
115
+ var path = curpath.split('/')[0] == '' ? curpath.substr(1) : curpath;
116
+ $scope.items[i]['uri'] = encodeURIComponent(path + '/' + $scope.items[i].name);
117
+ }
118
+ $scope.curpath = curpath;
119
+ $scope.lastpath = curpath;
120
+ set_history_path(curpath);
121
+ if (clearselect) {
122
+ $scope.selects = {};
123
+ $scope.selectall = false;
124
+ }
125
+ } else {
126
+ $scope.path = $scope.lastpath;
127
+ }
128
+ $scope.fileloading = false;
129
+ parse_path();
130
+ if (callback) callback.call();
131
+ }, false, true);
132
+ };
133
+ $scope.getitem = function(name, oldname) {
134
+ if (!oldname)
135
+ oldname = name;
136
+ else
137
+ delete $scope.selects[oldname];
138
+ Request.post('/api/operation/file', {
139
+ 'action': 'getitem',
140
+ 'path': $scope.curpath + '/' + name
141
+ }, function(data) {
142
+ if (data.code == 0) {
143
+ var iteminfo = data.data;
144
+ // update to item list
145
+ var found = false;
146
+ for (var i = 0; i < $scope.items.length; i++) {
147
+ if ($scope.items[i].name == oldname) {
148
+ $scope.items[i] = iteminfo;
149
+ found = true;
150
+ break;
151
+ }
152
+ }
153
+ // insert new item to proper position
154
+ if (!found) {
155
+ var inserted = false;
156
+ var i = 0;
157
+ if (iteminfo.isdir || iteminfo.islnk && iteminfo.link_isdir) {
158
+ for (; i < $scope.items.length; i++) {
159
+ var item = $scope.items[i];
160
+ if (item.isdir || item.islnk && item.link_isdir) {
161
+ if ($scope.items[i].name.localeCompare(iteminfo.name) > 1) {
162
+ $scope.items.splice(i, 0, iteminfo);
163
+ inserted = true;
164
+ break;
165
+ }
166
+ } else {
167
+ break;
168
+ }
169
+ }
170
+ } else {
171
+ for (; i < $scope.items.length; i++) {
172
+ var item = $scope.items[i];
173
+ if (item.isdir || item.islnk && item.link_isdir) continue;
174
+ if ($scope.items[i].name.localeCompare(iteminfo.name) > 1) {
175
+ $scope.items.splice(i, 0, iteminfo);
176
+ inserted = true;
177
+ break;
178
+ }
179
+ }
180
+ }
181
+ if (!inserted) $scope.items.splice(i, 0, iteminfo); // insert at the end of list
182
+ }
183
+ } else { // item not found
184
+ // delete to item list
185
+ for (var i = 0; i < $scope.items.length; i++) {
186
+ if ($scope.items[i].name == name) {
187
+ $scope.items.splice(i, 1);
188
+ break;
189
+ }
190
+ }
191
+ }
192
+ }, false, true);
193
+ };
194
+ $scope.upandlist = function() {
195
+ var patharr = $scope.curpath.split('/');
196
+ patharr.pop();
197
+ $scope.listdir(patharr.join('/') + '/', true);
198
+ };
199
+ $scope.editfile = function(path) {
200
+ Request.post('/api/operation/file', {
201
+ 'action': 'fread',
202
+ 'path': $scope.curpath + '/' + path,
203
+ 'remember': remember_file
204
+ }, function(data) {
205
+ if (data.code == 0) {
206
+ Message.setSuccess('');
207
+ var filedata = data.data;
208
+ $scope.filename = filedata.filename;
209
+ $scope.filepath = filedata.filepath;
210
+ $scope.filecharset = filedata.charset;
211
+ $scope.filecharset_org = filedata.charset;
212
+ editor.setValue('');
213
+ $('#list').hide();
214
+ $('#edit').show();
215
+ editor.setOption('mode', filedata.mimetype);
216
+ editor.setValue(filedata.content);
217
+ hasChange = false;
218
+ }
219
+ });
220
+ };
221
+ $scope.return2list = $scope.canceledit = function() {
222
+ if (hasChange) {
223
+ $scope.confirm_title = '是否放弃修改?';
224
+ $scope.confirm_body = $scope.filepath + ' 已被修改,是否放弃修改?';
225
+ $('#confirm').modal();
226
+ $scope.cancel = function() {};
227
+ $scope.confirm = function() {
228
+ $('#edit').hide();
229
+ $('#list').show();
230
+ Request.post('/api/operation/file', { 'action': 'fclose' }, false, false, true);
231
+ };
232
+ } else {
233
+ $('#edit').hide();
234
+ $('#list').show();
235
+ Request.post('/api/operation/file', { 'action': 'fclose' }, false, false, true);
236
+ }
237
+ };
238
+ $scope.savefile = function() {
239
+ if (!hasChange && $scope.filecharset == $scope.filecharset_org) {
240
+ Message.setInfo('文件未修改,无须保存!');
241
+ return;
242
+ }
243
+ Request.post('/api/operation/file', {
244
+ 'action': 'fwrite',
245
+ 'path': $scope.filepath,
246
+ 'charset': $scope.filecharset,
247
+ 'content': editor.getValue()
248
+ }, function(data) {
249
+ if (data.code == 0) {
250
+ hasChange = false;
251
+ $scope.getitem($scope.filename);
252
+ }
253
+ });
254
+ };
255
+ $scope.newfolder = function() {
256
+ $scope.newname_title = '新建文件夹';
257
+ $scope.newname_label = '文件夹名称';
258
+ $scope.newname_name = '';
259
+ $('#newname').modal();
260
+ $scope.newname = function() {
261
+ Request.post('/api/operation/file', {
262
+ 'action': 'createfolder',
263
+ 'path': $scope.curpath,
264
+ 'name': $scope.newname_name
265
+ }, function(data) {
266
+ if (data.code == 0) {
267
+ $scope.getitem($scope.newname_name);
268
+ }
269
+ });
270
+ };
271
+ };
272
+ $scope.newfile = function() {
273
+ $scope.newname_title = '新建文件';
274
+ $scope.newname_label = '文件名称';
275
+ $scope.newname_name = '';
276
+ $('#newname').modal();
277
+ $scope.newname = function() {
278
+ Request.post('/api/operation/file', {
279
+ 'action': 'createfile',
280
+ 'path': $scope.curpath,
281
+ 'name': $scope.newname_name
282
+ }, function(data) {
283
+ if (data.code == 0) {
284
+ $scope.getitem($scope.newname_name);
285
+ }
286
+ });
287
+ };
288
+ };
289
+ $scope.upload = function() {
290
+ $('#upload').modal();
291
+ };
292
+ $scope.doupload = function() {
293
+ var pathinfo = $('#uploadform').find('input[name=ufile]').val().split(/[\\\/]/);
294
+ var name = pathinfo[pathinfo.length - 1];
295
+ if (!name) {
296
+ return;
297
+ }
298
+ Request.post('/api/operation/file', {
299
+ 'action': 'getitem',
300
+ 'path': $scope.curpath + '/' + name
301
+ }, function(data) {
302
+ if (data.code == 0) {
303
+ $scope.confirm_title = '上传文件覆盖确认';
304
+ $scope.confirm_body = '<p>系统检测到当前目录下已存在同名文件 ' + name + '。</p><p>确认要覆盖这个文件吗?</p>';
305
+ $('#confirm').modal();
306
+ $scope.confirm = function() {
307
+ $('#uploadform').submit();
308
+ };
309
+ } else {
310
+ $('#uploadform').submit();
311
+ }
312
+ }, false, true);
313
+ };
314
+ $scope.download = function() {
315
+ $('#download').modal();
316
+ $scope.dodownload = function() {
317
+ Backend.call(
318
+ $scope,
319
+ module,
320
+ '/api/backend/wget',
321
+ '/api/backend/wget_' + encodeURIComponent(encodeURIComponent($scope.downloadurl)), {
322
+ 'url': $scope.downloadurl,
323
+ 'path': $scope.curpath
324
+ }, {
325
+ 'success': function(data) {
326
+ $scope.listdir();
327
+ }
328
+ }
329
+ );
330
+ };
331
+ };
332
+ $scope.togglehidden = function() {
333
+ $scope.showhidden = !$scope.showhidden;
334
+ $scope.listdir();
335
+ };
336
+ $scope.rename = function(oldname) {
337
+ $scope.newname_title = '重命名';
338
+ $scope.newname_label = '新名称';
339
+ $scope.newname_name = oldname;
340
+ $('#newname').modal();
341
+ $scope.newname = function() {
342
+ Request.post('/api/operation/file', {
343
+ 'action': 'rename',
344
+ 'path': $scope.curpath + '/' + oldname,
345
+ 'name': $scope.newname_name
346
+ }, function(data) {
347
+ if (data.code == 0) {
348
+ $scope.getitem($scope.newname_name, oldname);
349
+ }
350
+ });
351
+ };
352
+ };
353
+ var bindclipfunc = function(type) {
354
+ return function(name, selected) {
355
+ var cb = $scope.clipboard;
356
+ if (cb.srcpath != $scope.curpath) {
357
+ cb.items = {};
358
+ cb.count = 0;
359
+ }
360
+ if (typeof selected == 'undefined') {
361
+ if (typeof cb.items[name] == 'undefined') {
362
+ cb.srcpath = $scope.curpath;
363
+ cb.items[name] = type;
364
+ cb.count++;
365
+ } else if (cb.items[name] == type) {
366
+ delete cb.items[name];
367
+ cb.count--;
368
+ } else if (typeof selected == 'undefined') {
369
+ cb.items[name] = type;
370
+ }
371
+ } else {
372
+ if (selected) {
373
+ if (typeof cb.items[name] == 'undefined') {
374
+ cb.srcpath = $scope.curpath;
375
+ cb.count++;
376
+ }
377
+ cb.items[name] = type;
378
+ } else {
379
+ if (typeof cb.items[name] != 'undefined') {
380
+ delete cb.items[name];
381
+ cb.count--;
382
+ }
383
+ }
384
+ }
385
+ };
386
+ }
387
+ $scope.togglecopy = bindclipfunc('copy');
388
+ $scope.togglecut = bindclipfunc('cut');
389
+ $scope.togglelink = bindclipfunc('link');
390
+ $scope.paste = function() {
391
+ pasteeach();
392
+ };
393
+ var pastedo = function(type, srcpath, despath, name) {
394
+ if (type == 'copy') {
395
+ Backend.call(
396
+ $scope,
397
+ module,
398
+ '/api/backend/copy',
399
+ '/api/backend/copy_' + srcpath + '_' + despath, {
400
+ 'srcpath': srcpath,
401
+ 'despath': despath
402
+ }, {
403
+ 'success': function(data) {
404
+ delete $scope.clipboard.items[name];
405
+ $scope.selects = {};
406
+ $scope.listdir();
407
+ pasteeach();
408
+ },
409
+ 'error': function(data) {
410
+ $scope.listdir();
411
+ }
412
+ }
413
+ );
414
+ } else if (type == 'cut') {
415
+ Backend.call(
416
+ $scope,
417
+ module,
418
+ '/api/backend/move',
419
+ '/api/backend/move_' + srcpath + '_' + despath, {
420
+ 'srcpath': srcpath,
421
+ 'despath': despath
422
+ }, {
423
+ 'success': function(data) {
424
+ delete $scope.clipboard.items[name];
425
+ $scope.selects = {};
426
+ $scope.listdir();
427
+ pasteeach();
428
+ },
429
+ 'error': function(data) {
430
+ $scope.listdir();
431
+ }
432
+ }
433
+ );
434
+ } else if (type == 'link') {
435
+ Request.post('/api/operation/file', {
436
+ 'action': 'link',
437
+ 'srcpath': srcpath,
438
+ 'despath': despath
439
+ }, function(data) {
440
+ if (data.code == 0) {
441
+ $scope.selects = {};
442
+ $scope.listdir();
443
+ delete $scope.clipboard.items[name];
444
+ pasteeach();
445
+ }
446
+ });
447
+ }
448
+ };
449
+ var pasteeach = function(newname) {
450
+ // check if some file/folder/link already exists
451
+ var name = '';
452
+ for (name in $scope.clipboard.items) break;
453
+ if (!name) return;
454
+ var type = $scope.clipboard.items[name];
455
+ Request.post('/api/operation/file', {
456
+ 'action': 'exist',
457
+ 'name': newname ? newname : name,
458
+ 'path': $scope.curpath
459
+ }, function(data) {
460
+ if (data.code == 0) {
461
+ var srcpath = $scope.clipboard.srcpath + '/' + name;
462
+ var despath = $scope.curpath + '/' + (newname ? newname : name);
463
+ if (data.data) {
464
+ $scope.overwrite_filename = (newname ? newname : name);
465
+ $scope.overwrite_option = 'rename';
466
+ $scope.overwrite_newname = (newname ? newname : name) + '.new';
467
+ $('#overwriteconfirm').modal();
468
+ $scope.overwrite = function() {
469
+ if ($scope.overwrite_option == 'rename') {
470
+ pasteeach($scope.overwrite_newname);
471
+ } else {
472
+ pastedo(type, srcpath, despath, name);
473
+ }
474
+ };
475
+ //$scope.cancel = function(){
476
+ // delete $scope.clipboard.items[name];
477
+ //};
478
+ //$scope.confirm = function(){
479
+ // pastedo(type, srcpath, despath, name);
480
+ //};
481
+ } else { // no despath exists
482
+ pastedo(type, srcpath, despath, name);
483
+ }
484
+ }
485
+ });
486
+ };
487
+ $scope.move2trash = function(name) {
488
+ Request.post('/api/operation/file', {
489
+ 'action': 'delete',
490
+ 'paths': $scope.curpath + '/' + name
491
+ }, function(data) {
492
+ if (data.code == 0) {
493
+ $scope.getitem(name);
494
+ // deal with .filename.bak
495
+ var bakname = '.' + name + '.bak';
496
+ for (var i = 0; i < $scope.items.length; i++) {
497
+ if ($scope.items[i].name == bakname) {
498
+ $scope.getitem(bakname);
499
+ break;
500
+ }
501
+ }
502
+ }
503
+ });
504
+ };
505
+ $scope.compressconfirm = function(name, isreg) {
506
+ $scope.compress_isreg = isreg;
507
+ $scope.compress_type = isreg ? '.gz' : '.tar.gz';
508
+ $scope.compress_zipname = name;
509
+ $scope.compress_name = name;
510
+ $scope.compress_names = [];
511
+ $('#compressconfirm').modal();
512
+ };
513
+ $scope.compress = function() {
514
+ var zippath = $scope.curpath + '/' + $scope.compress_zipname + $scope.compress_type;
515
+ var srcpath = $scope.curpath + '/' + $scope.compress_name;
516
+ Backend.call(
517
+ $scope,
518
+ module,
519
+ '/api/backend/compress',
520
+ '/api/backend/compress_' + zippath + '_' + srcpath, {
521
+ 'zippath': zippath,
522
+ 'paths': srcpath
523
+ }, {
524
+ 'success': function(data) {
525
+ var newname = $scope.compress_zipname + $scope.compress_type;
526
+ if ($scope.compress_type == '.gz')
527
+ $scope.getitem(newname, $scope.compress_name);
528
+ else
529
+ $scope.getitem(newname);
530
+ }
531
+ }
532
+ );
533
+ };
534
+ $scope.decompress = function(name) {
535
+ var ns = name.split('.');
536
+ var f1 = ns.pop();
537
+ var f2 = ns.pop();
538
+ if (f1 == 'gz' && f2 != 'tar') {
539
+ var zippath = $scope.curpath + '/' + name;
540
+ Backend.call(
541
+ $scope,
542
+ module,
543
+ '/api/backend/decompress',
544
+ '/api/backend/decompress_' + zippath + '_', {
545
+ 'zippath': zippath
546
+ }, {
547
+ 'success': function(data) {
548
+ $scope.getitem(name.substr(0, name.length - 3), name);
549
+ }
550
+ }
551
+ );
552
+ return;
553
+ }
554
+ $scope.selector_title = '请选择要解压到的目录';
555
+ $scope.selector.onlydir = true;
556
+ $scope.selector.onlyfile = false;
557
+ $scope.selector.load($scope.curpath);
558
+ $scope.selector.selecthandler = function(path) {
559
+ $('#selector').modal('hide');
560
+ // check if file exists in the path
561
+ Message.setInfo('正在检测目录...', true);
562
+ Request.post('/api/operation/file', {
563
+ 'action': 'listdir',
564
+ 'path': path,
565
+ 'showhidden': true,
566
+ 'remember': false
567
+ }, function(data) {
568
+ if (data.code == 0) {
569
+ Message.setInfo('');
570
+ var confirm = function() {
571
+ var zippath = $scope.curpath + '/' + name;
572
+ Backend.call(
573
+ $scope,
574
+ module,
575
+ '/api/backend/decompress',
576
+ '/api/backend/decompress_' + zippath + '_' + path, {
577
+ 'zippath': zippath,
578
+ 'despath': path
579
+ }, {
580
+ 'success': function(data) {
581
+ if ($scope.curpath == path) $scope.listdir();
582
+ }
583
+ }
584
+ );
585
+ }
586
+ if (data.data.length > 0) {
587
+ $scope.confirm_title = '解压确认';
588
+ $scope.confirm_body = '<p>系统检测到目录 ' + path + ' 下存在文件,继续解压将可能覆盖这些文件。</p><p>确认要继续解压吗?</p>';
589
+ $('#confirm').modal();
590
+ $scope.confirm = confirm;
591
+ } else {
592
+ confirm();
593
+ }
594
+ } else {
595
+ Message.setError('检测目录失败!');
596
+ }
597
+ }, false, true);
598
+ };
599
+ $('#selector').modal();
600
+ };
601
+
602
+ $scope.$watch('selectall', function(value) {
603
+ angular.forEach($scope.items, function(item) {
604
+ $scope.selects[item.name] = value;
605
+ });
606
+ });
607
+ $scope.multicopy = function() {
608
+ var itemfound = false;
609
+ angular.forEach($scope.selects, function(selected, item) {
610
+ $scope.togglecopy(item, selected);
611
+ if (selected) itemfound = true;
612
+ });
613
+ if (!itemfound) {
614
+ Message.setError('请先选择文件或目录!');
615
+ return;
616
+ }
617
+ };
618
+ $scope.multicut = function() {
619
+ var itemfound = false;
620
+ angular.forEach($scope.selects, function(selected, item) {
621
+ $scope.togglecut(item, selected);
622
+ if (selected) itemfound = true;
623
+ });
624
+ if (!itemfound) {
625
+ Message.setError('请先选择文件或目录!');
626
+ return;
627
+ }
628
+ };
629
+ $scope.multidel = function() {
630
+ var paths = [];
631
+ angular.forEach($scope.selects, function(selected, item) {
632
+ if (selected) paths.push($scope.curpath + '/' + item);
633
+ });
634
+ if (paths.length == 0) {
635
+ Message.setError('请先选择文件或目录!');
636
+ return;
637
+ }
638
+ Request.post('/api/operation/file', {
639
+ 'action': 'delete',
640
+ 'paths': paths.join(',')
641
+ }, function(data) {
642
+ if (data.code == 0) {
643
+ $scope.selects = {};
644
+ $scope.listdir();
645
+ }
646
+ });
647
+ };
648
+ $scope.tarconfirm = function() {
649
+ var names = [];
650
+ angular.forEach($scope.selects, function(selected, item) {
651
+ if (selected) names.push(item);
652
+ });
653
+ if (names.length == 0) {
654
+ Message.setError('请先选择文件或目录!');
655
+ return;
656
+ }
657
+ if (names.length == 1) {
658
+ $scope.compressconfirm(names[0], false);
659
+ return
660
+ }
661
+ $scope.compress_isreg = false;
662
+ $scope.compress_type = '.tar.gz';
663
+ $scope.compress_zipname = $scope.curpath.split('/').pop();
664
+ $scope.compress_name = '多个项目';
665
+ $scope.compress_names = names;
666
+ $('#compressconfirm').modal();
667
+ };
668
+ $scope.tar = function() {
669
+ var zippath = $scope.curpath + '/' + $scope.compress_zipname + $scope.compress_type;
670
+ var srcpaths = [];
671
+ for (var i = 0; i < $scope.compress_names.length; i++) {
672
+ srcpaths.push($scope.curpath + '/' + $scope.compress_names[i]);
673
+ }
674
+ if (srcpaths.length == 0) {
675
+ Message.setError('请先选择文件或目录!');
676
+ return;
677
+ }
678
+ Backend.call(
679
+ $scope,
680
+ module,
681
+ '/api/backend/compress',
682
+ '/api/backend/compress_' + zippath + '_' + srcpaths.join(','), {
683
+ 'zippath': zippath,
684
+ 'paths': srcpaths.join(',')
685
+ }, {
686
+ 'success': function(data) {
687
+ $scope.listdir();
688
+ }
689
+ }
690
+ );
691
+ };
692
+
693
+ $scope.chownconfirm = function(name, user, group, isdir) {
694
+ if (!name) {
695
+ var names = [];
696
+ angular.forEach($scope.selects, function(selected, item) {
697
+ if (selected) names.push(item);
698
+ });
699
+ if (names.length == 0) {
700
+ Message.setError('请先选择文件或目录!');
701
+ return;
702
+ }
703
+ }
704
+ if (!$scope.users) {
705
+ Request.post('/api/operation/user', {
706
+ 'action': 'listuser',
707
+ 'fullinfo': false
708
+ }, function(data) {
709
+ if (data.code == 0) {
710
+ $scope.users = data.data;
711
+ }
712
+ }, false, true);
713
+ }
714
+ if (!$scope.groups) {
715
+ Request.post('/api/operation/user', {
716
+ 'action': 'listgroup',
717
+ 'fullinfo': false
718
+ }, function(data) {
719
+ if (data.code == 0) {
720
+ $scope.groups = data.data;
721
+ }
722
+ }, false, true);
723
+ }
724
+ if (name) {
725
+ $scope.chown_user = user;
726
+ $scope.chown_group = group;
727
+ $scope.chown_names = [name];
728
+ $scope.chown_recursively = true;
729
+ $scope.chown_hasdir = isdir;
730
+ } else {
731
+ $scope.chown_names = names;
732
+ $scope.chown_recursively = true;
733
+ $scope.chown_hasdir = true;
734
+ }
735
+ $('#chownconfirm').modal();
736
+ };
737
+ $scope.chown = function() {
738
+ var paths = [];
739
+ for (var i = 0; i < $scope.chown_names.length; i++)
740
+ paths.push($scope.curpath + '/' + $scope.chown_names[i]);
741
+ paths = paths.join(',');
742
+ Backend.call(
743
+ $scope,
744
+ module,
745
+ '/api/backend/chown',
746
+ '/api/backend/chown_' + paths, {
747
+ 'paths': paths,
748
+ 'user': $scope.chown_user,
749
+ 'group': $scope.chown_group,
750
+ 'recursively': $scope.chown_recursively
751
+ }, {
752
+ 'success': function(data) {
753
+ if ($scope.chown_names.length == 1)
754
+ $scope.getitem($scope.chown_names[0]);
755
+ else
756
+ $scope.listdir();
757
+ }
758
+ }
759
+ );
760
+ };
761
+
762
+ $scope.chmodconfirm = function(name, perms, isdir) {
763
+ if (!name) {
764
+ var names = [];
765
+ angular.forEach($scope.selects, function(selected, item) {
766
+ if (selected) names.push(item);
767
+ });
768
+ if (names.length == 0) {
769
+ Message.setError('请先选择文件或目录!');
770
+ return;
771
+ }
772
+ perms = '0744';
773
+ }
774
+ perms = parseInt(perms, 8);
775
+ $scope.chmod_permbits = [
776
+ [(perms & 0400) != 0, (perms & 0200) != 0, (perms & 0100) != 0],
777
+ [(perms & 0040) != 0, (perms & 0020) != 0, (perms & 0010) != 0],
778
+ [(perms & 0004) != 0, (perms & 0002) != 0, (perms & 0001) != 0],
779
+ ];
780
+ $scope.chmod_recursively = true;
781
+ if (name) {
782
+ $scope.chmod_names = [name];
783
+ $scope.chmod_hasdir = isdir;
784
+ } else {
785
+ $scope.chmod_names = names;
786
+ $scope.chmod_hasdir = true;
787
+ }
788
+ $('#chmodconfirm').modal();
789
+ };
790
+ $scope.chmod = function() {
791
+ var perms = 0000;
792
+ for (var i = 0; i < 3; i++)
793
+ for (var j = 0; j < 3; j++)
794
+ perms |= ($scope.chmod_permbits[i][j] << (8 - i * 3 - j));
795
+ perms = perms.toString(8);
796
+ var paths = [];
797
+ for (var i = 0; i < $scope.chmod_names.length; i++)
798
+ paths.push($scope.curpath + '/' + $scope.chmod_names[i]);
799
+ paths = paths.join(',');
800
+ Backend.call(
801
+ $scope,
802
+ module,
803
+ '/api/backend/chmod',
804
+ '/api/backend/chmod_' + paths, {
805
+ 'paths': paths,
806
+ 'perms': perms,
807
+ 'recursively': $scope.chmod_recursively
808
+ }, {
809
+ 'success': function(data) {
810
+ if ($scope.chmod_names.length == 1)
811
+ $scope.getitem($scope.chmod_names[0]);
812
+ else
813
+ $scope.listdir();
814
+ }
815
+ }
816
+ );
817
+ };
818
+
819
+ var hasChange = false;
820
+ var editor = CodeMirror(document.getElementById('editor'), {
821
+ value: '',
822
+ lineNumbers: true,
823
+ lineWrapping: true,
824
+ matchBrackets: true,
825
+ onCursorActivity: function() {
826
+ editor.setLineClass(hlLine, null, null);
827
+ hlLine = editor.setLineClass(editor.getCursor().line, null, 'activeline');
828
+ // disable match highlight in IE, or it will slow down the page
829
+ if (!/msie/.test(navigator.userAgent.toLowerCase())) editor.matchHighlight('CodeMirror-matchhighlight');
830
+ },
831
+ onChange: function() {
832
+ hasChange = true;
833
+ }
834
+ });
835
+ var hlLine = editor.setLineClass(0, 'activeline');
836
+ }
837
+ ];
838
+
839
+ var FileTrashCtrl = [
840
+ '$scope', '$routeParams', 'Module', 'Message', 'Request', 'Backend',
841
+ function($scope, $routeParams, Module, Message, Request, Backend) {
842
+ var module = 'file.trash';
843
+ Module.init(module, '回收站管理');
844
+
845
+ $scope.loaded = true;
846
+
847
+ $scope.confirm = function() {};
848
+
849
+ $scope.fileloading = false;
850
+ $scope.tlist = function() {
851
+ $scope.fileloading = true;
852
+ Request.post('/api/operation/file', {
853
+ 'action': 'tlist'
854
+ }, function(data) {
855
+ if (data.code == 0) {
856
+ $scope.items = data.data;
857
+ $scope.fileloading = false;
858
+ }
859
+ });
860
+ };
861
+ $scope.restore = function(mount, uuid) {
862
+ Request.post('/api/operation/file', {
863
+ 'action': 'trestore',
864
+ 'mount': mount,
865
+ 'uuid': uuid
866
+ }, function(data) {
867
+ if (data.code == 0) {
868
+ $scope.tlist();
869
+ }
870
+ });
871
+ };
872
+ $scope.tdeleteconfirm = function(name, mount, uuid) {
873
+ $scope.confirm_title = '删除确认';
874
+ $scope.confirm_body = '<p>删除后文件将不可恢复!</p><p>确认要删除 ' + name + ' 吗?</p>';
875
+ $('#confirm').modal();
876
+ $scope.confirm = function() {
877
+ $scope.tdelete(mount, uuid);
878
+ };
879
+ };
880
+ $scope.tdelete = function(mount, uuid) {
881
+ Request.post('/api/operation/file', {
882
+ 'action': 'titem',
883
+ 'mount': mount,
884
+ 'uuid': uuid
885
+ }, function(data) {
886
+ if (data.code == 0) {
887
+ var path = data.data.originpath;
888
+ Backend.call(
889
+ $scope,
890
+ module,
891
+ '/api/backend/remove',
892
+ '/api/backend/remove_' + path, {
893
+ 'paths': path
894
+ },
895
+ function() {
896
+ Request.post('/api/operation/file', {
897
+ 'action': 'tdelete',
898
+ 'mount': mount,
899
+ 'uuid': uuid
900
+ }, function(data) {
901
+ if (data.code == 0) {
902
+ $scope.tlist();
903
+ }
904
+ });
905
+ }
906
+ );
907
+ }
908
+ });
909
+ };
910
+ $scope.tcleanconfirm = function() {
911
+ $scope.confirm_title = '清空确认';
912
+ $scope.confirm_body = '<p>清空回收站后,回收站中的所有文件都将被删除且不可恢复!<p><p>确认要清空回收站吗?</p>';
913
+ $('#confirm').modal();
914
+ $scope.confirm = function() {
915
+ $scope.tclean();
916
+ };
917
+ };
918
+ $scope.tclean = function() {
919
+ Request.post('/api/operation/file', {
920
+ 'action': 'trashs'
921
+ }, function(data) {
922
+ if (data.code == 0) {
923
+ var trashs = data.data.join(',');
924
+ Backend.call(
925
+ $scope,
926
+ module,
927
+ '/api/backend/remove',
928
+ '/api/backend/remove_' + trashs, {
929
+ 'paths': trashs
930
+ },
931
+ function() {
932
+ Message.setSuccess('清空回收站完成!');
933
+ $scope.tlist();
934
+ }
935
+ );
936
+ }
937
+ });
938
+ };
939
+ }
940
+ ];