Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
jio_mebibou
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Alexandra Rogova
jio_mebibou
Commits
f0045483
Commit
f0045483
authored
Aug 21, 2013
by
Tristan Cavelier
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Some files removed temporarily
parent
3356688e
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
0 additions
and
3179 deletions
+0
-3179
src/jio.storage/conflictmanagerstorage.js
src/jio.storage/conflictmanagerstorage.js
+0
-1085
src/jio.storage/davstorage.js
src/jio.storage/davstorage.js
+0
-943
src/jio.storage/ramstorage.js
src/jio.storage/ramstorage.js
+0
-446
test/jio.storage/davstorage.tests.js
test/jio.storage/davstorage.tests.js
+0
-705
No files found.
src/jio.storage/conflictmanagerstorage.js
deleted
100644 → 0
View file @
3356688e
/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */
/*global jIO: true, hex_sha256: true, setTimeout: true */
jIO
.
addStorageType
(
'
conflictmanager
'
,
function
(
spec
,
my
)
{
var
that
,
priv
,
storage_exists
,
local_namespace
,
empty_fun
,
super_serialized
;
spec
=
spec
||
{};
that
=
my
.
basicStorage
(
spec
,
my
);
priv
=
{};
storage_exists
=
(
spec
.
storage
?
true
:
false
);
priv
.
sub_storage_spec
=
spec
.
storage
||
{
type
:
'
base
'
};
priv
.
sub_storage_string
=
JSON
.
stringify
(
priv
.
sub_storage_spec
);
local_namespace
=
'
jio/conflictmanager/
'
+
priv
.
sub_storage_string
+
'
/
'
;
empty_fun
=
function
()
{};
super_serialized
=
that
.
serialized
;
that
.
serialized
=
function
()
{
var
o
=
super_serialized
();
o
.
storage
=
priv
.
sub_storage_spec
;
return
o
;
};
that
.
validateState
=
function
()
{
if
(
storage_exists
)
{
return
''
;
}
return
'
Need at least one parameter: "storage".
'
;
};
priv
.
getDistantMetadata
=
function
(
command
,
path
,
success
,
error
)
{
var
cloned_option
=
command
.
cloneOption
();
cloned_option
.
metadata_only
=
false
;
that
.
addJob
(
'
get
'
,
priv
.
sub_storage_spec
,
path
,
cloned_option
,
success
,
error
);
};
priv
.
saveMetadataToDistant
=
function
(
command
,
path
,
content
,
success
,
error
)
{
that
.
addJob
(
'
put
'
,
priv
.
sub_storage_spec
,
{
_id
:
path
,
content
:
JSON
.
stringify
(
content
)
},
command
.
cloneOption
(),
success
,
error
);
};
priv
.
saveNewRevision
=
function
(
command
,
path
,
content
,
success
,
error
)
{
that
.
addJob
(
'
post
'
,
priv
.
sub_storage_spec
,
{
_id
:
path
,
content
:
content
},
command
.
cloneOption
(),
success
,
error
);
};
priv
.
loadRevision
=
function
(
command
,
path
,
success
,
error
)
{
that
.
addJob
(
'
get
'
,
priv
.
sub_storage_spec
,
path
,
command
.
cloneOption
(),
success
,
error
);
};
priv
.
deleteAFile
=
function
(
command
,
path
,
success
,
error
)
{
that
.
addJob
(
'
remove
'
,
priv
.
sub_storage_spec
,
{
_id
:
path
},
command
.
cloneOption
(),
success
,
error
);
};
priv
.
chooseARevision
=
function
(
metadata
)
{
var
tmp_last_modified
=
0
,
ret_rev
=
''
,
rev
;
for
(
rev
in
metadata
)
{
if
(
metadata
.
hasOwnProperty
(
rev
))
{
if
(
tmp_last_modified
<
metadata
[
rev
].
_last_modified
)
{
tmp_last_modified
=
metadata
[
rev
].
_last_modified
;
ret_rev
=
rev
;
}
}
}
return
ret_rev
;
};
priv
.
_revs
=
function
(
metadata
,
revision
)
{
if
(
!
(
metadata
&&
revision
))
{
return
null
;
}
if
(
metadata
[
revision
])
{
return
{
start
:
metadata
[
revision
].
_revisions
.
length
,
ids
:
metadata
[
revision
].
_revisions
};
}
return
null
;
};
priv
.
_revs_info
=
function
(
metadata
)
{
if
(
!
metadata
)
{
return
null
;
}
var
k
,
l
=
[];
for
(
k
in
metadata
)
{
if
(
metadata
.
hasOwnProperty
(
k
))
{
l
.
push
({
rev
:
k
,
status
:
(
metadata
[
k
]
?
(
metadata
[
k
].
_deleted
?
'
deleted
'
:
'
available
'
)
:
'
missing
'
)
});
}
}
return
l
;
};
priv
.
solveConflict
=
function
(
doc
,
option
,
param
)
{
var
o
=
{},
am
=
priv
.
newAsyncModule
(),
command
=
param
.
command
,
metadata_file_path
=
param
.
docid
+
'
.metadata
'
,
current_revision
=
''
,
current_revision_file_path
=
''
,
metadata_file_content
=
null
,
on_conflict
=
false
,
conflict_object
=
{
total_rows
:
0
,
rows
:
[]
},
on_remove
=
param
.
_deleted
,
previous_revision
=
param
.
previous_revision
,
previous_revision_content_object
=
null
,
now
=
new
Date
(),
failerror
;
o
.
getDistantMetadata
=
function
()
{
priv
.
getDistantMetadata
(
command
,
metadata_file_path
,
function
(
result
)
{
var
previous_revision_number
=
parseInt
(
previous_revision
.
split
(
'
-
'
)[
0
],
10
);
metadata_file_content
=
JSON
.
parse
(
result
.
content
);
// set current revision
// jslint: removed '' in hex_sha256(''...
current_revision
=
(
previous_revision_number
+
1
)
+
'
-
'
+
hex_sha256
(
doc
.
content
+
previous_revision
+
JSON
.
stringify
(
metadata_file_content
));
current_revision_file_path
=
param
.
docid
+
'
.
'
+
current_revision
;
previous_revision_content_object
=
metadata_file_content
[
previous_revision
]
||
{};
if
(
!
on_remove
)
{
am
.
wait
(
o
,
'
saveMetadataOnDistant
'
,
1
);
am
.
call
(
o
,
'
saveNewRevision
'
);
}
am
.
call
(
o
,
'
previousUpdateMetadata
'
);
},
function
(
error
)
{
am
.
call
(
o
,
'
error
'
,
[
error
]);
}
);
};
o
.
saveNewRevision
=
function
()
{
priv
.
saveNewRevision
(
command
,
current_revision_file_path
,
doc
.
content
,
function
()
{
am
.
call
(
o
,
'
saveMetadataOnDistant
'
);
},
function
(
error
)
{
am
.
call
(
o
,
'
error
'
,
[
error
]);
}
);
};
o
.
previousUpdateMetadata
=
function
()
{
var
i
;
for
(
i
=
0
;
i
<
param
.
key
.
length
;
i
+=
1
)
{
delete
metadata_file_content
[
param
.
key
[
i
]];
}
am
.
call
(
o
,
'
checkForConflicts
'
);
};
o
.
checkForConflicts
=
function
()
{
var
rev
;
for
(
rev
in
metadata_file_content
)
{
if
(
metadata_file_content
.
hasOwnProperty
(
rev
))
{
on_conflict
=
true
;
failerror
=
{
status
:
409
,
error
:
'
conflict
'
,
statusText
:
'
Conflict
'
,
reason
:
'
document update conflict
'
,
message
:
'
There is one or more conflicts
'
};
break
;
}
}
am
.
call
(
o
,
'
updateMetadata
'
);
};
o
.
updateMetadata
=
function
()
{
var
revision_history
,
id
=
''
;
id
=
current_revision
.
split
(
'
-
'
);
id
.
shift
();
id
=
id
.
join
(
'
-
'
);
revision_history
=
previous_revision_content_object
.
_revisions
;
revision_history
.
unshift
(
id
);
metadata_file_content
[
current_revision
]
=
{
_creation_date
:
previous_revision_content_object
.
_creation_date
||
now
.
getTime
(),
_last_modified
:
now
.
getTime
(),
_revisions
:
revision_history
,
_conflict
:
on_conflict
,
_deleted
:
on_remove
};
if
(
on_conflict
)
{
conflict_object
=
priv
.
createConflictObject
(
command
,
metadata_file_content
,
current_revision
);
}
am
.
call
(
o
,
'
saveMetadataOnDistant
'
);
};
o
.
saveMetadataOnDistant
=
function
()
{
priv
.
saveMetadataToDistant
(
command
,
metadata_file_path
,
metadata_file_content
,
function
()
{
am
.
call
(
o
,
'
deleteAllConflictingRevision
'
);
if
(
on_conflict
)
{
am
.
call
(
o
,
'
error
'
);
}
else
{
am
.
call
(
o
,
'
success
'
);
}
},
function
(
error
)
{
am
.
call
(
o
,
'
error
'
,
[
error
]);
}
);
};
o
.
deleteAllConflictingRevision
=
function
()
{
var
i
;
for
(
i
=
0
;
i
<
param
.
key
.
length
;
i
+=
1
)
{
priv
.
deleteAFile
(
command
,
param
.
docid
+
'
.
'
+
param
.
key
[
i
],
empty_fun
,
empty_fun
);
}
};
o
.
success
=
function
()
{
var
a
=
{
ok
:
true
,
id
:
param
.
docid
,
rev
:
current_revision
};
am
.
neverCall
(
o
,
'
error
'
);
am
.
neverCall
(
o
,
'
success
'
);
if
(
option
.
revs
)
{
a
.
revisions
=
priv
.
_revs
(
metadata_file_content
,
current_revision
);
}
if
(
option
.
revs_info
)
{
a
.
revs_info
=
priv
.
_revs_info
(
metadata_file_content
);
}
if
(
option
.
conflicts
)
{
a
.
conflicts
=
conflict_object
;
}
param
.
success
(
a
);
};
o
.
error
=
function
(
error
)
{
var
err
=
error
||
failerror
||
{
status
:
0
,
statusText
:
'
Unknown
'
,
error
:
'
unknown_error
'
,
message
:
'
Unknown error.
'
,
reason
:
'
unknown error
'
};
if
(
current_revision
)
{
err
.
rev
=
current_revision
;
}
if
(
option
.
revs
)
{
err
.
revisions
=
priv
.
_revs
(
metadata_file_content
,
current_revision
);
}
if
(
option
.
revs_info
)
{
err
.
revs_info
=
priv
.
_revs_info
(
metadata_file_content
);
}
if
(
option
.
conflicts
)
{
err
.
conflicts
=
conflict_object
;
}
am
.
neverCall
(
o
,
'
error
'
);
am
.
neverCall
(
o
,
'
success
'
);
param
.
error
(
err
);
};
am
.
call
(
o
,
'
getDistantMetadata
'
);
};
priv
.
createConflictObject
=
function
(
command
,
metadata
,
revision
)
{
return
{
total_rows
:
1
,
rows
:
[
priv
.
createConflictRow
(
command
,
command
.
getDocId
(),
metadata
,
revision
)]
};
};
priv
.
getParam
=
function
(
list
)
{
var
param
=
{},
i
=
0
;
if
(
typeof
list
[
i
]
===
'
string
'
)
{
param
.
content
=
list
[
i
];
i
+=
1
;
}
if
(
typeof
list
[
i
]
===
'
object
'
)
{
param
.
options
=
list
[
i
];
i
+=
1
;
}
else
{
param
.
options
=
{};
}
param
.
callback
=
function
()
{};
param
.
success
=
function
(
val
)
{
param
.
callback
(
undefined
,
val
);
};
param
.
error
=
function
(
err
)
{
param
.
callback
(
err
,
undefined
);
};
if
(
typeof
list
[
i
]
===
'
function
'
)
{
if
(
typeof
list
[
i
+
1
]
===
'
function
'
)
{
param
.
success
=
list
[
i
];
param
.
error
=
list
[
i
+
1
];
}
else
{
param
.
callback
=
list
[
i
];
}
}
return
param
;
};
priv
.
createConflictRow
=
function
(
command
,
docid
,
metadata
,
revision
)
{
var
row
=
{
id
:
docid
,
key
:
[],
value
:
{
// jslint: removed params /* content, option, success, error */
_solveConflict
:
function
()
{
var
param
=
{},
got
=
priv
.
getParam
(
arguments
);
if
(
got
.
content
===
undefined
)
{
param
.
_deleted
=
true
;
}
else
{
param
.
_deleted
=
false
;
}
param
.
success
=
got
.
success
;
param
.
error
=
got
.
error
;
param
.
previous_revision
=
revision
;
param
.
docid
=
docid
;
param
.
key
=
row
.
key
;
param
.
command
=
command
.
clone
();
return
priv
.
solveConflict
({
_id
:
docid
,
content
:
got
.
content
,
_rev
:
revision
},
got
.
options
,
param
);
}
}
},
k
;
for
(
k
in
metadata
)
{
if
(
metadata
.
hasOwnProperty
(
k
))
{
row
.
key
.
push
(
k
);
}
}
return
row
;
};
priv
.
newAsyncModule
=
function
()
{
var
async
=
{};
async
.
call
=
function
(
obj
,
function_name
,
arglist
)
{
obj
.
_wait
=
obj
.
_wait
||
{};
if
(
obj
.
_wait
[
function_name
])
{
obj
.
_wait
[
function_name
]
-=
1
;
return
empty_fun
;
}
// ok if undef or 0
arglist
=
arglist
||
[];
setTimeout
(
function
()
{
obj
[
function_name
].
apply
(
obj
[
function_name
],
arglist
);
});
};
async
.
neverCall
=
function
(
obj
,
function_name
)
{
obj
.
_wait
=
obj
.
_wait
||
{};
obj
.
_wait
[
function_name
]
=
-
1
;
};
async
.
wait
=
function
(
obj
,
function_name
,
times
)
{
obj
.
_wait
=
obj
.
_wait
||
{};
obj
.
_wait
[
function_name
]
=
times
;
};
async
.
end
=
function
()
{
async
.
call
=
empty_fun
;
};
return
async
;
};
that
.
post
=
function
(
command
)
{
that
.
put
(
command
);
};
/**
* Save a document and can manage conflicts.
* @method put
*/
that
.
put
=
function
(
command
)
{
var
o
=
{},
am
=
priv
.
newAsyncModule
(),
metadata_file_path
=
command
.
getDocId
()
+
'
.metadata
'
,
current_revision
=
''
,
current_revision_file_path
=
''
,
metadata_file_content
=
null
,
on_conflict
=
false
,
conflict_object
=
{
total_rows
:
0
,
rows
:
[]
},
previous_revision
=
command
.
getDocInfo
(
'
_rev
'
)
||
'
0
'
,
previous_revision_file_path
=
command
.
getDocId
()
+
'
.
'
+
previous_revision
,
now
=
new
Date
(),
failerror
;
o
.
getDistantMetadata
=
function
()
{
priv
.
getDistantMetadata
(
command
,
metadata_file_path
,
function
(
result
)
{
var
previous_revision_number
=
parseInt
(
previous_revision
.
split
(
'
-
'
)[
0
],
10
);
metadata_file_content
=
JSON
.
parse
(
result
.
content
);
// set current revision
current_revision
=
(
previous_revision_number
+
1
)
+
'
-
'
+
// jslint: removed hex_sha256(''+...
hex_sha256
(
command
.
getDocContent
()
+
previous_revision
+
JSON
.
stringify
(
metadata_file_content
));
current_revision_file_path
=
command
.
getDocId
()
+
'
.
'
+
current_revision
;
am
.
wait
(
o
,
'
saveMetadataOnDistant
'
,
1
);
am
.
call
(
o
,
'
saveNewRevision
'
);
am
.
call
(
o
,
'
checkForConflicts
'
);
},
function
(
error
)
{
if
(
error
.
status
===
404
)
{
current_revision
=
'
1-
'
+
hex_sha256
(
command
.
getDocContent
());
current_revision_file_path
=
command
.
getDocId
()
+
'
.
'
+
current_revision
;
am
.
wait
(
o
,
'
saveMetadataOnDistant
'
,
1
);
am
.
call
(
o
,
'
saveNewRevision
'
);
am
.
call
(
o
,
'
createMetadata
'
);
}
else
{
am
.
call
(
o
,
'
error
'
,
[
error
]);
}
}
);
};
o
.
saveNewRevision
=
function
()
{
priv
.
saveNewRevision
(
command
,
current_revision_file_path
,
command
.
getDocContent
(),
function
()
{
am
.
call
(
o
,
'
saveMetadataOnDistant
'
);
},
function
(
error
)
{
am
.
call
(
o
,
'
error
'
,
[
error
]);
}
);
};
o
.
checkForConflicts
=
function
()
{
var
rev
;
for
(
rev
in
metadata_file_content
)
{
if
(
metadata_file_content
.
hasOwnProperty
(
rev
)
&&
rev
!==
previous_revision
)
{
on_conflict
=
true
;
failerror
=
{
status
:
409
,
error
:
'
conflict
'
,
statusText
:
'
Conflict
'
,
reason
:
'
document update conflict
'
,
message
:
'
Document update conflict.
'
};
break
;
}
}
am
.
call
(
o
,
'
updateMetadata
'
);
};
o
.
createMetadata
=
function
()
{
var
id
=
current_revision
;
id
=
id
.
split
(
'
-
'
);
id
.
shift
();
id
=
id
.
join
(
'
-
'
);
metadata_file_content
=
{};
metadata_file_content
[
current_revision
]
=
{
_creation_date
:
now
.
getTime
(),
_last_modified
:
now
.
getTime
(),
_revisions
:
[
id
],
_conflict
:
false
,
_deleted
:
false
};
am
.
call
(
o
,
'
saveMetadataOnDistant
'
);
};
o
.
updateMetadata
=
function
()
{
var
previous_creation_date
,
revision_history
=
[],
id
=
''
;
if
(
metadata_file_content
[
previous_revision
])
{
previous_creation_date
=
metadata_file_content
[
previous_revision
].
_creation_date
;
revision_history
=
metadata_file_content
[
previous_revision
].
_revisions
;
delete
metadata_file_content
[
previous_revision
];
}
id
=
current_revision
.
split
(
'
-
'
);
id
.
shift
();
id
=
id
.
join
(
'
-
'
);
revision_history
.
unshift
(
id
);
metadata_file_content
[
current_revision
]
=
{
_creation_date
:
previous_creation_date
||
now
.
getTime
(),
_last_modified
:
now
.
getTime
(),
_revisions
:
revision_history
,
_conflict
:
on_conflict
,
_deleted
:
false
};
if
(
on_conflict
)
{
conflict_object
=
priv
.
createConflictObject
(
command
,
metadata_file_content
,
current_revision
);
}
am
.
call
(
o
,
'
saveMetadataOnDistant
'
);
};
o
.
saveMetadataOnDistant
=
function
()
{
priv
.
saveMetadataToDistant
(
command
,
metadata_file_path
,
metadata_file_content
,
function
()
{
am
.
call
(
o
,
'
deletePreviousRevision
'
);
if
(
on_conflict
)
{
am
.
call
(
o
,
'
error
'
);
}
else
{
am
.
call
(
o
,
'
success
'
);
}
},
function
(
error
)
{
am
.
call
(
o
,
'
error
'
,
[
error
]);
}
);
};
o
.
deletePreviousRevision
=
function
()
{
// jslint: removed /*&& !on_conflict*/
if
(
previous_revision
!==
'
0
'
)
{
priv
.
deleteAFile
(
command
,
previous_revision_file_path
,
empty_fun
,
empty_fun
);
}
};
o
.
success
=
function
()
{
var
a
=
{
ok
:
true
,
id
:
command
.
getDocId
(),
rev
:
current_revision
};
am
.
neverCall
(
o
,
'
error
'
);
am
.
neverCall
(
o
,
'
success
'
);
if
(
command
.
getOption
(
'
revs
'
))
{
a
.
revisions
=
priv
.
_revs
(
metadata_file_content
,
current_revision
);
}
if
(
command
.
getOption
(
'
revs_info
'
))
{
a
.
revs_info
=
priv
.
_revs_info
(
metadata_file_content
);
}
if
(
command
.
getOption
(
'
conflicts
'
))
{
a
.
conflicts
=
conflict_object
;
}
that
.
success
(
a
);
};
o
.
error
=
function
(
error
)
{
var
err
=
error
||
failerror
||
{
status
:
0
,
statusText
:
'
Unknown
'
,
error
:
'
unknown_error
'
,
message
:
'
Unknown error.
'
,
reason
:
'
unknown error
'
};
if
(
current_revision
)
{
err
.
rev
=
current_revision
;
}
if
(
command
.
getOption
(
'
revs
'
))
{
err
.
revisions
=
priv
.
_revs
(
metadata_file_content
,
current_revision
);
}
if
(
command
.
getOption
(
'
revs_info
'
))
{
err
.
revs_info
=
priv
.
_revs_info
(
metadata_file_content
);
}
if
(
command
.
getOption
(
'
conflicts
'
))
{
err
.
conflicts
=
conflict_object
;
}
am
.
neverCall
(
o
,
'
error
'
);
am
.
neverCall
(
o
,
'
success
'
);
that
.
error
(
err
);
};
am
.
call
(
o
,
'
getDistantMetadata
'
);
};
// end put
/**
* Load a document from several storages, and send the first retreived
* document.
* @method get
*/
that
.
get
=
function
(
command
)
{
var
o
=
{},
am
=
priv
.
newAsyncModule
(),
metadata_file_path
=
command
.
getDocId
()
+
'
.metadata
'
,
current_revision
=
command
.
getOption
(
'
rev
'
)
||
''
,
metadata_file_content
=
null
,
metadata_only
=
command
.
getOption
(
'
metadata_only
'
),
on_conflict
=
false
,
conflict_object
=
{
total_rows
:
0
,
rows
:
[]
},
doc
=
{
_id
:
command
.
getDocId
()
},
call404
=
function
(
message
)
{
am
.
call
(
o
,
'
error
'
,
[{
status
:
404
,
statusText
:
'
Not Found
'
,
error
:
'
not_found
'
,
message
:
message
,
reason
:
message
}]);
};
o
.
getDistantMetadata
=
function
()
{
priv
.
getDistantMetadata
(
command
,
metadata_file_path
,
function
(
result
)
{
metadata_file_content
=
JSON
.
parse
(
result
.
content
);
if
(
!
metadata_only
)
{
am
.
wait
(
o
,
'
success
'
,
1
);
}
am
.
call
(
o
,
'
affectMetadata
'
);
am
.
call
(
o
,
'
checkForConflicts
'
);
},
function
(
error
)
{
am
.
call
(
o
,
'
error
'
,
[
error
]);
}
);
};
o
.
affectMetadata
=
function
()
{
if
(
current_revision
)
{
if
(
!
metadata_file_content
[
current_revision
])
{
return
call404
(
'
Document revision does not exists.
'
);
}
}
else
{
current_revision
=
priv
.
chooseARevision
(
metadata_file_content
);
}
doc
.
_last_modified
=
metadata_file_content
[
current_revision
].
_last_modified
;
doc
.
_creation_date
=
metadata_file_content
[
current_revision
].
_creation_date
;
doc
.
_rev
=
current_revision
;
if
(
metadata_only
)
{
am
.
call
(
o
,
'
success
'
);
}
else
{
am
.
call
(
o
,
'
loadRevision
'
);
}
};
o
.
loadRevision
=
function
()
{
if
(
!
current_revision
||
metadata_file_content
[
current_revision
].
_deleted
)
{
return
call404
(
'
Document has been removed.
'
);
}
priv
.
loadRevision
(
command
,
doc
.
_id
+
'
.
'
+
current_revision
,
function
(
result
)
{
doc
.
content
=
result
.
content
;
am
.
call
(
o
,
'
success
'
);
},
function
(
error
)
{
am
.
call
(
o
,
'
error
'
,
[
error
]);
}
);
};
o
.
checkForConflicts
=
function
()
{
if
(
metadata_file_content
[
current_revision
].
_conflict
)
{
on_conflict
=
true
;
conflict_object
=
priv
.
createConflictObject
(
command
,
metadata_file_content
,
current_revision
);
}
am
.
call
(
o
,
'
success
'
);
};
o
.
success
=
function
()
{
am
.
neverCall
(
o
,
'
error
'
);
am
.
neverCall
(
o
,
'
success
'
);
if
(
command
.
getOption
(
'
revs
'
))
{
doc
.
_revisions
=
priv
.
_revs
(
metadata_file_content
,
current_revision
);
}
if
(
command
.
getOption
(
'
revs_info
'
))
{
doc
.
_revs_info
=
priv
.
_revs_info
(
metadata_file_content
);
}
if
(
command
.
getOption
(
'
conflicts
'
))
{
doc
.
_conflicts
=
conflict_object
;
}
that
.
success
(
doc
);
};
o
.
error
=
function
(
error
)
{
var
err
=
error
||
{
status
:
0
,
statusText
:
'
Unknown
'
,
message
:
'
Unknown error.
'
};
if
(
command
.
getOption
(
'
revs
'
))
{
err
.
_revisions
=
priv
.
_revs
(
metadata_file_content
,
current_revision
);
}
if
(
command
.
getOption
(
'
revs_info
'
))
{
err
.
_revs_info
=
priv
.
_revs_info
(
metadata_file_content
);
}
if
(
command
.
getOption
(
'
conflicts
'
))
{
err
.
_conflicts
=
conflict_object
;
}
am
.
neverCall
(
o
,
'
error
'
);
am
.
neverCall
(
o
,
'
success
'
);
that
.
error
(
err
);
};
am
.
call
(
o
,
'
getDistantMetadata
'
);
};
/**
* Get a document list from several storages, and returns the first
* retreived document list.
* @method allDocs
*/
that
.
allDocs
=
function
(
command
)
{
var
o
=
{},
am
=
priv
.
newAsyncModule
(),
metadata_only
=
command
.
getOption
(
'
metadata_only
'
),
result_list
=
[],
conflict_object
=
{
total_rows
:
0
,
rows
:
[]
},
success_count
=
0
,
success_max
=
0
;
o
.
retreiveList
=
function
()
{
var
cloned_option
=
command
.
cloneOption
(),
success
=
function
(
result
)
{
am
.
call
(
o
,
'
filterTheList
'
,
[
result
]);
},
error
=
function
(
error
)
{
am
.
call
(
o
,
'
error
'
,
[
error
]);
};
cloned_option
.
metadata_only
=
true
;
that
.
addJob
(
'
allDocs
'
,
priv
.
sub_storage_spec
,
null
,
cloned_option
,
success
,
error
);
};
o
.
filterTheList
=
function
(
result
)
{
var
i
,
splitname
;
success_max
+=
1
;
for
(
i
=
0
;
i
<
result
.
total_rows
;
i
+=
1
)
{
splitname
=
result
.
rows
[
i
].
id
.
split
(
'
.
'
)
||
[];
if
(
splitname
.
length
>
0
&&
splitname
[
splitname
.
length
-
1
]
===
'
metadata
'
)
{
success_max
+=
1
;
splitname
.
length
-=
1
;
am
.
call
(
o
,
'
loadMetadataFile
'
,
[
splitname
.
join
(
'
.
'
)]);
}
}
am
.
call
(
o
,
'
success
'
);
};
o
.
loadMetadataFile
=
function
(
path
)
{
priv
.
getDistantMetadata
(
command
,
path
+
'
.metadata
'
,
function
(
data
)
{
data
=
JSON
.
parse
(
data
.
content
);
var
revision
=
priv
.
chooseARevision
(
data
);
if
(
!
data
[
revision
].
_deleted
)
{
am
.
call
(
o
,
'
loadFile
'
,
[
path
,
revision
,
data
]);
}
else
{
am
.
call
(
o
,
'
success
'
);
}
},
function
(
error
)
{
am
.
call
(
o
,
'
error
'
,
[
error
]);
}
);
};
o
.
loadFile
=
function
(
path
,
revision
,
data
)
{
var
doc
=
{
id
:
path
,
key
:
path
,
value
:
{
_last_modified
:
data
[
revision
].
_last_modified
,
_creation_date
:
data
[
revision
].
_creation_date
,
_rev
:
revision
}
};
if
(
command
.
getOption
(
'
revs
'
))
{
doc
.
value
.
_revisions
=
priv
.
_revs
(
data
,
revision
);
}
if
(
command
.
getOption
(
'
revs_info
'
))
{
doc
.
value
.
_revs_info
=
priv
.
_revs_info
(
data
,
revision
);
}
if
(
command
.
getOption
(
'
conflicts
'
))
{
if
(
data
[
revision
].
_conflict
)
{
conflict_object
.
total_rows
+=
1
;
conflict_object
.
rows
.
push
(
priv
.
createConflictRow
(
command
,
path
,
data
,
revision
)
);
}
}
if
(
!
metadata_only
)
{
priv
.
loadRevision
(
command
,
path
+
'
.
'
+
revision
,
function
(
data
)
{
doc
.
content
=
data
.
content
;
result_list
.
push
(
doc
);
am
.
call
(
o
,
'
success
'
);
},
function
(
error
)
{
am
.
call
(
o
,
'
error
'
,
[
error
]);
}
);
}
else
{
result_list
.
push
(
doc
);
am
.
call
(
o
,
'
success
'
);
}
};
o
.
success
=
function
()
{
var
obj
;
success_count
+=
1
;
if
(
success_count
>=
success_max
)
{
am
.
end
();
obj
=
{
total_rows
:
result_list
.
length
,
rows
:
result_list
};
if
(
command
.
getOption
(
'
conflicts
'
))
{
obj
.
conflicts
=
conflict_object
;
}
that
.
success
(
obj
);
}
};
o
.
error
=
function
(
error
)
{
am
.
end
();
that
.
error
(
error
);
};
am
.
call
(
o
,
'
retreiveList
'
);
};
// end allDocs
/**
* Remove a document from several storages.
* @method remove
*/
that
.
remove
=
function
(
command
)
{
var
o
=
{},
am
=
priv
.
newAsyncModule
(),
metadata_file_path
=
command
.
getDocId
()
+
'
.metadata
'
,
current_revision
=
''
,
current_revision_file_path
=
''
,
metadata_file_content
=
null
,
on_conflict
=
false
,
conflict_object
=
{
total_rows
:
0
,
rows
:
[]
},
previous_revision
=
command
.
getOption
(
'
rev
'
)
||
'
0
'
,
previous_revision_file_path
=
command
.
getDocId
()
+
'
.
'
+
previous_revision
,
now
=
new
Date
(),
failerror
;
o
.
getDistantMetadata
=
function
()
{
priv
.
getDistantMetadata
(
command
,
metadata_file_path
,
function
(
result
)
{
metadata_file_content
=
JSON
.
parse
(
result
.
content
);
if
(
previous_revision
===
'
last
'
)
{
previous_revision
=
priv
.
chooseARevision
(
metadata_file_content
);
previous_revision_file_path
=
command
.
getDocId
()
+
'
.
'
+
previous_revision
;
}
var
previous_revision_number
=
parseInt
(
previous_revision
.
split
(
'
-
'
)[
0
],
10
)
||
0
;
// set current revision
current_revision
=
(
previous_revision_number
+
1
)
+
'
-
'
+
//jslint: removed hex_sha256(''...
hex_sha256
(
previous_revision
+
JSON
.
stringify
(
metadata_file_content
)
);
current_revision_file_path
=
command
.
getDocId
()
+
'
.
'
+
current_revision
;
am
.
call
(
o
,
'
checkForConflicts
'
);
},
function
(
error
)
{
if
(
error
.
status
===
404
)
{
am
.
call
(
o
,
'
error
'
,
[{
status
:
404
,
statusText
:
'
Not Found
'
,
error
:
'
not_found
'
,
reason
:
'
missing
'
,
message
:
'
Document not found.
'
}]);
}
else
{
am
.
call
(
o
,
'
error
'
,
[
error
]);
}
}
);
};
o
.
checkForConflicts
=
function
()
{
var
rev
;
for
(
rev
in
metadata_file_content
)
{
if
(
metadata_file_content
.
hasOwnProperty
(
rev
)
&&
rev
!==
previous_revision
)
{
on_conflict
=
true
;
failerror
=
{
status
:
409
,
error
:
'
conflict
'
,
statusText
:
'
Conflict
'
,
reason
:
'
document update conflict
'
,
message
:
'
There is one or more conflicts
'
};
break
;
}
}
am
.
call
(
o
,
'
updateMetadata
'
);
};
o
.
updateMetadata
=
function
()
{
var
previous_creation_date
,
revision_history
=
[],
id
=
''
;
if
(
metadata_file_content
[
previous_revision
])
{
previous_creation_date
=
metadata_file_content
[
previous_revision
].
_creation_date
;
revision_history
=
metadata_file_content
[
previous_revision
].
_revisions
;
delete
metadata_file_content
[
previous_revision
];
}
id
=
current_revision
;
id
=
id
.
split
(
'
-
'
);
id
.
shift
();
id
=
id
.
join
(
'
-
'
);
revision_history
.
unshift
(
id
);
metadata_file_content
[
current_revision
]
=
{
_creation_date
:
previous_creation_date
||
now
.
getTime
(),
_last_modified
:
now
.
getTime
(),
_revisions
:
revision_history
,
_conflict
:
on_conflict
,
_deleted
:
true
};
if
(
on_conflict
)
{
conflict_object
=
priv
.
createConflictObject
(
command
,
metadata_file_content
,
current_revision
);
}
am
.
call
(
o
,
'
saveMetadataOnDistant
'
);
};
o
.
saveMetadataOnDistant
=
function
()
{
priv
.
saveMetadataToDistant
(
command
,
metadata_file_path
,
metadata_file_content
,
function
()
{
am
.
call
(
o
,
'
deletePreviousRevision
'
);
if
(
on_conflict
)
{
am
.
call
(
o
,
'
error
'
);
}
else
{
am
.
call
(
o
,
'
success
'
);
}
},
function
(
error
)
{
am
.
call
(
o
,
'
error
'
,
[
error
]);
}
);
};
o
.
deletePreviousRevision
=
function
()
{
// jslint: removed /*&& !on_conflict*/
if
(
previous_revision
!==
'
0
'
)
{
priv
.
deleteAFile
(
command
,
previous_revision_file_path
,
empty_fun
,
empty_fun
);
}
};
o
.
success
=
function
(
revision
)
{
var
a
=
{
ok
:
true
,
id
:
command
.
getDocId
(),
rev
:
revision
||
current_revision
};
am
.
neverCall
(
o
,
'
error
'
);
am
.
neverCall
(
o
,
'
success
'
);
if
(
command
.
getOption
(
'
revs
'
))
{
a
.
revisions
=
priv
.
_revs
(
metadata_file_content
,
current_revision
);
}
if
(
command
.
getOption
(
'
revs_info
'
))
{
a
.
revs_info
=
priv
.
_revs_info
(
metadata_file_content
);
}
if
(
command
.
getOption
(
'
conflicts
'
))
{
a
.
conflicts
=
conflict_object
;
}
that
.
success
(
a
);
};
o
.
error
=
function
(
error
)
{
var
err
=
error
||
failerror
||
{
status
:
0
,
statusText
:
'
Unknown
'
,
error
:
'
unknown_error
'
,
message
:
'
Unknown error.
'
,
reason
:
'
unknown error
'
};
if
(
current_revision
)
{
err
.
rev
=
current_revision
;
}
if
(
command
.
getOption
(
'
revs
'
))
{
err
.
revisions
=
priv
.
_revs
(
metadata_file_content
,
current_revision
);
}
if
(
command
.
getOption
(
'
revs_info
'
))
{
err
.
revs_info
=
priv
.
_revs_info
(
metadata_file_content
);
}
if
(
command
.
getOption
(
'
conflicts
'
))
{
err
.
conflicts
=
conflict_object
;
}
am
.
neverCall
(
o
,
'
error
'
);
am
.
neverCall
(
o
,
'
success
'
);
that
.
error
(
err
);
};
am
.
call
(
o
,
'
getDistantMetadata
'
);
};
// end remove
return
that
;
});
src/jio.storage/davstorage.js
deleted
100644 → 0
View file @
3356688e
/*
* Copyright 2013, Nexedi SA
* Released under the LGPL license.
* http://www.gnu.org/licenses/lgpl.html
*/
/*jslint indent: 2, maxlen: 80, nomen: true */
/*global define, jIO, jQuery, btoa */
// JIO Dav Storage Description :
// {
// type: "dav",
// url: {string}
// }
// {
// type: "dav",
// url: {string},
// auth_type: {string}, (optional)
// - "auto" (default) (not implemented)
// - "basic"
// - "digest" (not implemented)
// realm: {string}, (optional)
// - undefined (default) (not implemented)
// - "<string>" realm name (not implemented)
// username: {string},
// password: {string} (optional)
// }
// {
// type: "dav",
// url: {string},
// encoded_login: {string}
// }
// {
// type: "dav",
// url: {string},
// secured_login: {string} (not implemented)
// }
// NOTE: to get the authentication type ->
// curl --verbose -X OPTION http://domain/
// In the headers: "WWW-Authenticate: Basic realm="DAV-upload"
// URL Characters convertion:
// If I want to retrieve the file which id is -> http://100%.json
// http://domain/collection/http://100%.json cannot be applied
// - '/' is col separator,
// - '?' is url/parameter separator
// - '%' is special char
// - '.' document and attachment separator
// http://100%.json will become
// - http:%2F%2F100%25.json to avoid bad request ('/', '%' -> '%2F', '%25')
// - http:%2F%2F100%25_.json to avoid ids conflicts ('.' -> '_.')
// - http:%252F%252F100%2525_.json to avoid request bad interpretation
// ('%', '%25')
// The file will be saved as http:%2F%2F100%25_.json
// define([module_name], [dependencies], module);
(
function
(
dependencies
,
module
)
{
"
use strict
"
;
if
(
typeof
define
===
'
function
'
&&
define
.
amd
)
{
return
define
(
dependencies
,
module
);
}
module
(
jIO
,
jQuery
);
}([
'
jio
'
,
'
jquery
'
],
function
(
jIO
,
$
)
{
"
use strict
"
;
jIO
.
addStorageType
(
"
dav
"
,
function
(
spec
,
my
)
{
var
priv
=
{},
that
=
my
.
basicStorage
(
spec
,
my
),
dav
=
{};
// ATTRIBUTES //
priv
.
url
=
null
;
priv
.
username
=
null
;
priv
.
password
=
null
;
priv
.
encoded_login
=
null
;
// CONSTRUCTOR //
/**
* Init the dav storage connector thanks to the description
* @method __init__
* @param {object} description The description object
*/
priv
.
__init__
=
function
(
description
)
{
priv
.
url
=
description
.
url
||
""
;
priv
.
url
=
priv
.
removeSlashIfLast
(
priv
.
url
);
// if (description.secured_login) {
// not implemented
// } else
if
(
description
.
encoded_login
)
{
priv
.
encoded_login
=
description
.
encoded_login
;
}
else
if
(
description
.
auth_type
)
{
if
(
description
.
auth_type
===
"
basic
"
)
{
priv
.
encoded_login
=
"
Basic
"
+
btoa
((
description
.
username
||
""
)
+
"
:
"
+
(
description
.
password
||
""
));
}
}
else
{
priv
.
encoded_login
=
""
;
}
};
// OVERRIDES //
that
.
specToStore
=
function
()
{
// TODO: secured password
// The encoded_login can be seen by anyone,
// we must find a way to secure it!
// secured_login = encrypt(encoded_login)
// encoded_login = decrypt(secured_login)
return
{
"
url
"
:
priv
.
url
,
"
encoded_login
"
:
priv
.
encoded_login
};
};
that
.
validateState
=
function
()
{
if
(
typeof
priv
.
url
!==
"
string
"
||
priv
.
url
===
""
)
{
return
"
The webDav server URL is not provided
"
;
}
if
(
priv
.
encoded_login
===
null
)
{
return
"
Impossible to create the authorization
"
;
}
return
""
;
};
// TOOLS //
/**
* Generate a new uuid
* @method generateUuid
* @return {string} The new uuid
*/
priv
.
generateUuid
=
function
()
{
var
S4
=
function
()
{
/* 65536 */
var
i
,
string
=
Math
.
floor
(
Math
.
random
()
*
0x10000
).
toString
(
16
);
for
(
i
=
string
.
length
;
i
<
4
;
i
+=
1
)
{
string
=
"
0
"
+
string
;
}
return
string
;
};
return
S4
()
+
S4
()
+
"
-
"
+
S4
()
+
"
-
"
+
S4
()
+
"
-
"
+
S4
()
+
"
-
"
+
S4
()
+
S4
()
+
S4
();
};
// /**
// * Clones an object in deep
// * @method clone
// * @param {object} object The object to clone
// * @return {object} The cloned object
// */
// priv.clone = function (object) {
// var tmp = JSON.stringify(object);
// if (tmp === undefined) {
// return undefined;
// }
// return JSON.parse(tmp);
// };
/**
* Replace substrings to another strings
* @method recursiveReplace
* @param {string} string The string to do replacement
* @param {array} list_of_replacement An array of couple
* ["substring to select", "selected substring replaced by this string"].
* @return {string} The replaced string
*/
priv
.
recursiveReplace
=
function
(
string
,
list_of_replacement
)
{
var
i
,
split_string
=
string
.
split
(
list_of_replacement
[
0
][
0
]);
if
(
list_of_replacement
[
1
])
{
for
(
i
=
0
;
i
<
split_string
.
length
;
i
+=
1
)
{
split_string
[
i
]
=
priv
.
recursiveReplace
(
split_string
[
i
],
list_of_replacement
.
slice
(
1
)
);
}
}
return
split_string
.
join
(
list_of_replacement
[
0
][
1
]);
};
/**
* Changes spaces to %20, / to %2f, % to %25 and ? to %3f
* @method secureName
* @param {string} name The name to secure
* @return {string} The secured name
*/
priv
.
secureName
=
function
(
name
)
{
return
priv
.
recursiveReplace
(
name
,
[
[
"
"
,
"
%20
"
],
[
"
/
"
,
"
%2F
"
],
[
"
%
"
,
"
%25
"
],
[
"
?
"
,
"
%3F
"
]
]);
};
/**
* Restores the original name from a secured name
* @method restoreName
* @param {string} secured_name The secured name to restore
* @return {string} The original name
*/
priv
.
restoreName
=
function
(
secured_name
)
{
return
priv
.
recursiveReplace
(
secured_name
,
[
[
"
%20
"
,
"
"
],
[
"
%2F
"
,
"
/
"
],
[
"
%25
"
,
"
%
"
],
[
"
%3F
"
,
"
?
"
]
]);
};
/**
* Convert document id and attachment id to a file name
* @method idsToFileName
* @param {string} doc_id The document id
* @param {string} attachment_id The attachment id (optional)
* @return {string} The file name
*/
priv
.
idsToFileName
=
function
(
doc_id
,
attachment_id
)
{
doc_id
=
priv
.
secureName
(
doc_id
).
split
(
"
.
"
).
join
(
"
_.
"
);
if
(
typeof
attachment_id
===
"
string
"
)
{
attachment_id
=
priv
.
secureName
(
attachment_id
).
split
(
"
.
"
).
join
(
"
_.
"
);
return
doc_id
+
"
.
"
+
attachment_id
;
}
return
doc_id
;
};
/**
* Convert a file name to a document id (and attachment id if there)
* @method fileNameToIds
* @param {string} file_name The file name to convert
* @return {array} ["document id", "attachment id"] or ["document id"]
*/
priv
.
fileNameToIds
=
function
(
file_name
)
{
var
separator_index
=
-
1
,
split
=
file_name
.
split
(
"
.
"
);
split
.
slice
(
0
,
-
1
).
forEach
(
function
(
file_name_part
,
index
)
{
if
(
file_name_part
.
slice
(
-
1
)
!==
"
_
"
)
{
if
(
separator_index
!==
-
1
)
{
separator_index
=
new
TypeError
(
"
Corrupted file name
"
);
separator_index
.
status
=
24
;
throw
separator_index
;
}
separator_index
=
index
;
}
});
if
(
separator_index
===
-
1
)
{
return
[
priv
.
restoreName
(
priv
.
restoreName
(
file_name
).
split
(
"
_.
"
).
join
(
"
.
"
))];
}
return
[
priv
.
restoreName
(
priv
.
restoreName
(
split
.
slice
(
0
,
separator_index
+
1
).
join
(
"
.
"
)
).
split
(
"
_.
"
).
join
(
"
.
"
)),
priv
.
restoreName
(
priv
.
restoreName
(
split
.
slice
(
separator_index
+
1
).
join
(
"
.
"
)
).
split
(
"
_.
"
).
join
(
"
.
"
))
];
};
/**
* Removes the last character if it is a "/". "/a/b/c/" become "/a/b/c"
* @method removeSlashIfLast
* @param {string} string The string to modify
* @return {string} The modified string
*/
priv
.
removeSlashIfLast
=
function
(
string
)
{
if
(
string
[
string
.
length
-
1
]
===
"
/
"
)
{
return
string
.
slice
(
0
,
-
1
);
}
return
string
;
};
/**
* Modify an ajax object to add default values
* @method makeAjaxObject
* @param {string} file_name The file name to add to the url
* @param {object} ajax_object The ajax object to override
* @return {object} A new ajax object with default values
*/
priv
.
makeAjaxObject
=
function
(
file_name
,
method
,
ajax_object
)
{
ajax_object
.
type
=
method
||
ajax_object
.
type
||
"
GET
"
;
ajax_object
.
url
=
priv
.
url
+
"
/
"
+
priv
.
secureName
(
file_name
)
+
"
?_=
"
+
Date
.
now
();
ajax_object
.
async
=
ajax_object
.
async
===
false
?
false
:
true
;
ajax_object
.
crossdomain
=
ajax_object
.
crossdomain
===
false
?
false
:
true
;
ajax_object
.
headers
=
ajax_object
.
headers
||
{};
ajax_object
.
headers
.
Authorization
=
ajax_object
.
headers
.
Authorization
||
priv
.
encoded_login
;
return
ajax_object
;
};
/**
* Runs all ajax requests for davStorage
* @method ajax
* @param {string} doc_id The document id
* @param {string} attachment_id The attachment id, can be undefined
* @param {string} method The request method
* @param {object} ajax_object The request parameters (optional)
*/
priv
.
ajax
=
function
(
doc_id
,
attachment_id
,
method
,
ajax_object
)
{
var
new_ajax_object
=
JSON
.
parse
(
JSON
.
stringify
(
ajax_object
)
||
"
{}
"
);
return
$
.
ajax
(
priv
.
makeAjaxObject
(
priv
.
idsToFileName
(
doc_id
||
''
,
attachment_id
),
method
,
new_ajax_object
));
//.always(then || function () {});
};
/**
* Creates error objects for this storage
* @method createError
* @param {string} url url to clean up
* @return {object} error The error object
*/
priv
.
createError
=
function
(
status
,
message
,
reason
)
{
var
error
=
{
"
status
"
:
status
,
"
message
"
:
message
,
"
reason
"
:
reason
};
switch
(
status
)
{
case
404
:
error
.
statusText
=
"
Not found
"
;
break
;
case
405
:
error
.
statusText
=
"
Method Not Allowed
"
;
break
;
case
409
:
error
.
statusText
=
"
Conflicts
"
;
break
;
case
24
:
error
.
statusText
=
"
Corrupted Document
"
;
break
;
}
error
.
error
=
error
.
statusText
.
toLowerCase
().
split
(
"
"
).
join
(
"
_
"
);
return
error
;
};
/**
* Converts ajax error object to a JIO error object
* @method ajaxErrorToJioError
* @param {object} ajax_error_object The ajax error object
* @param {string} message The error message
* @param {string} reason The error reason
* @return {object} The JIO error object
*/
priv
.
ajaxErrorToJioError
=
function
(
ajax_error_object
,
message
,
reason
)
{
var
jio_error_object
=
{};
jio_error_object
.
status
=
ajax_error_object
.
status
;
jio_error_object
.
statusText
=
ajax_error_object
.
statusText
;
jio_error_object
.
error
=
ajax_error_object
.
statusText
.
toLowerCase
().
split
(
"
"
).
join
(
"
_
"
);
jio_error_object
.
message
=
message
;
jio_error_object
.
reason
=
reason
;
return
jio_error_object
;
};
/**
* Function that create an object containing jQuery like callbacks
* @method makeJQLikeCallback
* @return {object} jQuery like callback methods
*/
priv
.
makeJQLikeCallback
=
function
()
{
var
result
=
null
,
emptyFun
=
function
()
{},
jql
=
{
"
respond
"
:
function
()
{
result
=
arguments
;
},
"
to_return
"
:
{
"
always
"
:
function
(
func
)
{
if
(
result
)
{
func
.
apply
(
func
,
result
);
jql
.
to_return
.
always
=
emptyFun
;
}
else
{
jql
.
respond
=
func
;
}
return
jql
.
to_return
;
},
"
then
"
:
function
(
func
)
{
if
(
result
)
{
func
(
result
[
1
]);
jql
.
to_return
.
then
=
emptyFun
;
}
else
{
jql
.
respond
=
function
(
err
,
response
)
{
func
(
response
);
};
}
return
jql
.
to_return
;
}
}
};
return
jql
;
};
// DAV REQUESTS //
/**
* Retrieve a document file
* @method dav.getDocument
* @param {string} doc_id The document id
*/
dav
.
getDocument
=
function
(
doc_id
)
{
var
doc
,
jql
=
priv
.
makeJQLikeCallback
(),
error
=
null
;
priv
.
ajax
(
doc_id
,
undefined
,
"
GET
"
).
always
(
function
(
one
,
state
,
three
)
{
if
(
state
!==
"
success
"
)
{
error
=
priv
.
ajaxErrorToJioError
(
one
,
"
Cannot retrieve document
"
,
"
Unknown
"
);
if
(
one
.
status
===
404
)
{
error
.
reason
=
"
Not Found
"
;
}
return
jql
.
respond
(
error
,
undefined
);
}
try
{
doc
=
JSON
.
parse
(
one
);
}
catch
(
e
)
{
return
jql
.
respond
(
priv
.
createError
(
24
,
"
Cannot parse document
"
,
"
Document is corrupted
"
),
undefined
);
}
// document health is good
return
jql
.
respond
(
undefined
,
doc
);
});
return
jql
.
to_return
;
};
/**
* Retrieve an attachment file
* @method dav.getAttachment
* @param {string} doc_id The document id
* @param {string} attachment_id The attachment id
*/
dav
.
getAttachment
=
function
(
doc_id
,
attachment_id
)
{
var
jql
=
priv
.
makeJQLikeCallback
(),
error
=
null
;
priv
.
ajax
(
doc_id
,
attachment_id
,
"
GET
"
).
always
(
function
(
one
,
state
,
three
)
{
if
(
state
!==
"
success
"
)
{
error
=
priv
.
ajaxErrorToJioError
(
one
,
"
Cannot retrieve attachment
"
,
"
Unknown
"
);
if
(
one
.
status
===
404
)
{
error
.
reason
=
"
Not Found
"
;
}
return
jql
.
respond
(
error
,
undefined
);
}
return
jql
.
respond
(
undefined
,
one
);
});
return
jql
.
to_return
;
};
/**
* Uploads a document file
* @method dav.putDocument
* @param {object} doc The document object
*/
dav
.
putDocument
=
function
(
doc
)
{
var
jql
=
priv
.
makeJQLikeCallback
();
priv
.
ajax
(
doc
.
_id
,
undefined
,
"
PUT
"
,
{
"
dataType
"
:
"
text
"
,
"
data
"
:
JSON
.
stringify
(
doc
)
}).
always
(
function
(
one
,
state
,
three
)
{
if
(
state
!==
"
success
"
)
{
return
jql
.
respond
(
priv
.
ajaxErrorToJioError
(
one
,
"
Cannot upload document
"
,
"
Unknown
"
),
undefined
);
}
jql
.
respond
(
undefined
,
{
"
ok
"
:
true
,
"
id
"
:
doc
.
_id
});
});
return
jql
.
to_return
;
};
/**
* Uploads an attachment file
* @method dav.putAttachment
* @param {string} doc_id The document id
* @param {string} attachment_id The attachment id
* @param {string} data The attachment data
*/
dav
.
putAttachment
=
function
(
doc_id
,
attachment_id
,
data
)
{
var
jql
=
priv
.
makeJQLikeCallback
();
priv
.
ajax
(
doc_id
,
attachment_id
,
"
PUT
"
,
{
"
dataType
"
:
"
text
"
,
"
data
"
:
data
}).
always
(
function
(
one
,
state
,
three
)
{
if
(
state
!==
"
success
"
)
{
return
jql
.
respond
(
priv
.
ajaxErrorToJioError
(
one
,
"
Cannot upload attachment
"
,
"
Unknown
"
),
undefined
);
}
return
jql
.
respond
(
undefined
,
{
"
ok
"
:
true
,
"
id
"
:
doc_id
,
"
attachment
"
:
attachment_id
});
});
return
jql
.
to_return
;
};
/**
* Deletes a document file
* @method dav.removeDocument
* @param {string} doc_id The document id
*/
dav
.
removeDocument
=
function
(
doc_id
)
{
var
jql
=
priv
.
makeJQLikeCallback
(),
error
=
null
;
priv
.
ajax
(
doc_id
,
undefined
,
"
DELETE
"
).
always
(
function
(
one
,
state
,
three
)
{
if
(
state
!==
"
success
"
)
{
error
=
priv
.
ajaxErrorToJioError
(
one
,
"
Cannot delete document
"
,
"
Unknown
"
);
if
(
one
.
status
===
404
)
{
error
.
reason
=
"
Not Found
"
;
}
return
jql
.
respond
(
error
,
undefined
);
}
jql
.
respond
(
undefined
,
{
"
ok
"
:
true
,
"
id
"
:
doc_id
});
});
return
jql
.
to_return
;
};
/**
* Deletes an attachment file
* @method dav.removeAttachment
* @param {string} doc_id The document id
* @param {string} attachment_id The attachment id
*/
dav
.
removeAttachment
=
function
(
doc_id
,
attachment_id
)
{
var
jql
=
priv
.
makeJQLikeCallback
(),
error
=
null
;
priv
.
ajax
(
doc_id
,
attachment_id
,
"
DELETE
"
).
always
(
function
(
one
,
state
,
three
)
{
if
(
state
!==
"
success
"
)
{
error
=
priv
.
ajaxErrorToJioError
(
one
,
"
Cannot delete attachment
"
,
"
Unknown
"
);
if
(
one
.
status
===
404
)
{
error
.
reason
=
"
Not Found
"
;
}
return
jql
.
respond
(
error
,
undefined
);
}
jql
.
respond
(
undefined
,
{
"
ok
"
:
true
,
"
id
"
:
doc_id
});
});
return
jql
.
to_return
;
};
/**
* Get a list of document file
* @method dav.allDocs
*/
dav
.
allDocs
=
function
()
{
var
jql
=
priv
.
makeJQLikeCallback
(),
rows
=
[];
priv
.
ajax
(
undefined
,
undefined
,
"
PROPFIND
"
,
{
"
dataType
"
:
"
xml
"
,
"
headers
"
:
{
"
Depth
"
:
1
}
}).
always
(
function
(
one
,
state
,
three
)
{
var
response
,
len
;
if
(
state
!==
"
success
"
)
{
return
jql
.
respond
(
priv
.
ajaxErrorToJioError
(
one
,
"
Cannot get the document list
"
,
"
Unknown
"
),
undefined
);
}
response
=
$
(
one
).
find
(
"
D
\\
:response, response
"
);
len
=
response
.
length
;
if
(
len
===
1
)
{
return
jql
.
respond
({
"
total_rows
"
:
0
,
"
rows
"
:
[]});
}
response
.
each
(
function
(
i
,
data
)
{
var
row
;
if
(
i
>
0
)
{
// exclude parent folder
row
=
{
"
id
"
:
""
,
"
key
"
:
""
,
"
value
"
:
{}
};
$
(
data
).
find
(
"
D
\\
:href, href
"
).
each
(
function
()
{
row
.
id
=
$
(
this
).
text
().
split
(
'
/
'
).
slice
(
-
1
)[
0
];
try
{
row
.
id
=
priv
.
fileNameToIds
(
row
.
id
);
}
catch
(
e
)
{
if
(
e
.
name
===
"
TypeError
"
&&
e
.
status
===
24
)
{
return
;
}
throw
e
;
}
if
(
row
.
id
.
length
!==
1
)
{
row
=
undefined
;
}
else
{
row
.
id
=
row
.
id
[
0
];
row
.
key
=
row
.
id
;
}
});
if
(
row
!==
undefined
)
{
rows
.
push
(
row
);
}
}
});
jql
.
respond
(
undefined
,
{
"
total_rows
"
:
rows
.
length
,
"
rows
"
:
rows
});
});
return
jql
.
to_return
;
};
// JIO COMMANDS //
// wedDav methods rfc4918 (short summary)
// COPY Reproduces single resources (files) and collections (directory
// trees). Will overwrite files (if specified by request) but will
// respond 209 (Conflict) if it would overwrite a tree
// DELETE deletes files and directory trees
// GET just the vanilla HTTP/1.1 behaviour
// HEAD ditto
// LOCK locks a resources
// MKCOL creates a directory
// MOVE Moves (rename or copy) a file or a directory tree. Will
// 'overwrite' files (if specified by the request) but will respond
// 209 (Conflict) if it would overwrite a tree.
// OPTIONS If WebDAV is enabled and available for the path this reports the
// WebDAV extension methods
// PROPFIND Retrieves the requested file characteristics, DAV lock status
// and 'dead' properties for individual files, a directory and its
// child files, or a directory tree
// PROPPATCHset and remove 'dead' meta-data properties
// PUT Update or create resource or collections
// UNLOCK unlocks a resource
// Notes: all Ajax requests should be CORS (cross-domain)
// adding custom headers triggers preflight OPTIONS request!
// http://remysharp.com/2011/04/21/getting-cors-working/
/**
* Creates a new document
* @method post
* @param {object} command The JIO command
*/
that
.
post
=
function
(
command
)
{
var
doc_id
=
command
.
getDocId
()
||
priv
.
generateUuid
();
dav
.
getDocument
(
doc_id
).
always
(
function
(
err
,
response
)
{
if
(
err
)
{
if
(
err
.
status
===
404
)
{
// the document does not already exist
// updating document
var
doc
=
command
.
cloneDoc
();
doc
.
_id
=
doc_id
;
return
dav
.
putDocument
(
doc
).
always
(
function
(
err
,
response
)
{
if
(
err
)
{
return
that
.
retry
(
err
);
}
return
that
.
success
(
response
);
});
}
if
(
err
.
status
===
24
)
{
return
that
.
error
(
err
);
}
// an error occured
return
that
.
retry
(
err
);
}
// the document already exists
return
that
.
error
(
priv
.
createError
(
405
,
"
Cannot create document
"
,
"
Document already exists
"
));
});
};
/**
* Creates or updates a document
* @method put
* @param {object} command The JIO command
*/
that
.
put
=
function
(
command
)
{
dav
.
putDocument
(
command
.
cloneDoc
()).
always
(
function
(
err
,
response
)
{
if
(
err
)
{
// an error occured
return
that
.
retry
(
err
);
}
// document updated
return
that
.
success
(
response
);
});
};
/**
* Add an attachment to a document
* @method putAttachment
* @param {object} command The JIO command
*/
that
.
putAttachment
=
function
(
command
)
{
var
doc
=
null
,
doc_id
=
command
.
getDocId
(),
attachment_id
,
tmp
;
attachment_id
=
command
.
getAttachmentId
();
dav
.
getDocument
(
doc_id
).
always
(
function
(
err
,
response
)
{
if
(
err
)
{
// document not found or error
tmp
=
that
.
retry
;
if
(
err
.
status
===
404
||
err
.
status
===
24
)
{
tmp
=
that
.
error
;
}
return
tmp
(
err
);
}
doc
=
response
;
doc
.
_attachments
=
doc
.
_attachments
||
{};
doc
.
_attachments
[
attachment_id
]
=
{
"
length
"
:
command
.
getAttachmentLength
(),
"
digest
"
:
"
md5-
"
+
command
.
md5SumAttachmentData
(),
"
content_type
"
:
command
.
getAttachmentMimeType
()
};
// put the attachment
dav
.
putAttachment
(
doc_id
,
attachment_id
,
command
.
getAttachmentData
()
).
always
(
function
(
err
,
response
)
{
if
(
err
)
{
// an error occured
return
that
.
retry
(
err
);
}
// update the document
dav
.
putDocument
(
doc
).
always
(
function
(
err
,
response
)
{
if
(
err
)
{
return
that
.
retry
(
err
);
}
response
.
attachment
=
attachment_id
;
return
that
.
success
(
response
);
});
});
});
};
/**
* Get a document
* @method get
* @param {object} command The JIO command
*/
that
.
get
=
function
(
command
)
{
dav
.
getDocument
(
command
.
getDocId
()).
always
(
function
(
err
,
response
)
{
if
(
err
)
{
if
(
err
.
status
===
404
||
err
.
status
===
24
)
{
return
that
.
error
(
err
);
}
return
that
.
retry
(
err
);
}
return
that
.
success
(
response
);
});
};
/**
* Get an attachment
* @method getAttachment
* @param {object} command The JIO command
*/
that
.
getAttachment
=
function
(
command
)
{
dav
.
getAttachment
(
command
.
getDocId
(),
command
.
getAttachmentId
()
).
always
(
function
(
err
,
response
)
{
if
(
err
)
{
if
(
err
.
status
===
404
)
{
return
that
.
error
(
err
);
}
return
that
.
retry
(
err
);
}
return
that
.
success
(
response
);
});
};
/**
* Remove a document
* @method remove
* @param {object} command The JIO command
*/
that
.
remove
=
function
(
command
)
{
var
doc_id
=
command
.
getDocId
(),
count
=
0
,
end
;
end
=
function
()
{
count
-=
1
;
if
(
count
===
0
)
{
that
.
success
({
"
ok
"
:
true
,
"
id
"
:
doc_id
});
}
};
dav
.
getDocument
(
doc_id
).
always
(
function
(
err
,
response
)
{
var
attachment_id
=
null
;
if
(
err
)
{
if
(
err
.
status
===
404
)
{
return
that
.
error
(
err
);
}
if
(
err
.
status
!==
24
)
{
// 24 -> corrupted document
return
that
.
retry
(
err
);
}
response
=
{};
}
count
+=
2
;
dav
.
removeDocument
(
doc_id
).
always
(
function
(
err
,
response
)
{
if
(
err
)
{
if
(
err
.
status
===
404
)
{
return
that
.
error
(
err
);
}
return
that
.
retry
(
err
);
}
return
end
();
});
for
(
attachment_id
in
response
.
_attachments
)
{
if
(
response
.
_attachments
.
hasOwnProperty
(
attachment_id
))
{
count
+=
1
;
dav
.
removeAttachment
(
doc_id
,
attachment_id
).
always
(
end
);
}
}
end
();
});
};
/**
* Remove an attachment
* @method removeAttachment
* @param {object} command The JIO command
*/
that
.
removeAttachment
=
function
(
command
)
{
var
doc_id
=
command
.
getDocId
(),
doc
,
attachment_id
;
attachment_id
=
command
.
getAttachmentId
();
dav
.
getDocument
(
doc_id
).
always
(
function
(
err
,
response
)
{
var
still_has_attachments
;
if
(
err
)
{
if
(
err
.
status
===
404
||
err
.
status
===
24
)
{
return
that
.
error
(
err
);
}
return
that
.
retry
(
err
);
}
doc
=
response
;
if
(
typeof
(
doc
.
_attachments
||
{})[
attachment_id
]
!==
"
object
"
)
{
return
that
.
error
(
priv
.
createError
(
404
,
"
Cannot remove attachment
"
,
"
Not Found
"
));
}
delete
doc
.
_attachments
[
attachment_id
];
// check if there is still attachments
for
(
still_has_attachments
in
doc
.
_attachments
)
{
if
(
doc
.
_attachments
.
hasOwnProperty
(
still_has_attachments
))
{
break
;
}
}
if
(
still_has_attachments
===
undefined
)
{
delete
doc
.
_attachments
;
}
doc
.
_id
=
doc_id
;
dav
.
putDocument
(
doc
).
always
(
function
(
err
,
response
)
{
if
(
err
)
{
return
that
.
retry
(
err
);
}
dav
.
removeAttachment
(
doc_id
,
attachment_id
).
always
(
function
(
err
,
response
)
{
that
.
success
({
"
ok
"
:
true
,
"
id
"
:
doc_id
,
"
attachment
"
:
attachment_id
});
});
});
});
};
/**
* Gets a document list from a distant dav storage
* Options:
* - {boolean} include_docs Also retrieve the actual document content.
* @method allDocs
* @param {object} command The JIO command
*/
that
.
allDocs
=
function
(
command
)
{
var
count
=
0
,
end
,
rows
;
end
=
function
()
{
count
-=
1
;
if
(
count
===
0
)
{
that
.
success
(
rows
);
}
};
dav
.
allDocs
().
always
(
function
(
err
,
response
)
{
if
(
err
)
{
return
that
.
retry
(
err
);
}
if
(
command
.
getOption
(
"
include_docs
"
)
===
true
)
{
count
+=
1
;
rows
=
response
;
rows
.
rows
.
forEach
(
function
(
row
)
{
count
+=
1
;
dav
.
getDocument
(
row
.
id
).
always
(
function
(
err
,
response
)
{
if
(
err
)
{
if
(
err
.
status
===
404
||
err
.
status
===
24
)
{
return
that
.
error
(
err
);
}
return
that
.
retry
(
err
);
}
row
.
doc
=
response
;
end
();
});
});
end
();
}
else
{
that
.
success
(
response
);
}
});
};
priv
.
__init__
(
spec
);
return
that
;
});
}));
src/jio.storage/ramstorage.js
deleted
100644 → 0
View file @
3356688e
/*
* Copyright 2013, Nexedi SA
* Released under the LGPL license.
* http://www.gnu.org/licenses/lgpl.html
*/
/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */
/*global define, jIO, setTimeout, complex_queries */
// define([module_name], [dependencies], module);
(
function
(
dependencies
,
module
)
{
"
use strict
"
;
if
(
typeof
define
===
'
function
'
&&
define
.
amd
)
{
return
define
(
dependencies
,
module
);
}
module
(
jIO
);
}([
'
jio
'
],
function
(
jIO
)
{
var
storage
=
{};
/**
* Returns 4 hexadecimal random characters.
*
* @return {String} The characters
*/
function
S4
()
{
return
(
'
0000
'
+
Math
.
floor
(
Math
.
random
()
*
0x10000
/* 65536 */
).
toString
(
16
)).
slice
(
-
4
);
}
/**
* An Universal Unique ID generator
*
* @return {String} The new UUID.
*/
function
generateUuid
()
{
return
S4
()
+
S4
()
+
"
-
"
+
S4
()
+
"
-
"
+
S4
()
+
"
-
"
+
S4
()
+
"
-
"
+
S4
()
+
S4
()
+
S4
();
}
/**
* Checks if an object has no enumerable keys
*
* @param {Object} obj The object
* @return {Boolean} true if empty, else false
*/
function
objectIsEmpty
(
obj
)
{
var
k
;
for
(
k
in
obj
)
{
if
(
obj
.
hasOwnProperty
(
k
))
{
return
false
;
}
}
return
true
;
}
/**
* JIO Ram Storage. Type = 'ram'.
* Memory "database" storage.
*
* Storage Description:
*
* {
* "type": "ram",
* "namespace": <string>, // default 'default'
* }
*
* Document are stored in path
* 'namespace/document_id' like this:
*
* {
* "_id": "document_id",
* "_attachments": {
* "attachment_name": {
* "length": data_length,
* "digest": "md5-XXX",
* "content_type": "mime/type"
* },
* "attachment_name2": {..}, ...
* },
* "metadata_name": "metadata_value"
* "metadata_name2": ...
* ...
* }
*
* Only "_id" and "_attachments" are specific metadata keys, other one can be
* added without loss.
*
* @class RamStorage
*/
function
ramStorage
(
spec
,
my
)
{
var
that
,
priv
=
{},
ramstorage
;
that
=
my
.
basicStorage
(
spec
,
my
);
/*
* Wrapper for the localStorage used to simplify instion of any kind of
* values
*/
ramstorage
=
{
getItem
:
function
(
item
)
{
var
value
=
storage
[
item
];
return
value
===
undefined
?
null
:
JSON
.
parse
(
value
);
},
setItem
:
function
(
item
,
value
)
{
storage
[
item
]
=
JSON
.
stringify
(
value
);
},
removeItem
:
function
(
item
)
{
delete
storage
[
item
];
}
};
// attributes
if
(
typeof
spec
.
namespace
!==
'
string
'
)
{
priv
.
namespace
=
'
default
'
;
}
else
{
priv
.
namespace
=
spec
.
namespace
;
}
// ===================== overrides ======================
that
.
specToStore
=
function
()
{
return
{
"
namespace
"
:
priv
.
namespace
};
};
that
.
validateState
=
function
()
{
return
''
;
};
// ==================== commands ====================
/**
* Create a document in local storage.
* @method post
* @param {object} command The JIO command
*/
that
.
post
=
function
(
command
)
{
setTimeout
(
function
()
{
var
doc
,
doc_id
=
command
.
getDocId
();
if
(
!
doc_id
)
{
doc_id
=
generateUuid
();
}
doc
=
ramstorage
.
getItem
(
priv
.
namespace
+
"
/
"
+
doc_id
);
if
(
doc
===
null
)
{
// the document does not exist
doc
=
command
.
cloneDoc
();
doc
.
_id
=
doc_id
;
delete
doc
.
_attachments
;
ramstorage
.
setItem
(
priv
.
namespace
+
"
/
"
+
doc_id
,
doc
);
that
.
success
({
"
ok
"
:
true
,
"
id
"
:
doc_id
});
}
else
{
// the document already exists
that
.
error
({
"
status
"
:
409
,
"
statusText
"
:
"
Conflicts
"
,
"
error
"
:
"
conflicts
"
,
"
message
"
:
"
Cannot create a new document
"
,
"
reason
"
:
"
Document already exists
"
});
}
});
};
/**
* Create or update a document in local storage.
* @method put
* @param {object} command The JIO command
*/
that
.
put
=
function
(
command
)
{
setTimeout
(
function
()
{
var
doc
,
tmp
;
doc
=
ramstorage
.
getItem
(
priv
.
namespace
+
"
/
"
+
command
.
getDocId
());
if
(
doc
===
null
)
{
// the document does not exist
doc
=
command
.
cloneDoc
();
delete
doc
.
_attachments
;
}
else
{
// the document already exists
tmp
=
command
.
cloneDoc
();
tmp
.
_attachments
=
doc
.
_attachments
;
doc
=
tmp
;
}
// write
ramstorage
.
setItem
(
priv
.
namespace
+
"
/
"
+
command
.
getDocId
(),
doc
);
that
.
success
({
"
ok
"
:
true
,
"
id
"
:
command
.
getDocId
()
});
});
};
/**
* Add an attachment to a document
* @method putAttachment
* @param {object} command The JIO command
*/
that
.
putAttachment
=
function
(
command
)
{
setTimeout
(
function
()
{
var
doc
;
doc
=
ramstorage
.
getItem
(
priv
.
namespace
+
"
/
"
+
command
.
getDocId
());
if
(
doc
===
null
)
{
// the document does not exist
that
.
error
({
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
,
"
error
"
:
"
not_found
"
,
"
message
"
:
"
Impossible to add attachment
"
,
"
reason
"
:
"
Document not found
"
});
return
;
}
// the document already exists
doc
.
_attachments
=
doc
.
_attachments
||
{};
doc
.
_attachments
[
command
.
getAttachmentId
()]
=
{
"
content_type
"
:
command
.
getAttachmentMimeType
(),
"
digest
"
:
"
md5-
"
+
command
.
md5SumAttachmentData
(),
"
length
"
:
command
.
getAttachmentLength
()
};
// upload data
ramstorage
.
setItem
(
priv
.
namespace
+
"
/
"
+
command
.
getDocId
()
+
"
/
"
+
command
.
getAttachmentId
(),
command
.
getAttachmentData
());
// write document
ramstorage
.
setItem
(
priv
.
namespace
+
"
/
"
+
command
.
getDocId
(),
doc
);
that
.
success
({
"
ok
"
:
true
,
"
id
"
:
command
.
getDocId
(),
"
attachment
"
:
command
.
getAttachmentId
()
});
});
};
/**
* Get a document
* @method get
* @param {object} command The JIO command
*/
that
.
get
=
function
(
command
)
{
setTimeout
(
function
()
{
var
doc
=
ramstorage
.
getItem
(
priv
.
namespace
+
"
/
"
+
command
.
getDocId
());
if
(
doc
!==
null
)
{
that
.
success
(
doc
);
}
else
{
that
.
error
({
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
,
"
error
"
:
"
not_found
"
,
"
message
"
:
"
Cannot find the document
"
,
"
reason
"
:
"
Document does not exist
"
});
}
});
};
/**
* Get a attachment
* @method getAttachment
* @param {object} command The JIO command
*/
that
.
getAttachment
=
function
(
command
)
{
setTimeout
(
function
()
{
var
doc
=
ramstorage
.
getItem
(
priv
.
namespace
+
"
/
"
+
command
.
getDocId
()
+
"
/
"
+
command
.
getAttachmentId
());
if
(
doc
!==
null
)
{
that
.
success
(
doc
);
}
else
{
that
.
error
({
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
,
"
error
"
:
"
not_found
"
,
"
message
"
:
"
Cannot find the attachment
"
,
"
reason
"
:
"
Attachment does not exist
"
});
}
});
};
/**
* Remove a document
* @method remove
* @param {object} command The JIO command
*/
that
.
remove
=
function
(
command
)
{
setTimeout
(
function
()
{
var
doc
,
i
,
attachment_list
;
doc
=
ramstorage
.
getItem
(
priv
.
namespace
+
"
/
"
+
command
.
getDocId
());
attachment_list
=
[];
if
(
doc
!==
null
&&
typeof
doc
===
"
object
"
)
{
if
(
typeof
doc
.
_attachments
===
"
object
"
)
{
// prepare list of attachments
for
(
i
in
doc
.
_attachments
)
{
if
(
doc
.
_attachments
.
hasOwnProperty
(
i
))
{
attachment_list
.
push
(
i
);
}
}
}
}
else
{
return
that
.
error
({
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
,
"
error
"
:
"
not_found
"
,
"
message
"
:
"
Document not found
"
,
"
reason
"
:
"
missing
"
});
}
ramstorage
.
removeItem
(
priv
.
namespace
+
"
/
"
+
command
.
getDocId
());
// delete all attachments
for
(
i
=
0
;
i
<
attachment_list
.
length
;
i
+=
1
)
{
ramstorage
.
removeItem
(
priv
.
namespace
+
"
/
"
+
command
.
getDocId
()
+
"
/
"
+
attachment_list
[
i
]);
}
that
.
success
({
"
ok
"
:
true
,
"
id
"
:
command
.
getDocId
()
});
});
};
/**
* Remove an attachment
* @method removeAttachment
* @param {object} command The JIO command
*/
that
.
removeAttachment
=
function
(
command
)
{
setTimeout
(
function
()
{
var
doc
,
error
,
i
,
attachment_list
;
error
=
function
(
word
)
{
that
.
error
({
"
status
"
:
404
,
"
statusText
"
:
"
Not Found
"
,
"
error
"
:
"
not_found
"
,
"
message
"
:
word
+
"
not found
"
,
"
reason
"
:
"
missing
"
});
};
doc
=
ramstorage
.
getItem
(
priv
.
namespace
+
"
/
"
+
command
.
getDocId
());
// remove attachment from document
if
(
doc
!==
null
&&
typeof
doc
===
"
object
"
&&
typeof
doc
.
_attachments
===
"
object
"
)
{
if
(
typeof
doc
.
_attachments
[
command
.
getAttachmentId
()]
===
"
object
"
)
{
delete
doc
.
_attachments
[
command
.
getAttachmentId
()];
if
(
priv
.
objectIsEmpty
(
doc
.
_attachments
))
{
delete
doc
.
_attachments
;
}
ramstorage
.
setItem
(
priv
.
namespace
+
"
/
"
+
command
.
getDocId
(),
doc
);
ramstorage
.
removeItem
(
priv
.
namespace
+
"
/
"
+
command
.
getDocId
()
+
"
/
"
+
command
.
getAttachmentId
());
that
.
success
({
"
ok
"
:
true
,
"
id
"
:
command
.
getDocId
(),
"
attachment
"
:
command
.
getAttachmentId
()
});
}
else
{
error
(
"
Attachment
"
);
}
}
else
{
error
(
"
Document
"
);
}
});
};
/**
* Get all filenames belonging to a user from the document index
* @method allDocs
* @param {object} command The JIO command
*/
that
.
allDocs
=
function
(
command
)
{
var
i
,
row
,
path_re
,
rows
=
[],
document_list
,
option
,
document_object
;
document_list
=
[];
path_re
=
new
RegExp
(
"
^
"
+
complex_queries
.
stringEscapeRegexpCharacters
(
priv
.
namespace
)
+
"
/[^/]+$
"
);
option
=
command
.
cloneOption
();
if
(
typeof
complex_queries
!==
"
object
"
||
(
option
.
query
===
undefined
&&
option
.
sort_on
===
undefined
&&
option
.
select_list
===
undefined
&&
option
.
include_docs
===
undefined
))
{
rows
=
[];
for
(
i
in
storage
)
{
if
(
storage
.
hasOwnProperty
(
i
))
{
// filter non-documents
if
(
path_re
.
test
(
i
))
{
row
=
{
"
value
"
:
{}};
row
.
id
=
i
.
split
(
'
/
'
).
slice
(
-
1
)[
0
];
row
.
key
=
row
.
id
;
if
(
command
.
getOption
(
'
include_docs
'
))
{
row
.
doc
=
ramstorage
.
getItem
(
i
);
}
rows
.
push
(
row
);
}
}
}
that
.
success
({
"
rows
"
:
rows
,
"
total_rows
"
:
rows
.
length
});
}
else
{
// create complex query object from returned results
for
(
i
in
storage
)
{
if
(
storage
.
hasOwnProperty
(
i
))
{
if
(
path_re
.
test
(
i
))
{
document_list
.
push
(
ramstorage
.
getItem
(
i
));
}
}
}
option
.
select_list
=
option
.
select_list
||
[];
option
.
select_list
.
push
(
"
_id
"
);
if
(
option
.
include_docs
===
true
)
{
document_object
=
{};
document_list
.
forEach
(
function
(
meta
)
{
document_object
[
meta
.
_id
]
=
meta
;
});
}
complex_queries
.
QueryFactory
.
create
(
option
.
query
||
""
).
exec
(
document_list
,
option
);
document_list
=
document_list
.
map
(
function
(
value
)
{
var
o
=
{
"
id
"
:
value
.
_id
,
"
key
"
:
value
.
_id
};
if
(
option
.
include_docs
===
true
)
{
o
.
doc
=
document_object
[
value
.
_id
];
delete
document_object
[
value
.
_id
];
}
delete
value
.
_id
;
o
.
value
=
value
;
return
o
;
});
that
.
success
({
"
total_rows
"
:
document_list
.
length
,
"
rows
"
:
document_list
});
}
};
return
that
;
}
jIO
.
addStorageType
(
'
ram
'
,
ramStorage
);
}));
test/jio.storage/davstorage.tests.js
deleted
100644 → 0
View file @
3356688e
/*jslint indent: 2, maxlen: 80, nomen: true */
/*global define, jIO, jio_tests, window, test, ok, deepEqual, sinon, expect */
// define([module_name], [dependencies], module);
(
function
(
dependencies
,
module
)
{
"
use strict
"
;
if
(
typeof
define
===
'
function
'
&&
define
.
amd
)
{
return
define
(
dependencies
,
module
);
}
module
(
jIO
,
jio_tests
);
}([
'
jio
'
,
'
jio_tests
'
,
'
davstorage
'
],
function
(
jIO
,
util
)
{
"
use strict
"
;
function
generateTools
()
{
return
{
clock
:
sinon
.
useFakeTimers
(),
spy
:
util
.
ospy
,
tick
:
util
.
otick
};
}
module
(
"
DAVStorage
"
);
test
(
"
Post
"
,
function
()
{
var
o
=
generateTools
(
this
);
o
.
jio
=
jIO
.
newJio
({
"
type
"
:
"
dav
"
,
"
url
"
:
"
https://ca-davstorage:8080
"
,
"
auth_type
"
:
"
basic
"
,
"
username
"
:
"
admin
"
,
"
password
"
:
"
pwd
"
});
// post without id
o
.
server
=
sinon
.
fakeServer
.
create
();
o
.
server
.
respondWith
(
"
GET
"
,
new
RegExp
(
"
https://ca-davstorage:8080/[0-9a-fA-F]{4}
"
),
[
404
,
{
"
Content-Type
"
:
"
text/html
"
},
"
<h1>Document not found</h1>
"
]
);
o
.
server
.
respondWith
(
"
PUT
"
,
new
RegExp
(
"
https://ca-davstorage:8080/[0-9a-fA-F]{4}
"
),
[
200
,
{
"
Content-Type
"
:
"
text/html
"
},
"
<h1>Document updated!</h1>
"
]
);
o
.
spy
(
o
,
"
jobstatus
"
,
"
done
"
,
"
Post without id
"
);
o
.
jio
.
post
({},
{
"
max_retry
"
:
1
},
function
(
err
,
response
)
{
o
.
f
.
apply
(
arguments
);
if
(
response
)
{
ok
(
util
.
isUuid
(
response
.
id
),
"
Uuid should look like
"
+
"
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx :
"
+
response
.
id
);
}
});
o
.
clock
.
tick
(
1000
);
o
.
server
.
respond
();
o
.
tick
(
o
);
o
.
server
.
restore
();
// post document with id
o
.
server
=
sinon
.
fakeServer
.
create
();
o
.
server
.
respondWith
(
"
GET
"
,
new
RegExp
(
"
https://ca-davstorage:8080/http:%252F%252F100%2525_
\\
.json
"
),
[
404
,
{
"
Content-Type
"
:
"
text/html
"
},
"
<h1>Document not found</h1>
"
]
);
o
.
server
.
respondWith
(
"
PUT
"
,
new
RegExp
(
"
https://ca-davstorage:8080/http:%252F%252F100%2525_
\\
.json
"
),
[
200
,
{
"
Content-Type
"
:
"
text/html
"
},
"
<h1>Document updated!</h1>
"
]
);
o
.
spy
(
o
,
"
value
"
,
{
"
id
"
:
"
http://100%.json
"
,
"
ok
"
:
true
},
"
Create document with an id
"
);
o
.
jio
.
post
({
"
_id
"
:
"
http://100%.json
"
,
"
title
"
:
"
Hello There
"
},
{
"
max_retry
"
:
1
},
o
.
f
);
o
.
clock
.
tick
(
1000
);
o
.
server
.
respond
();
o
.
tick
(
o
);
o
.
server
.
restore
();
// post already existant file
o
.
server
=
sinon
.
fakeServer
.
create
();
o
.
server
.
respondWith
(
"
GET
"
,
new
RegExp
(
"
https://ca-davstorage:8080/http:%252F%252F100%2525_
\\
.json
"
),
[
200
,
{
"
Content-Type
"
:
"
text/plain
"
},
'
{"_id":"doc1","title":"Hello There"}
'
]
);
o
.
spy
(
o
,
"
status
"
,
405
,
"
Update document previous -> 405
"
);
o
.
jio
.
post
({
"
_id
"
:
"
http://100%.json
"
,
"
title
"
:
"
Hello There Again
"
},
{
"
max_retry
"
:
1
},
o
.
f
);
o
.
clock
.
tick
(
1000
);
o
.
server
.
respond
();
o
.
tick
(
o
);
o
.
server
.
restore
();
util
.
closeAndcleanUpJio
(
o
.
jio
);
});
test
(
"
Put
"
,
function
()
{
var
o
=
generateTools
(
this
);
o
.
jio
=
jIO
.
newJio
({
"
type
"
:
"
dav
"
,
"
url
"
:
"
https://ca-davstorage:8080
"
,
"
auth_type
"
:
"
basic
"
,
"
username
"
:
"
admin
"
,
"
password
"
:
"
pwd
"
});
// put without id => 20 Id Required
o
.
spy
(
o
,
"
status
"
,
20
,
"
Put without id -> 20
"
);
o
.
jio
.
put
({},
o
.
f
);
o
.
tick
(
o
);
// put non empty document
o
.
server
=
sinon
.
fakeServer
.
create
();
o
.
server
.
respondWith
(
"
PUT
"
,
new
RegExp
(
"
https://ca-davstorage:8080/http:%252F%252F100%2525_
\\
.json
"
),
[
200
,
{
"
Content-Type
"
:
"
text/html
"
},
"
<h1>OK1</h1>
"
]
);
o
.
spy
(
o
,
"
value
"
,
{
"
ok
"
:
true
,
"
id
"
:
"
http://100%.json
"
},
"
Create document
"
);
o
.
jio
.
put
({
"
_id
"
:
"
http://100%.json
"
,
"
title
"
:
"
Hi There
"
},
{
"
max_retry
"
:
1
},
o
.
f
);
o
.
clock
.
tick
(
1000
);
o
.
server
.
respond
();
o
.
tick
(
o
);
o
.
server
.
restore
();
// update document
o
.
server
=
sinon
.
fakeServer
.
create
();
o
.
server
.
respondWith
(
"
PUT
"
,
new
RegExp
(
"
https://ca-davstorage:8080/http:%252F%252F100%2525_
\\
.json
"
),
[
200
,
{
"
Content-Type
"
:
"
text/html
"
},
"
<h1>OK!</h1>
"
]
);
o
.
spy
(
o
,
"
value
"
,
{
"
ok
"
:
true
,
"
id
"
:
"
http://100%.json
"
},
"
Update document
"
);
o
.
jio
.
put
({
"
_id
"
:
"
http://100%.json
"
,
"
title
"
:
"
Hi There Again
"
},
{
"
max_retry
"
:
1
},
o
.
f
);
o
.
clock
.
tick
(
1000
);
o
.
server
.
respond
();
o
.
tick
(
o
);
o
.
server
.
restore
();
// putAttachment without document id => 20 Id Required
o
.
spy
(
o
,
"
status
"
,
20
,
"
PutAttachment without doc id -> 20
"
);
o
.
jio
.
putAttachment
({
"
_attachment
"
:
"
body.html
"
},
o
.
f
);
o
.
tick
(
o
);
// putAttachment without attachment id => 22 Attachment Id Required
o
.
spy
(
o
,
"
status
"
,
22
,
"
PutAttachment without attachment id -> 22
"
);
o
.
jio
.
putAttachment
({
"
_id
"
:
"
http://100%.json
"
},
o
.
f
);
o
.
tick
(
o
);
// putAttachment without underlying document => 404 Not Found
o
.
server
=
sinon
.
fakeServer
.
create
();
o
.
server
.
respondWith
(
"
GET
"
,
new
RegExp
(
"
https://ca-davstorage:8080/http:%252F%252F100%2525_
\\
.json
"
),
[
404
,
{
"
Content-Type
"
:
"
text/html
"
},
"
<h1>Not Found</h1>
"
]
);
o
.
spy
(
o
,
"
status
"
,
404
,
"
PutAttachment without document -> 404
"
);
o
.
jio
.
putAttachment
({
"
_id
"
:
"
http://100%.json
"
,
"
_attachment
"
:
"
putattmt2
"
},
{
"
max_retry
"
:
1
},
o
.
f
);
o
.
clock
.
tick
(
1000
);
o
.
server
.
respond
();
o
.
tick
(
o
);
o
.
server
.
restore
();
// upload attachment
o
.
server
=
sinon
.
fakeServer
.
create
();
o
.
server
.
respondWith
(
"
GET
"
,
new
RegExp
(
"
https://ca-davstorage:8080/http:%252F%252F100%2525_
\\
.json
"
),
[
200
,
{
"
Content-Type
"
:
"
text/plain
"
},
'
{"_id":"http://100%.json","title":"Hi There!"}
'
]
);
o
.
server
.
respondWith
(
"
PUT
"
,
new
RegExp
(
"
https://ca-davstorage:8080/
"
+
"
http:%252F%252F100%2525_
\\
.json.body_
\\
.html
"
),
[
200
,
{
"
Content-Type
"
:
"
text/html
"
},
"
<h1>OK!</h1>
"
]
);
o
.
server
.
respondWith
(
"
PUT
"
,
new
RegExp
(
"
https://ca-davstorage:8080/http:%252F%252F100%2525_
\\
.json
"
),
[
200
,
{
"
Content-Type
"
:
"
text/html
"
},
"
<h1>OK!</h1>
"
]
);
o
.
spy
(
o
,
"
value
"
,
{
"
ok
"
:
true
,
"
id
"
:
"
http://100%.json
"
,
"
attachment
"
:
"
body.html
"
},
"
Upload attachment
"
);
o
.
jio
.
putAttachment
({
"
_id
"
:
"
http://100%.json
"
,
"
_attachment
"
:
"
body.html
"
,
"
_mimetype
"
:
"
text/html
"
,
"
_data
"
:
"
<h1>Hi There!!</h1><p>How are you?</p>
"
},
{
"
max_retry
"
:
1
},
o
.
f
);
o
.
clock
.
tick
(
1000
);
o
.
server
.
respond
();
o
.
tick
(
o
);
o
.
server
.
restore
();
util
.
closeAndcleanUpJio
(
o
.
jio
);
});
test
(
"
Get
"
,
function
()
{
var
o
=
generateTools
(
this
);
o
.
jio
=
jIO
.
newJio
({
"
type
"
:
"
dav
"
,
"
url
"
:
"
https://ca-davstorage:8080
"
,
"
auth_type
"
:
"
basic
"
,
"
username
"
:
"
admin
"
,
"
password
"
:
"
pwd
"
});
// get inexistent document
o
.
server
=
sinon
.
fakeServer
.
create
();
o
.
server
.
respondWith
(
"
GET
"
,
new
RegExp
(
"
https://ca-davstorage:8080/http:%252F%252F100%2525_
\\
.json
"
),
[
404
,
{
"
Content-Type
"
:
"
text/html
"
},
"
<h1>Not Found</h1>
"
]
);
o
.
spy
(
o
,
"
status
"
,
404
,
"
Get non existing document -> 404
"
);
o
.
jio
.
get
({
"
_id
"
:
"
http://100%.json
"
},
{
"
max_retry
"
:
1
},
o
.
f
);
o
.
clock
.
tick
(
1000
);
o
.
server
.
respond
();
o
.
tick
(
o
);
o
.
server
.
restore
();
// get document
o
.
server
=
sinon
.
fakeServer
.
create
();
o
.
server
.
respondWith
(
"
GET
"
,
new
RegExp
(
"
https://ca-davstorage:8080/http:%252F%252F100%2525_
\\
.json
"
),
[
200
,
{
"
Content-Type
"
:
"
text/html
"
},
'
{"_id":"http://100%.json","title":"Hi There!"}
'
]
);
o
.
spy
(
o
,
"
value
"
,
{
"
_id
"
:
"
http://100%.json
"
,
"
title
"
:
"
Hi There!
"
},
"
Get document
"
);
o
.
jio
.
get
({
"
_id
"
:
"
http://100%.json
"
},
{
"
max_retry
"
:
1
},
o
.
f
);
o
.
clock
.
tick
(
1000
);
o
.
server
.
respond
();
o
.
tick
(
o
);
o
.
server
.
restore
();
// get inexistent attachment
o
.
server
=
sinon
.
fakeServer
.
create
();
o
.
server
.
respondWith
(
"
GET
"
,
new
RegExp
(
"
https://ca-davstorage:8080/
"
+
"
http:%252F%252F100%2525_
\\
.json
\\
.body_
\\
.html
"
),
[
404
,
{
"
Content-Type
"
:
"
text/html
"
},
"
<h1>Not Found</h1>
"
]
);
o
.
spy
(
o
,
"
status
"
,
404
,
"
Get inexistent attachment -> 404
"
);
o
.
jio
.
getAttachment
({
"
_id
"
:
"
http://100%.json
"
,
"
_attachment
"
:
"
body.html
"
},
{
"
max_retry
"
:
1
},
o
.
f
);
o
.
clock
.
tick
(
1000
);
o
.
server
.
respond
();
o
.
tick
(
o
);
o
.
server
.
restore
();
// get attachment
o
.
server
=
sinon
.
fakeServer
.
create
();
o
.
server
.
respondWith
(
"
GET
"
,
new
RegExp
(
"
https://ca-davstorage:8080/
"
+
"
http:%252F%252F100%2525_
\\
.json
\\
.body_
\\
.html
"
),
[
200
,
{
"
Content-Type
"
:
"
text/plain
"
},
"
My Attachment Content
"
]
);
o
.
spy
(
o
,
"
value
"
,
"
My Attachment Content
"
,
"
Get attachment
"
);
o
.
jio
.
getAttachment
({
"
_id
"
:
"
http://100%.json
"
,
"
_attachment
"
:
"
body.html
"
},
{
"
max_retry
"
:
1
},
o
.
f
);
o
.
clock
.
tick
(
1000
);
o
.
server
.
respond
();
o
.
tick
(
o
);
o
.
server
.
restore
();
util
.
closeAndcleanUpJio
(
o
.
jio
);
});
test
(
"
Remove
"
,
function
()
{
var
o
=
generateTools
(
this
);
o
.
jio
=
jIO
.
newJio
({
"
type
"
:
"
dav
"
,
"
url
"
:
"
https://ca-davstorage:8080
"
,
"
auth_type
"
:
"
basic
"
,
"
username
"
:
"
admin
"
,
"
password
"
:
"
pwd
"
});
// remove inexistent document
o
.
server
=
sinon
.
fakeServer
.
create
();
o
.
server
.
respondWith
(
"
GET
"
,
new
RegExp
(
"
https://ca-davstorage:8080/http:%252F%252F100%2525_
\\
.json
"
),
[
404
,
{
"
Content-Type
"
:
"
text/html
"
},
"
<h1>Not Found</h1>
"
]
);
o
.
spy
(
o
,
"
status
"
,
404
,
"
Remove inexistent document -> 404
"
);
o
.
jio
.
remove
({
"
_id
"
:
"
http://100%.json
"
},
{
"
max_retry
"
:
1
},
o
.
f
);
o
.
clock
.
tick
(
1000
);
o
.
server
.
respond
();
o
.
tick
(
o
);
o
.
server
.
restore
();
// remove document
o
.
server
=
sinon
.
fakeServer
.
create
();
o
.
server
.
respondWith
(
"
GET
"
,
new
RegExp
(
"
https://ca-davstorage:8080/http:%252F%252F100%2525_
\\
.json
"
),
[
200
,
{
"
Content-Type
"
:
"
text/html
"
},
"
{My corrupted document}
"
]
);
o
.
server
.
respondWith
(
"
DELETE
"
,
new
RegExp
(
"
https://ca-davstorage:8080/http:%252F%252F100%2525_
\\
.json
"
),
[
200
,
{
"
Content-Type
"
:
"
text/plain
"
},
"
<h1>Deleted</h1>
"
]
);
o
.
spy
(
o
,
"
value
"
,
{
"
ok
"
:
true
,
"
id
"
:
"
http://100%.json
"
},
"
Remove document
"
);
o
.
jio
.
remove
({
"
_id
"
:
"
http://100%.json
"
},
{
"
max_retry
"
:
1
},
o
.
f
);
o
.
clock
.
tick
(
1000
);
o
.
server
.
respond
();
o
.
tick
(
o
);
o
.
server
.
restore
();
// remove inexistent attachment
o
.
server
=
sinon
.
fakeServer
.
create
();
o
.
server
.
respondWith
(
"
GET
"
,
new
RegExp
(
"
https://ca-davstorage:8080/http:%252F%252F100%2525_
\\
.json
"
),
[
200
,
{
"
Content-Type
"
:
"
text/plain
"
},
"
{}
"
]
);
o
.
spy
(
o
,
"
status
"
,
404
,
"
Remove inexistent attachment -> 404
"
);
o
.
jio
.
removeAttachment
({
"
_id
"
:
"
http://100%.json
"
,
"
_attachment
"
:
"
body.html
"
},
{
"
max_retry
"
:
1
},
o
.
f
);
o
.
clock
.
tick
(
1000
);
o
.
server
.
respond
();
o
.
tick
(
o
);
// o.server.respond();
// o.server.respond();
o
.
server
.
restore
();
// remove attachment
o
.
server
=
sinon
.
fakeServer
.
create
();
o
.
server
.
respondWith
(
"
GET
"
,
new
RegExp
(
"
https://ca-davstorage:8080/http:%252F%252F100%2525_
\\
.json
"
),
[
200
,
{
"
Content-Type
"
:
"
text/plain
"
},
JSON
.
stringify
({
"
_attachments
"
:
{
"
body.html
"
:
{
"
length
"
:
32
,
"
digest
"
:
"
md5-dontcare
"
,
"
content_type
"
:
"
text/html
"
}
}
})
]
);
o
.
server
.
respondWith
(
"
PUT
"
,
new
RegExp
(
"
https://ca-davstorage:8080/http:%252F%252F100%2525_
\\
.json
"
),
[
200
,
{
"
Content-Type
"
:
"
text/html
"
},
"
<h1>OK</h1>
"
]
);
o
.
server
.
respondWith
(
"
DELETE
"
,
new
RegExp
(
"
https://ca-davstorage:8080/
"
+
"
http:%252F%252F100%2525_
\\
.json.body_
\\
.html
"
),
[
200
,
{
"
Content-Type
"
:
"
text/html
"
},
"
<h1>OK</h1>
"
]
);
o
.
spy
(
o
,
"
value
"
,
{
"
ok
"
:
true
,
"
id
"
:
"
http://100%.json
"
,
"
attachment
"
:
"
body.html
"
},
"
Remove attachment
"
);
o
.
jio
.
removeAttachment
({
"
_id
"
:
"
http://100%.json
"
,
"
_attachment
"
:
"
body.html
"
},
{
"
max_retry
"
:
1
},
o
.
f
);
o
.
clock
.
tick
(
1000
);
o
.
server
.
respond
();
o
.
tick
(
o
);
o
.
server
.
restore
();
// remove document with multiple attachments
o
.
server
=
sinon
.
fakeServer
.
create
();
o
.
server
.
respondWith
(
"
GET
"
,
new
RegExp
(
"
https://ca-davstorage:8080/http:%252F%252F100%2525_
\\
.json
"
),
[
200
,
{
"
Content-Type
"
:
"
text/html
"
},
JSON
.
stringify
({
"
_attachments
"
:
{
"
body.html
"
:
{
"
length
"
:
32
,
"
digest
"
:
"
md5-dontcare
"
,
"
content_type
"
:
"
text/html
"
},
"
other
"
:
{
"
length
"
:
3
,
"
digest
"
:
"
md5-dontcare-again
"
,
"
content_type
"
:
"
text/plain
"
}
}
})
]
);
o
.
server
.
respondWith
(
"
DELETE
"
,
new
RegExp
(
"
https://ca-davstorage:8080/http:%252F%252F100%2525_
\\
.json
"
),
[
200
,
{
"
Content-Type
"
:
"
text/plain
"
},
"
<h1>Deleted</h1>
"
]
);
o
.
server
.
respondWith
(
"
DELETE
"
,
new
RegExp
(
"
https://ca-davstorage:8080/
"
+
"
http:%252F%252F100%2525_
\\
.json
\\
.body_
\\
.html
"
),
[
200
,
{
"
Content-Type
"
:
"
text/plain
"
},
"
<h1>Deleted</h1>
"
]
);
o
.
server
.
respondWith
(
"
DELETE
"
,
new
RegExp
(
"
https://ca-davstorage:8080/
"
+
"
http:%252F%252F100%2525_
\\
.json
\\
.other
"
),
[
200
,
{
"
Content-Type
"
:
"
text/plain
"
},
"
<h1>Deleted</h1>
"
]
);
o
.
spy
(
o
,
"
value
"
,
{
"
ok
"
:
true
,
"
id
"
:
"
http://100%.json
"
},
"
Remove document containing multiple attachments
"
);
o
.
jio
.
remove
({
"
_id
"
:
"
http://100%.json
"
},
{
"
max_retry
"
:
1
},
o
.
f
);
o
.
clock
.
tick
(
1000
);
o
.
server
.
respond
();
o
.
tick
(
o
);
o
.
server
.
restore
();
util
.
closeAndcleanUpJio
(
o
.
jio
);
});
test
(
"
AllDocs
"
,
function
()
{
// need to make server requests before activating fakeServer
var
davlist
,
o
=
generateTools
();
davlist
=
"
<?xml version=
\"
1.0
\"
encoding=
\"
utf-8
\"
?> <D:multist
"
+
"
atus xmlns:D=
\"
DAV:
\"
> <D:response xmlns:lp1=
\"
DAV:
\"
xmlns:lp2
"
+
"
=
\"
http://apache.org/dav/props/
\"
> <D:href>/some/path/</D:href>
"
+
"
<D:propstat> <D:prop> <lp1:resourcetype><D:collection/></lp1:r
"
+
"
esourcetype> <lp1:creationdate>2012-05-02T12:48:33Z</lp1:creati
"
+
"
ondate> <lp1:getlastmodified>Wed, 02 May 2012 12:48:33 GMT</lp1
"
+
"
:getlastmodified> <lp1:getetag>
\"
1000-4bf0d1aeb9e43
\"
</lp1:gete
"
+
"
tag> <D:supportedlock> <D:lockentry> <D:lockscope><D:exclusive/
"
+
"
></D:lockscope> <D:locktype><D:write/></D:locktype> </D:lockent
"
+
"
ry> <D:lockentry> <D:lockscope><D:shared/></D:lockscope> <D:loc
"
+
"
ktype><D:write/></D:locktype> </D:lockentry> </D:supportedlock>
"
+
"
<D:lockdiscovery/> <D:getcontenttype>httpd/unix-directory</D:g
"
+
"
etcontenttype> </D:prop> <D:status>HTTP/1.1 200 OK</D:status> <
"
+
"
/D:propstat> </D:response> <D:response xmlns:lp1=
\"
DAV:
\"
xmlns
"
+
"
:lp2=
\"
http://apache.org/dav/props/
\"
> <D:href>/some/path/http:
"
+
"
%252F%252F100%2525_.json</D:href> <D:propstat> <D:prop> <lp1:re
"
+
"
sourcetype/> <lp1:creationdate>2012-05-02T12:48:31Z</lp1:creati
"
+
"
ondate> <lp1:getcontentlength>201</lp1:getcontentlength> <lp1:g
"
+
"
etlastmodified>Wed, 02 May 2012 12:48:27 GMT</lp1:getlastmodifi
"
+
"
ed> <lp1:getetag>
\"
c9-4bf0d1a845df9
\"
</lp1:getetag> <lp2:execut
"
+
"
able>F</lp2:executable> <D:supportedlock> <D:lockentry> <D:lock
"
+
"
scope><D:exclusive/></D:lockscope> <D:locktype><D:write/></D:lo
"
+
"
cktype> </D:lockentry> <D:lockentry> <D:lockscope><D:shared/></
"
+
"
D:lockscope> <D:locktype><D:write/></D:locktype> </D:lockentry>
"
+
"
</D:supportedlock> <D:lockdiscovery/> </D:prop> <D:status>HTTP
"
+
"
/1.1 200 OK</D:status> </D:propstat> </D:response> <D:response
"
+
"
xmlns:lp1=
\"
DAV:
\"
xmlns:lp2=
\"
http://apache.org/dav/props/
\"
>
"
+
"
<D:href>/some/path/ISBN:1038729410372</D:href> <D:propstat> <D:
"
+
"
prop> <lp1:resourcetype/> <lp1:creationdate>2012-05-01T17:41:13
"
+
"
Z</lp1:creationdate> <lp1:getcontentlength>223</lp1:getcontentl
"
+
"
ength> <lp1:getlastmodified>Wed, 02 May 2012 10:48:33 GMT</lp1:
"
+
"
getlastmodified> <lp1:getetag>
\"
c9-4bf0d1aeb9e43
\"
</lp1:getetag
"
+
"
> <lp2:executable>F</lp2:executable> <D:supportedlock> <D:locke
"
+
"
ntry> <D:lockscope><D:exclusive/></D:lockscope> <D:locktype><D:
"
+
"
write/></D:locktype> </D:lockentry> <D:lockentry> <D:lockscope>
"
+
"
<D:shared/></D:lockscope> <D:locktype><D:write/></D:locktype> <
"
+
"
/D:lockentry> </D:supportedlock> <D:lockdiscovery/> </D:prop> <
"
+
"
D:status>HTTP/1.1 200 OK</D:status> </D:propstat> </D:response>
"
+
"
<D:response xmlns:lp1=
\"
DAV:
\"
xmlns:lp2=
\"
http://apache.org/d
"
+
"
av/props/
\"
> <D:href>/some/path/http:%252F%252F100%2525_.json.b
"
+
"
ody_.html</D:href> <D:propstat> <D:prop> <lp1:resourcetype/> <l
"
+
"
p1:creationdate>2012-05-01T17:41:13Z</lp1:creationdate> <lp1:ge
"
+
"
tcontentlength>223</lp1:getcontentlength> <lp1:getlastmodified>
"
+
"
Wed, 02 May 2012 10:48:33 GMT</lp1:getlastmodified> <lp1:geteta
"
+
"
g>
\"
c9-4bf0d1aeb9e43
\"
</lp1:getetag> <lp2:executable>F</lp2:exe
"
+
"
cutable> <D:supportedlock> <D:lockentry> <D:lockscope><D:exclus
"
+
"
ive/></D:lockscope> <D:locktype><D:write/></D:locktype> </D:loc
"
+
"
kentry> <D:lockentry> <D:lockscope><D:shared/></D:lockscope> <D
"
+
"
:locktype><D:write/></D:locktype> </D:lockentry> </D:supportedl
"
+
"
ock> <D:lockdiscovery/> </D:prop> <D:status>HTTP/1.1 200 OK</D:
"
+
"
status> </D:propstat> </D:response> </D:multistatus>
"
;
o
.
jio
=
jIO
.
newJio
({
"
type
"
:
"
dav
"
,
"
url
"
:
"
https://ca-davstorage:8080
"
,
"
auth_type
"
:
"
basic
"
,
"
username
"
:
"
admin
"
,
"
password
"
:
"
pwd
"
});
// get all documents
o
.
server
=
sinon
.
fakeServer
.
create
();
o
.
server
.
respondWith
(
"
PROPFIND
"
,
new
RegExp
(
"
https://ca-davstorage:8080/
"
),
[
200
,
{
"
Content-Type
"
:
"
text/xml
"
},
davlist
]
);
o
.
spy
(
o
,
"
value
"
,
{
"
rows
"
:
[
{
"
id
"
:
"
http://100%.json
"
,
"
key
"
:
"
http://100%.json
"
,
"
value
"
:
{}},
{
"
id
"
:
"
ISBN:1038729410372
"
,
"
key
"
:
"
ISBN:1038729410372
"
,
"
value
"
:
{}}
],
"
total_rows
"
:
2
},
"
allDocs
"
);
o
.
jio
.
allDocs
(
o
.
f
);
o
.
clock
.
tick
(
1000
);
o
.
server
.
respond
();
o
.
tick
(
o
);
o
.
server
.
restore
();
// allDocs with option include_docs
o
.
server
=
sinon
.
fakeServer
.
create
();
o
.
server
.
respondWith
(
"
PROPFIND
"
,
new
RegExp
(
"
https://ca-davstorage:8080/
"
),
[
200
,
{
"
Content-Type
"
:
"
text/xml
"
},
davlist
]
);
o
.
doc1
=
{
"
_id
"
:
"
http://100%.json
"
,
"
_attachments
"
:
{
"
body.html
"
:
{
"
length
"
:
32
,
"
digest
"
:
"
md5-doncare
"
,
"
content_type
"
:
"
text/html
"
}
}};
o
.
doc2
=
{
"
_id
"
:
"
ISBN:1038729410372
"
,
"
title
"
:
"
Book Title
"
};
o
.
server
.
respondWith
(
"
GET
"
,
new
RegExp
(
"
https://ca-davstorage:8080/http:%252F%252F100%2525_
\\
.json
"
),
[
200
,
{
"
Content-Type
"
:
"
text/plain
"
},
JSON
.
stringify
(
o
.
doc1
)
]
);
o
.
server
.
respondWith
(
"
GET
"
,
new
RegExp
(
"
https://ca-davstorage:8080/ISBN:1038729410372
"
),
[
200
,
{
"
Content-Type
"
:
"
text/plain
"
},
JSON
.
stringify
(
o
.
doc2
)
]
);
o
.
spy
(
o
,
"
value
"
,
{
"
rows
"
:
[{
"
id
"
:
"
http://100%.json
"
,
"
key
"
:
"
http://100%.json
"
,
"
value
"
:
{},
"
doc
"
:
o
.
doc1
},
{
"
id
"
:
"
ISBN:1038729410372
"
,
"
key
"
:
"
ISBN:1038729410372
"
,
"
value
"
:
{},
"
doc
"
:
o
.
doc2
}],
"
total_rows
"
:
2
},
"
allDocs (include_docs)
"
);
o
.
jio
.
allDocs
({
"
include_docs
"
:
true
},
o
.
f
);
o
.
clock
.
tick
(
1000
);
o
.
server
.
respond
();
o
.
tick
(
o
);
o
.
server
.
restore
();
util
.
closeAndcleanUpJio
(
o
.
jio
);
});
}));
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment