刘泉皓

没有最强的法术,只有最强的法师。

ShareList OneDrive插件bug修复

19 Jan 2020 » memory

ShareList是一个网页版服务器目录浏览Web程序,它能够挂载本地目录、虚拟目录、OneDrive、Google Drive等文件系统,功能强大,还支持预览部分多媒体文件,如jpg、mp4、mkv等。

问题描述

这几天有人送我了一个Office365 E5子账户,有免费的1TOneDrive网盘,所以我就共享了个目录挂载到我的ShareList上,但是却报错了,步骤如下:

OneDrive中新建一个共享目录test,里面放了一张图片。

img01

img02

ShareList挂载OneDriveForBusiness到显示名称为testme的虚拟目录。

img03

ShareList首页显示:

img04

点击进入testme却报错了:

img05

问题调查分析

根据调用栈可以清楚的看到,Onedrive的分享由sharelist/plugins/drive.odb.js插件提供支持,错误是Invalid time value

format.js最近的调用是113行,所以看看代码到底是什么。

updated_at: datetime(i.Modified.replace(/\//g,'-')),

这段代码就是把i/字符替换为-,看上去并没有什么问题。但是错误是Invalid time value,所以看看datetime()传入的时间到底是什么。

我们在return {前面插入console.log("i:", i)

let children = data ? data.map((i) => {
    console.log("i:", i)   
    return {
    id: rootId + '@' + i.FileRef,
    name: i.FileLeafRef,
    ext: i['.fileType'],
    protocol: defaultProtocol,
    created_at: '-',
    updated_at: datetime(i.Modified.replace(/\//g,'-')),
    size: i.FileSizeDisplay,
    type: i.FSObjType == '1' ? 'folder' : undefined,
    }
}) : []

然后用node启动服务器,会打印出i的所有值。(注:这里的i其实是sharelist请求Onedrive分享链接返回的Header 头)。

i: { ID: '9',
  ...
  Modified: '19/1/2020 下午 2:20',
  'Modified.': '2020-01-19 14:20:56',
  'Modified.FriendlyDisplay': '1|0|6|2',
  ...
  '.etag': '"{DB2F9350-4B23-44DE-863B-C3C0DF7A2E0E},4"' }

最主要的就是Modified了,它的值是19/1/2020 下午 2:20,看上去没有什么问题。那么现在看看报错核心文件sharelist/app/utils/format.js30行是什么。

return a.toISOString()

再看看这里的a是什么。

const datetime = (date, expr = 'iso') => {
  var a = new Date()
  if(isDate(date)){
    a = date
  }
  else if(isString(date)){
    try{
      a = new Date(date);
    }catch(e){

    }
  }

很明显,drive.odb.js调用datetime()时传入了19-1-2020 下午 2:20这个日期(/replace()替换成了-),那么具体执行的是a = date还是a = new Date(date)呢?

追一追代码,发现核心代码在sharelist/app/utils/base.js,如下:

const isType = (type) => (obj) => (Object.prototype.toString.call(obj) === `[object ${type}]`)
...
const isDate = isType('Date')

很明显,我们这里调用的是[object String],而不是[object Date],那么isType(date)会为false,因此会执行a = new Date(date);,那么我们在Chrome浏览器的Console执行一下看看。

a = new Date('19-1-2020 下午 2:20')
Invalid Date

原因就在这里了,日期格式错了。那么我们再来看看返回的Header 头,发现还有一个'Modified.',一看就是标准格式,那么我们用它试试看。

a = new Date('2020-01-19 14:20:56')
Sun Jan 19 2020 14:20:56 GMT+0800 (China Standard Time)

解决方法

问题就调查清楚了,ShareListsharelist/plugins/drive.odb.js文件中updated_at: datetime(i.Modified.replace(/\//g,'-')),使用了错误的Modified头属性,把它替换成'Modified.'即可,注意这里由于属性名包含.字符,所以我们用数组方式调用。

updated_at: datetime(i['Modified.'].replace(/\//g,'-')),

现在再看看ShareListtestme目录,大功告成。

img06

额外注意事项

在调试过程中,我发现后台建立虚拟目录时不能使用部分关键字,如odonedrive等,不然会被解析成相应插件打开目录导致错误,具体的如下:

liuxu:~/source/git/sharelist/plugins$ find . -name "*.js" | xargs grep "protocols ="
./drive.od.api.js:const protocols = ['oda']
./drive.h5ai.js:const protocols = ['h5ai']
./drive.book.js:const protocols = ['book']
./drive.od.js:const protocols = ['od', 'onedrive']
./drive.lanzou.js:const protocols = ['lanzou']
./drive.odb.js:const protocols = ['odb']
./drive.openload.js:const protocols = ['openload']
./drive.gd.api.js:const protocols = ['gda']
./drive.gd.js:const protocols = ['gd','googledrive']
./drive.webdav.js:const protocols = ['webdav']
./drive.github.js:const protocols = ['github']
./drive.joy.js:const protocols = ['joy']

所以取名最好用大写或者带_的字符串或者中文。


知识共享许可协议    鄂ICP备 15002452号-5    鄂公网安备 42088102000048号