diff --git a/CHANGELOG.md b/CHANGELOG.md index a9560894..c9afba15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,8 +28,8 @@ This release contains **BREAKING CHANGES!** - Refactor WsgiDirBrowser: - Use Jinja2 and load static assets through own WsgiDAV provider - Move to `addons.dir_browser` package -- Support Docker - https://cloud.docker.com/swarm/mar10/repository/docker/mar10/wsgidav/ + - Option 'ms_sharepoint_support' replaces ms_sharepoint_plugin and ms_sharepoint_urls +- Support [Docker image](https://hub.docker.com/r/mar10/wsgidav/) - MSI setup uses Cheroot/6.4 Python 3.6 - #112: Added limited support for Microsoft's Win32LastModified property. diff --git a/Pipfile.lock b/Pipfile.lock index 6a58907c..1a4d87a8 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "71896b78f481864d95bc30cf5409ce75210aa2e1360d3e22517d6f70d34193e4" + "sha256": "de45564f00f78767d283e860c569b2af7c1262f0a8b992a98b3b3b3f99ffc3a8" }, "pipfile-spec": 6, "requires": {}, @@ -43,22 +43,6 @@ ], "version": "==1.0" }, - "pluggy": { - "hashes": [ - "sha256:6e3836e39f4d36ae72840833db137f7b7d35105079aee6ec4a62d9f80d594dd1", - "sha256:95eb8364a4708392bae89035f45341871286a333f749c3141c20573d2b3876e1" - ], - "markers": "python_version != '3.3.*' and python_version != '3.0.*' and python_version >= '2.7' and python_version != '3.1.*' and python_version != '3.2.*'", - "version": "==0.7.1" - }, - "py": { - "hashes": [ - "sha256:3fd59af7435864e1a243790d322d763925431213b6b8529c6ca71081ace3bbf7", - "sha256:e31fb2767eb657cbde86c454f02e99cb846d3cd9d61b318525140214fdc0e98e" - ], - "markers": "python_version != '3.3.*' and python_version != '3.2.*' and python_version != '3.0.*' and python_version != '3.1.*' and python_version >= '2.7'", - "version": "==1.5.4" - }, "pyyaml": { "hashes": [ "sha256:3d7da3009c0f3e783b2c873687652d83b1bbfd5c88e9813fb7e5b03c0dd3108b", @@ -75,29 +59,6 @@ ], "index": "pypi", "version": "==3.13" - }, - "six": { - "hashes": [ - "sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", - "sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb" - ], - "version": "==1.11.0" - }, - "tox": { - "hashes": [ - "sha256:37cf240781b662fb790710c6998527e65ca6851eace84d1595ee71f7af4e85f7", - "sha256:eb61aa5bcce65325538686f09848f04ef679b5cd9b83cc491272099b28739600" - ], - "index": "pypi", - "version": "==3.2.1" - }, - "virtualenv": { - "hashes": [ - "sha256:2ce32cd126117ce2c539f0134eb89de91a8413a29baac49cbab3eb50e2026669", - "sha256:ca07b4c0b54e14a91af9f34d0919790b016923d157afda5efdde55c96718f752" - ], - "markers": "python_version != '3.0.*' and python_version != '3.1.*' and python_version != '3.2.*' and python_version >= '2.7'", - "version": "==16.0.0" } }, "develop": { @@ -153,11 +114,11 @@ }, "beautifulsoup4": { "hashes": [ - "sha256:272081ad78c5495ba67083a0e50920163701fa6fe67fbb5eefeb21b5dd88c40b", - "sha256:5a3d659840960a4107047b6328d6d4cdaaee69939bf11adc07466a1856c99a80", - "sha256:bd43a3b26d2886acd63070c43da821b60dea603eb6d45bab0294aac6129adbfa" + "sha256:194ec62a25438adcb3fdb06378b26559eda1ea8a747367d34c33cef9c7f48d57", + "sha256:90f8e61121d6ae58362ce3bed8cd997efb00c914eae0ff3d363c32f9a9822d10", + "sha256:f0abd31228055d698bb392a826528ea08ebb9959e6bea17c606fd9c9009db938" ], - "version": "==4.6.1" + "version": "==4.6.3" }, "black": { "hashes": [ @@ -169,10 +130,10 @@ }, "certifi": { "hashes": [ - "sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7", - "sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0" + "sha256:4c1d68a1408dd090d2f3a869aa94c3947cc1d967821d1ed303208c9f41f0f2f4", + "sha256:b6e8b28b2b7e771a41ecdd12d4d43262ecab52adebbafa42c77d6b57fb6ad3a4" ], - "version": "==2018.4.16" + "version": "==2018.8.13" }, "chardet": { "hashes": [ @@ -375,11 +336,12 @@ }, "pluggy": { "hashes": [ - "sha256:6e3836e39f4d36ae72840833db137f7b7d35105079aee6ec4a62d9f80d594dd1", - "sha256:95eb8364a4708392bae89035f45341871286a333f749c3141c20573d2b3876e1" + "sha256:7f8ae7f5bdf75671a718d2daf0a64b7885f74510bcd98b1a0bb420eb9a9d0cff", + "sha256:d345c8fe681115900d6da8d048ba67c25df42973bda370783cd58826442dcd7c", + "sha256:e160a7fcf25762bb60efc7e171d4497ff1d8d2d75a3d0df7a21b76821ecbf5c5" ], - "markers": "python_version != '3.3.*' and python_version != '3.0.*' and python_version >= '2.7' and python_version != '3.1.*' and python_version != '3.2.*'", - "version": "==0.7.1" + "markers": "python_version != '3.3.*' and python_version != '3.2.*' and python_version != '3.0.*' and python_version != '3.1.*' and python_version >= '2.7'", + "version": "==0.6.0" }, "py": { "hashes": [ diff --git a/doc/annotated_wsgidav.conf b/doc/annotated_wsgidav.conf index 6a8fbc40..8646e5ef 100644 --- a/doc/annotated_wsgidav.conf +++ b/doc/annotated_wsgidav.conf @@ -147,8 +147,9 @@ dir_browser = { "response_trailer": "", # Raw HTML code, appended as footer "davmount": False, # Send response if request URL contains '?davmount' "ms_mount": False, # Add an 'open as webfolder' link (requires Windows) - "ms_sharepoint_plugin": True, # Invoke MS Offce documents for editing using WebDAV - "ms_sharepoint_urls": False, # Prepend 'ms-word:ofe|u|' to URL for MS Offce documents + "ms_sharepoint_support": True, # Invoke MS Offce documents for editing using WebDAV + ; "ms_sharepoint_plugin": False, # Invoke MS Offce documents for editing using WebDAV + ; "ms_sharepoint_urls": False, # Prepend 'ms-word:ofe|u|' to URL for MS Offce documents # "app_class": MyBrowser, # (DEPRECATED with 2.4.0) Used instead of WsgiDavDirBrowser } diff --git a/doc/sample_wsgidav.conf b/doc/sample_wsgidav.conf index cab1cfa3..c45c7b5e 100644 --- a/doc/sample_wsgidav.conf +++ b/doc/sample_wsgidav.conf @@ -150,8 +150,9 @@ dir_browser = { "response_trailer": "", # Raw HTML code, appended as footer "davmount": False, # Send response if request URL contains '?davmount' "ms_mount": False, # Add an 'open as webfolder' link (requires Windows) - "ms_sharepoint_plugin": True, # Invoke MS Offce documents for editing using WebDAV - "ms_sharepoint_urls": False, # Prepend 'ms-word:ofe|u|' to URL for MS Offce documents + "ms_sharepoint_support": True, # Invoke MS Offce documents for editing using WebDAV + ; "ms_sharepoint_plugin": False, # Invoke MS Offce documents for editing using WebDAV + ; "ms_sharepoint_urls": False, # Prepend 'ms-word:ofe|u|' to URL for MS Offce documents # "app_class": MyBrowser, # (DEPRECATED with 2.4.0) Used instead of WsgiDavDirBrowser } diff --git a/doc/sample_wsgidav.json b/doc/sample_wsgidav.json index 0c38136b..d6750b98 100644 --- a/doc/sample_wsgidav.json +++ b/doc/sample_wsgidav.json @@ -38,7 +38,6 @@ "response_trailer": "", "davmount": false, "ms_mount": false, - "ms_sharepoint_plugin": true, - "ms_sharepoint_urls": false + "ms_sharepoint_support": true } } diff --git a/sample_wsgidav.yaml b/sample_wsgidav.yaml index c711ed68..479c9c78 100644 --- a/sample_wsgidav.yaml +++ b/sample_wsgidav.yaml @@ -114,7 +114,7 @@ verbose: 3 #: Set logging output format #: (see https://docs.python.org/3/library/logging.html#logging.Formatter) -logger_format: "%(asctime)s.%(msecs)03d - <%(thread)d> %(name)-27s %(levelname)-8s: %(message)s" +logger_format: "%(asctime)s.%(msecs)03d - <%(thread)05d> %(name)-27s %(levelname)-8s: %(message)s" logger_date_format: "%H:%M:%S" #: Let ErrorPrinter middleware catch all exceptions to return as 500 Internal Error @@ -154,13 +154,20 @@ dir_browser: davmount: false #: Add an 'open as webfolder' link (requires Windows IE <= 7!) ms_mount: false - #: Invoke MS Office documents for editing using WebDAV by adding JavaScript - #: code that invokes the SharePoint plugin ActiveXObject("SharePoint.OpenDocuments") - #: (Requires MS IE) - ms_sharepoint_plugin: false - #: Prepend 'ms-word:ofe|u|' to URLs for MS Office documents - #: (This option is ignored if ms_sharepoint_plugin is true.) - ms_sharepoint_urls: true + #: Invoke MS Office documents for editing using WebDAV by adding a JavaScript + #: click handler. + #: - For IE 11 and below invokes the SharePoint ActiveXObject("SharePoint.OpenDocuments") + #: - If the custom legacy Firefox plugin is available, it will be used + #: https://docs.microsoft.com/en-us/previous-versions/office/developer/sharepoint-2010/ff407576(v%3Doffice.14) + #: - Otherwise the Office URL prefix is used (e.g. 'ms-word:ofe|u|http://server/path/file.docx') + ms_sharepoint_support: true + # #: Invoke MS Office documents for editing using WebDAV by adding JavaScript + # #: code that invokes the SharePoint plugin ActiveXObject("SharePoint.OpenDocuments") + # #: (Requires MS IE 8-11, but not Edge) + # ms_sharepoint_plugin: false + # #: Prepend 'ms-word:ofe|u|' to URLs for MS Office documents + # #: (This option is ignored if ms_sharepoint_plugin is true.) + # ms_sharepoint_urls: false # ---------------------------------------------------------------------------- diff --git a/wsgidav/addons/dir_browser/__init__.py b/wsgidav/addons/dir_browser/__init__.py index cdd6133a..c62c98cd 100644 --- a/wsgidav/addons/dir_browser/__init__.py +++ b/wsgidav/addons/dir_browser/__init__.py @@ -133,7 +133,7 @@ def _get_context(self, environ, davres): assert davres.is_collection dirConfig = environ["wsgidav.config"].get("dir_browser", {}) - isReadOnly = environ["wsgidav.provider"].is_readonly() + is_readonly = environ["wsgidav.provider"].is_readonly() context = { "htdocs": (self.config.get("mount_path") or "") + ASSET_SHARE, @@ -143,7 +143,7 @@ def _get_context(self, environ, davres): "url": davres.get_href(), # util.make_complete_url(environ), "parentUrl": util.get_uri_parent(davres.get_href()), "config": dirConfig, - "is_readonly": isReadOnly, + "is_readonly": is_readonly, } trailer = dirConfig.get("response_trailer") @@ -173,22 +173,27 @@ def _get_context(self, environ, davres): for res in childList: di = res.get_display_info() href = res.get_href() + ofe_prefix = None tr_classes = [] a_classes = [] if res.is_collection: tr_classes.append("directory") - if not isReadOnly and not res.is_collection: + if not is_readonly and not res.is_collection: ext = os.path.splitext(href)[1].lstrip(".").lower() officeType = msOfficeExtToTypeMap.get(ext) if officeType: - if dirConfig.get("ms_sharepoint_plugin"): + if dirConfig.get("ms_sharepoint_support"): + ofe_prefix = "ms-{}:ofe|u|".format(officeType) + a_classes.append("msoffice") + elif dirConfig.get("ms_sharepoint_plugin"): a_classes.append("msoffice") elif dirConfig.get("ms_sharepoint_urls"): href = "ms-{}:ofe|u|{}".format(officeType, href) entry = { "href": href, + "ofe_prefix": ofe_prefix, "aClass": " ".join(a_classes), "trClass": " ".join(tr_classes), "displayName": res.get_display_name(), diff --git a/wsgidav/addons/dir_browser/htdocs/script.js b/wsgidav/addons/dir_browser/htdocs/script.js index 8b5a6390..94713c83 100644 --- a/wsgidav/addons/dir_browser/htdocs/script.js +++ b/wsgidav/addons/dir_browser/htdocs/script.js @@ -1,59 +1,148 @@ +// Cached plugin reference (or null. if it could not be instantiated) +var sharePointPlugin = undefined; + function onLoad() { // console.log("loaded."); } + +/** + * + */ +function getSharePointPlugin() { + if( sharePointPlugin !== undefined ) { + return sharePointPlugin; + } + sharePointPlugin = null; + + var plugin = document.getElementById("winFirefoxPlugin"); + + if ( plugin && typeof plugin.EditDocument === "function" ) { + window.console && console.log("Using embedded custom SharePoint plugin."); + sharePointPlugin = plugin; + } else if( "ActiveXObject" in window ){ + plugin = null; + try { + plugin = new ActiveXObject("SharePoint.OpenDocuments.3"); // Office 2007+ + } catch(e) { + try { + plugin = new ActiveXObject("SharePoint.OpenDocuments.2"); // Office 2003 + } catch(e2) { + try { + plugin = new ActiveXObject("SharePoint.OpenDocuments.1"); // Office 2000/XP + } catch(e3) { + window.console && console.warn("Could not create ActiveXObject('SharePoint.OpenDocuments'): (requires IE <= 11 and check security settings."); + } + } + } + if( plugin ){ + window.console && console.log("Using native SharePoint plugin."); + sharePointPlugin = plugin; + } + } + return sharePointPlugin; +} + + +/** + * + * @param {object} opts + */ +function openWebDavDocument(opts) { + var //webDavPath = opts.webDavPath, + // URL with a prefix like '' + ofe_link = opts.ofe + opts.href, // (e.g. 'ms-word:ofe|u|http://server/path/file.docx') + url = opts.href; + // url = window.location.protocol + "//" + window.location.host + opts.href; + // webDavPlugin = document.getElementById("winFirefoxPlugin"), + // fileExt = opts.fileName.split(".").pop(), + // errorMsg = "Could not open '" + webDavPath + "'. check MS Office installation and security settings."; + // errorMsg = getContext("msg_could_not_open_document_make_sure_program_for_file_type_installed_fmt").replace("{file_ext}", fileExt); + + var plugin = getSharePointPlugin(); + var res = false; + + alert("url " + url + ", " + ofe_link) + + if( plugin ) { + try { + res = plugin.EditDocument(url); + if( res === false ) { + window.console && console.warn("SharePoint plugin.EditDocument(" + url + ") returned false"); + } + } catch(e) { + window.console && console.warn("SharePoint plugin.EditDocument(" + url + ") raised an exception", e); + } + } + if ( res === false ) { + if( ofe_link ) { + window.console && console.log("Could not use SharePoint plugin: trying " + ofe_link); + window.open(ofe_link, "_self"); + return false; + } + } + return res; +} + + +// /** +// * +// * @param {*} url +// */ +// function openWithSharePointPlugin(url) { +// var res = false, +// control = null, +// isFF = false; + +// // Get the most recent version of the SharePoint plugin +// if( "ActiveXObject" in window ){ +// try { +// control = new ActiveXObject("SharePoint.OpenDocuments.3"); // Office 2007+ +// } catch(e) { +// try { +// control = new ActiveXObject("SharePoint.OpenDocuments.2"); // Office 2003 +// } catch(e2) { +// try { +// control = new ActiveXObject("SharePoint.OpenDocuments.1"); // Office 2000/XP +// } catch(e3) { +// window.console && console.warn("Could not create ActiveXObject('SharePoint.OpenDocuments'). Check your browsers security settings."); +// return false; +// } +// } +// } +// if( !control ){ +// window.console && console.warn("Cannot instantiate the required ActiveX control to open the document. This is most likely because you do not have Office installed or you have an older version of Office."); +// } +// } else { +// window.console && console.warn("Non-IE: trying FFWinPlugin Plug-in..."); +// control = document.getElementById("winFirefoxPlugin"); +// isFF = true; +// } + +// try { +// res = control.EditDocument(url); +// if( !res ){ +// window.console && console.warn("SharePoint.OpenDocuments.EditDocument('" + url + "') returned false."); +// } +// } catch (e){ +// window.console && console.warn("SharePoint.OpenDocuments.EditDocument('" + url + "') failed.", e); +// } +// return res; +// } + + /* Event delegation handler for clicks on a-tags with class 'msoffice'. */ function onClickTable(event) { - var target = event.target || event.srcElement, - href = target.href; + var target = event.target || event.srcElement, + opts = { + href: target.href, + ofe: target.getAttribute("data-ofe") + }; - if( href && target.className === "msoffice" ){ - if( openWithSharePointPlugin(href) ){ + if( target.className === "msoffice" ){ + if( openWebDavDocument(opts) ){ // prevent default processing return false; } } } - -function openWithSharePointPlugin(url) { - var res = false, - control = null, - isFF = false; - - // Get the most recent version of the SharePoint plugin - if( window.ActiveXObject ){ - try { - control = new ActiveXObject("SharePoint.OpenDocuments.3"); // Office 2007+ - } catch(e) { - try { - control = new ActiveXObject("SharePoint.OpenDocuments.2"); // Office 2003 - } catch(e2) { - try { - control = new ActiveXObject("SharePoint.OpenDocuments.1"); // Office 2000/XP - } catch(e3) { - window.console && console.warn("Could not create ActiveXObject('SharePoint.OpenDocuments'). Check your browsers security settings."); - return false; - } - } - } - if( !control ){ - window.console && console.warn("Cannot instantiate the required ActiveX control to open the document. This is most likely because you do not have Office installed or you have an older version of Office."); - } - } else { - window.console && console.log("Non-IE: trying FFWinPlugin Plug-in..."); - control = document.getElementById("winFirefoxPlugin"); - isFF = true; - } - - try { -// window.console && console.log("SharePoint.OpenDocuments.EditDocument('" + url + "')..."); - res = control.EditDocument(url); -// window.console && console.log("SharePoint.OpenDocuments.EditDocument('" + url + "')... res = ", res); - if( !res ){ - window.console && console.warn("SharePoint.OpenDocuments.EditDocument('" + url + "') returned false."); - } - } catch (e){ - window.console && console.warn("SharePoint.OpenDocuments.EditDocument('" + url + "') failed.", e); - } - return res; -} diff --git a/wsgidav/addons/dir_browser/htdocs/template.html b/wsgidav/addons/dir_browser/htdocs/template.html index ae292d96..19eee2ae 100644 --- a/wsgidav/addons/dir_browser/htdocs/template.html +++ b/wsgidav/addons/dir_browser/htdocs/template.html @@ -71,7 +71,9 @@

{% for row in rows %} - {{row.displayName}} + + {{row.displayName}} + {{ row.displayType }} {{ row.strSize }} diff --git a/wsgidav/default_conf.py b/wsgidav/default_conf.py index cbd0ebc3..4eb3e705 100644 --- a/wsgidav/default_conf.py +++ b/wsgidav/default_conf.py @@ -84,7 +84,8 @@ "davmount": False, # Add an 'open as webfolder' link (requires Windows clients): "ms_mount": False, - "ms_sharepoint_plugin": True, # Invoke MS Offce documents for editing using WebDAV - "ms_sharepoint_urls": False, # Prepend 'ms-word:ofe|u|' to URL for MS Offce documents + "ms_sharepoint_support": True, # Invoke MS Offce documents for editing using WebDAV + # "ms_sharepoint_plugin": False, # Invoke MS Offce documents for editing using WebDAV + # "ms_sharepoint_urls": False, # Prepend 'ms-word:ofe|u|' to URL for MS Offce documents }, } diff --git a/wsgidav/wsgidav_app.py b/wsgidav/wsgidav_app.py index 82d95544..19d8af71 100644 --- a/wsgidav/wsgidav_app.py +++ b/wsgidav/wsgidav_app.py @@ -85,6 +85,8 @@ def _check_config(config): deprecated_fields = { "dir_browser.app_class": "middleware_stack", "dir_browser.enable": "middleware_stack", + "dir_browser.ms_sharepoint_plugin": "dir_browser.ms_sharepoint_support", + "dir_browser.ms_sharepoint_url": "dir_browser.ms_sharepoint_support", "domaincontroller": "domain_controller", "acceptbasic": "http_authenticator.accept_basic", "acceptdigest": "http_authenticator.accept_digest",