webdav_client_plus 3.0.0
webdav_client_plus: ^3.0.0 copied to clipboard
A simple WebDAV client that supports some common methods.
Changelog #
3.0.0 #
Security #
- Cross-origin redirects now drop
Authorization,CookieandProxy-Authorizationset throughsetHeaders, not only per-request ones, and keep dropping them on later same-origin hops. DigestAuthno longer sends anAuthorizationheader before the server's first challenge; that header carried a response hash computed without a nonce.
Breaking #
Auth.authorizetakes an optionalbodyandDigestAuth.authorizereturnsString?:nullbefore a challenge is known or when its algorithm is not supported, instead of an MD5 response.- The library re-exports the dio and xml types used in its public API
(
CancelToken,DioException,DioExceptionType,Options,ProgressCallback,Response,ResponseBody,ResponseType,XmlElementand its find/string extensions), so callers no longer need directdio/xmldependencies. Code that also imports another library exporting one of these names, such asResponsefrompackage:http, needs a prefix orhideon one of the imports. - Paths follow
PathMode.baseRelativeby default, the convention of rclone, the npmwebdavclient and webdavclient3. A path is decoded text relative to the base URL, with or without a leading/.%,?and#are part of the name, and..above the base throwsArgumentError.WebdavFile.path,propFindRaw/propFindDepthkeys and discovery helper results are base-relative paths, or absolute URLs for resources outside the base. Thehrefarguments ofbind,rebind,mergeandmkworkspacetake the same form. SetWebdavOptions(pathMode: PathMode.legacy)to keep the previous behaviour until the next major release. WebdavFile.parseFilestakes the body and a function converting each href to a path, and no longer skips the requested resource;WebdavFile.parsetakes the converted path before the raw href.- The license changes from BSD-3-Clause to Apache-2.0.
NOTICEkeeps the original BSD-3-Clause notice for the upstreamwebdav_clientcode.
Added #
WebdavOptionsconfigurespathMode, headers and timeouts when creating a client;WebdavClient.webdavOptionsreflects laterset*calls.MultiStatusResponse.rawHrefkeeps the href as sent by the server.ActiveLock.lockRootexposes theDAV:lockrootresource in the same form asWebdavFile.path, so a lock inherited from a parent collection can be told apart and unlocked or refreshed on its root.
Fixed #
mkdirAllno longer issues MKCOL for collections above the base URL when it creates missing parents, and a%XXsequence in a listed name no longer turns into a different name whenWebdavFile.pathis passed back.WebdavFile.createdaccepts an RFC 3339 leap second (23:59:60UTC at the end of a month) instead of dropping the value.- WebDAV elements are matched in the
DAV:namespace only, so a same-named element from another namespace no longer fills lock fields, lock tokens,DAV:errorpreconditions, ACL entries, privileges, supported methods or supported reports. supportedLivePropertiesunwraps theDAV:name/DAV:propelement of RFC 3253 §3.1.4 instead of reporting the wrapper.- Headers a request must not carry (sensitive ones after a cross-origin
redirect, entity ones on a 303 GET) are removed from the final request
instead of being set to
null, which the web adapter sent as the literal valuenull. readFilecleanup no longer raises unhandled async errors when closing or deleting the partial file fails, and a failed close after the last chunk also removes the file.lock()reports a malformed response body asWebdavExceptioninstead of leaking anXmlParserException.readDir,readProps,propFindandquotaBytesreport a PROPFIND response with an empty or malformed body asWebdavExceptioninstead of leaking anXmlParserException(or a cast error fromquotaBytes).syncCollectionsendsDepth: 0as RFC 6578 §3.3 requires, even when the caller passes aDepthheader; thedepthargument only setsDAV:sync-level.basicSearchwraps the query in theDAV:searchrequestroot required by RFC 5323 §2.3.refreshLockaccepts any absolute URI as a lock token, not onlyurn:uuid:andopaquelocktoken:ones, and skipsNotconditions.- Digest picks its challenge by auth-scheme, so a
WWW-Authenticatefield listing several schemes works, and chooses the strongest supported algorithm; a challenge with only unsupported algorithms or qop values fails instead of silently using MD5 or the qop-less formula.qop=auth-inthashes the actual request body. A streamed request that cannot be retried after a 401 leaves the client's Digest state unchanged. readFilereports a 401 asWebdavExceptioninstead ofStateError, no longer limits the whole download toreceiveTimeout, and removes the partial file when writing it fails. When the local file cannot be created, the response body is cancelled instead of being buffered by dio. On timeout or cancellation the partial file is removed before the error is thrown, even when closing it fails.readFileandreadStreamread the body of an unsuccessful response into the exception, releasing the connection.- A 303 turns the request into a GET without entity headers, including ones
set through
setHeaders, and keeps HEAD as HEAD. ALocationthat cannot be parsed is no longer followed in a loop, and a redirect that is not followed keeps its body for the caller. - COPY/MOVE retries a 409 once after creating the parent instead of looping,
and no longer sends the
Ifheader and conditions to the parent MKCOL. A 207 that names no member fails instead of passing as success, since RFC 4918 §9.8.5 sends 207 only when errors stopped the operation. readPropsandquotaBytesuse the response entry for the requested resource instead of the first one when a Depth 0 reply lists others.- Download progress treats any
Content-Encodingother thanidentityas compressed. readDirno longer returns the requested collection itself when the base URL has a path (e.g./remote.php/dav/files/<user>). Hrefs are now compared against the resolved request URL, ignoring percent-encoding differences.DAV:statusvalues are only accepted as HTTP status-lines, so text such aserror 200no longer marks a propstat as successful.- Hrefs are decoded exactly once and kept as sent when they are not valid
percent-encoding, so a bare
%no longer makesreadDirthrow and%2541is no longer read asA. Raw non-ASCII characters in hrefs are kept instead of making parsing throw. Surrounding whitespace is trimmed from hrefs and lock tokens. - Multi-Status parsing only reads the
DAV:responsechildren of the root, so property values containingresponseelements no longer add phantom entries. Response, propstat and status elements must be inDAV:, and a 207 whose root is notDAV:multistatusis reported as malformed instead of as an empty success. WebdavFilereads its fields fromDAV:properties only; a same-named property in another namespace stays incustomProps.creationdatealso accepts HTTP dates and lowercase RFC 3339, rejects dates outside the RFC 3339 grammar or calendar (such as Feb 30) instead of rolling them over, and two-digit RFC 850 years follow RFC 9110 §5.6.7.propFindfinds the target under a base path atDepth: 1instead of returning an empty map, and no longer returns the properties of another resource when the response holds a single entry or names it by an absolute href on another origin.- Absolute
HTTP://andHTTPS://targets are recognised regardless of scheme case instead of being resolved as paths. modifyPropsno longer gives set and remove properties in different namespaces the same prefix, which sent the wrong property.setProps,modifyPropsandpropPatchthrow when a 207 carries a response-level error status. PROPPATCH, COPY and MOVE treat as failed a propstat whoseDAV:statusis missing or unparsable, a response whose ownDAV:statusis unparsable, and a response with neither a status nor propstats.
2.0.0 #
Breaking #
- The
xmlconstraint moved from^6.0.0to^7.0.1.xml7 deprecates thenamespacearguments in favour ofnamespaceUri, which does not exist in 6, so both versions cannot be supported at once.XmlElementappears in the return types ofpropFind,propFindRaw,accessControlList, andaclRestrictions, so dependents pinned toxml6 will not resolve against this release. - The SDK constraint moved from
>=3.0.0 <4.0.0to^3.11.0.xml7.0.1 requires Dart 3.11, so the previous floor could not be honoured; it is now declared accurately rather than failing during resolution. - Remaining dependency floors were raised to the versions this release is
tested against:
convert^3.1.2,crypto^3.0.7,dio^5.11.0. - Sources moved from
src/client.dart,src/dio.dart,src/file.dart, andsrc/utils.dartintosrc/client/,src/models/, andsrc/internal/. Importingpackage:webdav_client_plus/webdav_client_plus.dartis unaffected; direct imports of the oldsrc/paths are not. - GET and PUT no longer issue an OPTIONS preflight. Servers that relied on the preflight to create an implicit session see one fewer request.
Added #
- Access control (RFC 3744):
acl,accessControlList,aclRestrictions,currentUserPrivilegeSet,currentUserPrincipal,inheritedAclSet,ownerPrincipal,groupMemberSet,groupMembership,principalCollectionSet,principalMatch,principalPropertySearch,principalSearchPropertySet,principalUrl,alternateUriSet. - Versioning (RFC 3253):
versionControl,checkin,checkout,uncheckout,checkedIn,checkedOut,versionTree,versionHistory,versionHistoryReport,label,merge,baselineControl,mkactivity,mkworkspace,expandProperty,predecessorSet,successorSet,activityCollectionSet,workspaceCollectionSet. - Bindings (RFC 5842):
bind,unbind,rebind. - Collection synchronization (RFC 6578):
syncCollection. - Property access:
propFind,propFindAll,propFindDepth,propFindNames,propFindRaw,propPatch,orderpatch,mkdirWithProps,supportedMethods,supportedLiveProperties,supportedReports,resourceTypes,quotaBytes,source,comment,creatorDisplayName.propFindRawreports per-property status codes rather than collapsing them. - Locking:
lockDiscovery,supportedLocks,refreshLock. - Transport:
requestruns arbitrary verbs through the built-in auth stack, withreport,search,options, andheadbuilt on top. Also addedreadStream,writeStream,create,updateIfMatch, andabsoluteUrl. - Subscriptions:
subscribe,unsubscribe,poll. - Multi-Status parsing:
parseMultiStatus,parseMultiStatusToMap,MultiStatusResponse, andMultiStatusPropstat, carrying per-property status codes together with<d:error>,<d:responsedescription>, and<d:location>.
Changed #
copyacceptsDepth: 0per RFC 4918 §9.8 and rejects unsupported depths.- Lock tokens are read from the
Lock-Tokenresponse header first, with the XML body retained as a fallback (RFC 4918 §§9.10.1, 10.5). - Requests carrying an
Ifheader now also sendCache-Control: no-cacheandPragma: no-cache(RFC 4918 §10.4.5). - DELETE responses with 207 Multi-Status report per-member diagnostics.
Fixed #
DestinationandIfheader URLs are percent-encoded. Paths containing a space or any non-ASCII character previously produced an invalid header value, which servers such as dufs rejected with400 Invalid Destination, breakingcopy,move, andrenameon those paths. Existing%XXescapes are left intact, so pre-encoded input such as%2Fis not double-encoded.- A 3xx response with no
Locationheader now reportsNo location header foundinstead of a generic failure. The rawrequestescape hatch still returns the response unchanged. - Cancelling a
readFileno longer raisesPathNotFoundExceptionwhen the partial download has already been removed. The cleanup runs from an unawaited cancel handler, so the error surfaced as an unhandled async error rather than reaching the caller. resolveAgainstBaseUrlstrips dot-segments per RFC 4918 §8.3.resolveAgainstBaseUrltreats leading-slash references as server-root URLs.WebdavFileretains custom property XML, so empty and structured values survive PROPFIND parsing.WebdavFileparsing accepts every 2xx propstat status, so entries from compliant servers are no longer dropped.
1.0.0 #
- Initial release of the project.