Skip to content

Commit 3ea03ab

Browse files
committed
1.0.93-Beta
1 parent f8475b7 commit 3ea03ab

File tree

14 files changed

+363
-220
lines changed

14 files changed

+363
-220
lines changed

FileSystem/DavFile.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,8 @@ class DavFile extends DavHierarchyItem_1.DavHierarchyItem {
244244
}
245245
// Move the file.
246246
await util_1.promisify(fs_1.rename)(this.directory, newDirPath);
247+
// Locks should not be copied, delete them.
248+
await FileSystemInfoExtension_1.FileSystemInfoExtension.setExtendedAttribute(newDirPath, "Locks", {});
247249
}
248250
//$>
249251
//$<IHierarchyItem.Delete
@@ -261,14 +263,18 @@ class DavFile extends DavHierarchyItem_1.DavHierarchyItem {
261263
* @remarks
262264
* Client do not plan to restore upload. Remove any temporary files / cleanup resources here.
263265
*/
264-
cancelUploadAsync() {
266+
cancelUpload() {
267+
return this.delete(null);
265268
}
266269
//$>
267270
/**
268271
* Returns instance of @see IUploadProgressAsync interface.
269-
* @returns Just returns this class.
272+
* @returns Just returns this class.
270273
*/
271274
getUploadProgress() {
275+
const arr = new Array();
276+
arr.push(this);
277+
return arr;
272278
}
273279
containsDownloadParam(url) {
274280
const ind = url.indexOf('?');

FileSystem/DavFile.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import { DavStatus } from "ithit.webdav.server/DavStatus";
66
import { IItemCollection } from "ithit.webdav.server/IItemCollection";
77
import { MultistatusException } from "ithit.webdav.server/MultistatusException";
88
import { EncodeUtil } from "ithit.webdav.server/EncodeUtil";
9+
import { IResumableUpload } from "ithit.webdav.server/ResumableUpload/IResumableUpload";
10+
import { IUploadProgress } from "ithit.webdav.server/ResumableUpload/IUploadProgress";
911
import { lookup } from "mime-types";
1012
import { sep, join } from "path";
1113
import { promisify } from "util";
@@ -18,7 +20,7 @@ import { F_OK } from "constants";
1820
/**
1921
* Represents file in WebDAV repository.
2022
*/
21-
export class DavFile extends DavHierarchyItem implements IFile {
23+
export class DavFile extends DavHierarchyItem implements IFile, IResumableUpload, IUploadProgress {
2224

2325

2426
//$<IContent.ContentType
@@ -306,6 +308,9 @@ export class DavFile extends DavHierarchyItem implements IFile {
306308

307309
// Move the file.
308310
await promisify(rename)(this.directory, newDirPath);
311+
312+
// Locks should not be copied, delete them.
313+
await FileSystemInfoExtension.setExtendedAttribute(newDirPath, "Locks", {});
309314
}
310315
//$>
311316

@@ -325,16 +330,20 @@ export class DavFile extends DavHierarchyItem implements IFile {
325330
* @remarks
326331
* Client do not plan to restore upload. Remove any temporary files / cleanup resources here.
327332
*/
328-
public cancelUploadAsync(): void {
333+
public cancelUpload(): Promise<void> {
334+
return this.delete(null as any as MultistatusException);
329335
}
330336
//$>
331337

332338
/**
333339
* Returns instance of @see IUploadProgressAsync interface.
334-
* @returns Just returns this class.
340+
* @returns Just returns this class.
335341
*/
336-
public getUploadProgress(): void {
342+
public getUploadProgress(): IResumableUpload[] {
343+
const arr = new Array<IResumableUpload>();
344+
arr.push(this);
337345

346+
return arr;
338347
}
339348

340349
public containsDownloadParam(url: string): boolean {

FileSystem/DavFolder.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,13 @@ class DavFolder extends DavHierarchyItem_1.DavHierarchyItem {
5858
for (let i = 0; i < listOfFiles.length; i++) {
5959
const file = this.path + listOfFiles[i];
6060
const child = await this.context.getHierarchyItem(file);
61-
if (child !== null) {
61+
if (child !== null && child !== undefined) {
6262
children.push(child);
6363
}
6464
}
65-
return children;
65+
const folders = children.filter(i => i.fileSystemInfo.isDirectory());
66+
const files = children.filter(i => !i.fileSystemInfo.isDirectory());
67+
return folders.sort((a, b) => a.name > b.name ? 1 : -1).concat(files.sort((a, b) => a.name > b.name ? 1 : -1));
6668
}
6769
//$>
6870
//$<IFolder.CreateFile

FileSystem/DavFolder.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,17 +62,20 @@ export class DavFolder extends DavHierarchyItem implements IFolder {
6262
// You can filter children items in this implementation and
6363
// return only items that you want to be visible for this
6464
// particular user.
65-
const children = new Array<IHierarchyItem>();
65+
const children = new Array<DavHierarchyItem>();
6666
const listOfFiles = await promisify(readdir)(this.directory);
6767
for (let i = 0; i < listOfFiles.length; i++) {
6868
const file = this.path + listOfFiles[i];
69-
const child: IHierarchyItem | null = await this.context.getHierarchyItem(file);
70-
if (child !== null) {
71-
children.push(child);
69+
const child = await this.context.getHierarchyItem(file);
70+
if (child !== null && child !== undefined) {
71+
children.push((child as any as DavHierarchyItem));
7272
}
7373
}
7474

75-
return children;
75+
const folders = children.filter( i => i.fileSystemInfo.isDirectory());
76+
const files = children.filter( i => !i.fileSystemInfo.isDirectory());
77+
78+
return folders.sort((a, b) => a.name > b.name ? 1 : -1).concat(files.sort((a, b) => a.name > b.name ? 1 : -1));
7679
}
7780
//$>
7881

FileSystem/DavHierarchyItem.js

Lines changed: 74 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ const DavStatus_1 = require("ithit.webdav.server/DavStatus");
1111
const path_1 = require("path");
1212
const DateLockInfo_1 = require("./DateLockInfo");
1313
const FileSystemInfoExtension_1 = require("./ExtendedAttributes/FileSystemInfoExtension");
14+
const util_1 = require("util");
15+
const child_process_1 = require("child_process");
1416
/**
1517
* Base class for WebDAV items (folders, files, etc).
1618
*/
@@ -21,6 +23,10 @@ class DavHierarchyItem {
2123
* @param path Encoded path relative to WebDAV root folder.
2224
*/
2325
constructor(directory, context, path, stats) {
26+
/**
27+
* Name of properties attribute.
28+
*/
29+
this.propertiesAttributeName = "Properties";
2430
/**
2531
* Name of locks attribute.
2632
*/
@@ -87,10 +93,10 @@ class DavHierarchyItem {
8793
* @param allprop Whether all properties shall be retrieved.
8894
* @returns Property values.
8995
*/
90-
getProperties(props, allprop) {
91-
let propertyValues = this.getPropertyValues();
96+
async getProperties(props, allprop) {
97+
let propertyValues = await this.getPropertyValues();
9298
if (!allprop) {
93-
propertyValues = propertyValues.filter(item => item.qualifiedName);
99+
propertyValues = propertyValues.filter(item => props.findIndex(p => p.name === item.qualifiedName.name) > -1);
94100
}
95101
return propertyValues;
96102
}
@@ -100,8 +106,8 @@ class DavHierarchyItem {
100106
* Retrieves names of all user defined properties.
101107
* @returns Property names.
102108
*/
103-
getPropertyNames() {
104-
const propertyValues = this.getPropertyValues();
109+
async getPropertyNames() {
110+
const propertyValues = await this.getPropertyValues();
105111
const g = propertyValues.map(item => item.qualifiedName);
106112
return g;
107113
}
@@ -113,7 +119,54 @@ class DavHierarchyItem {
113119
* @param delProps Properties to be deleted.
114120
* @param multistatus Information about properties that failed to create, update or delate.
115121
*/
116-
updateProperties(setProps, delProps, multistatus) { }
122+
async updateProperties(setProps, delProps, multistatus) {
123+
await this.requireHasToken();
124+
let propertyValues = await this.getPropertyValues();
125+
for (const propToSet of setProps) {
126+
// Microsoft Mini-redirector may update file creation date, modification date and access time passing properties:
127+
// <Win32CreationTime xmlns="urn:schemas-microsoft-com:">Thu, 28 Mar 2013 20:15:34 GMT</Win32CreationTime>
128+
// <Win32LastModifiedTime xmlns="urn:schemas-microsoft-com:">Thu, 28 Mar 2013 20:36:24 GMT</Win32LastModifiedTime>
129+
// <Win32LastAccessTime xmlns="urn:schemas-microsoft-com:">Thu, 28 Mar 2013 20:36:24 GMT</Win32LastAccessTime>
130+
// In this case update creation and modified date in your storage or do not save this properties at all, otherwise
131+
// Windows Explorer will display creation and modification date from this props and it will differ from the values
132+
// in the Created and Modified fields in your storage
133+
if (propToSet.qualifiedName.namespace == "urn:schemas-microsoft-com:") {
134+
const creationTimeUtc = new Date();
135+
creationTimeUtc.setTime(Date.parse(propToSet.value));
136+
switch (propToSet.qualifiedName.name) {
137+
case "Win32CreationTime": {
138+
const { stderr } = await util_1.promisify(child_process_1.exec)(`powershell $(Get-Item ${this.directory}).creationtime=$(Get-Date "${creationTimeUtc.toISOString()}")`);
139+
if (stderr) {
140+
throw stderr;
141+
}
142+
break;
143+
}
144+
case "Win32LastModifiedTime": {
145+
const { stderr } = await util_1.promisify(child_process_1.exec)(`powershell $(Get-Item ${this.directory}).lastwritetime=$(Get-Date "${creationTimeUtc.toISOString()}")`);
146+
if (stderr) {
147+
throw stderr;
148+
}
149+
break;
150+
}
151+
default:
152+
this.context.logger.logDebug(`Unspecified case:
153+
DavHierarchyItem.UpdateProperties ${propToSet.qualifiedName.name} from ${propToSet.qualifiedName.namespace} namesapce`);
154+
break;
155+
}
156+
}
157+
else {
158+
const existingProp = propertyValues.filter(p => p.qualifiedName.name === propToSet.qualifiedName.name)[0] || null;
159+
if (existingProp != null) {
160+
existingProp.value = propToSet.value;
161+
}
162+
else {
163+
propertyValues.push(propToSet);
164+
}
165+
}
166+
}
167+
propertyValues = propertyValues.filter(prop => !(delProps.length && delProps.findIndex(delProp => delProp.name === prop.qualifiedName.name) > -1));
168+
await FileSystemInfoExtension_1.FileSystemInfoExtension.setExtendedAttribute(this.directory, this.propertiesAttributeName, propertyValues);
169+
}
117170
//$>
118171
//$<IMsItem.GetFileAttributes
119172
/**
@@ -233,16 +286,26 @@ class DavHierarchyItem {
233286
/**
234287
* Check that if the item is locked then client has submitted correct lock token.
235288
*/
236-
requireHasToken(skipShared = false) {
289+
async requireHasToken(skipShared = false) {
290+
const locks = await this.getLocks();
291+
if (locks !== null && locks.length) {
292+
const clientLockTokens = this.context.request.clientLockTokens;
293+
const resultFiltering = locks.filter(l => !(clientLockTokens.length && clientLockTokens.findIndex(clientLockToken => clientLockToken === l.lockToken) > -1));
294+
if (resultFiltering.length) {
295+
throw new LockedException_1.LockedException();
296+
}
297+
}
237298
return Promise.resolve();
238299
}
239300
/**
240301
* Retrieves list of user defined propeties for this item.
241302
* @returns List of user defined properties.
242303
*/
243-
getPropertyValues() {
244-
if (this.propertyValues === null) {
304+
async getPropertyValues() {
305+
if (this.propertyValues === null || this.propertyValues === undefined) {
245306
this.propertyValues = new Array();
307+
this.propertyValues = await FileSystemInfoExtension_1.FileSystemInfoExtension.getExtendedAttribute(this.directory, this.propertiesAttributeName);
308+
this.propertyValues = Array.isArray(this.propertyValues) ? this.propertyValues.filter(item => Object.keys(item).length && item.constructor === Object) : [];
246309
}
247310
return this.propertyValues;
248311
}
@@ -272,8 +335,8 @@ class DavHierarchyItem {
272335
async saveLock(lockInfo) {
273336
let locks = await this.getLocks(true);
274337
// remove all expired locks
275-
locks = locks.filter(x => x.expiration <= Date.now());
276-
const existingLock = locks.filter(x => x.lockToken <= lockInfo.lockToken)[0] || null;
338+
locks = locks.filter(x => Date.now() <= x.expiration);
339+
const existingLock = locks.filter(x => x.lockToken === lockInfo.lockToken)[0] || null;
277340
if (existingLock) {
278341
existingLock.timeOut = lockInfo.timeOut;
279342
existingLock.level = lockInfo.level;

0 commit comments

Comments
 (0)