fx115: Update lots of OS.File/OS.Path uses

This commit is contained in:
Dan Stillman 2023-12-04 05:05:34 -05:00
parent 5a8a7ebccc
commit 920461cd9d
36 changed files with 233 additions and 300 deletions

View file

@ -231,7 +231,7 @@ var Scaffold = new function () {
if (await fp.show() != fp.returnOK) { if (await fp.show() != fp.returnOK) {
return false; return false;
} }
var path = OS.Path.normalize(fp.file); var path = PathUtils.normalize(fp.file);
if (oldPath == path) { if (oldPath == path) {
return false; return false;
} }
@ -296,7 +296,7 @@ var Scaffold = new function () {
monaco.languages.registerCompletionItemProvider('javascript', this.createCompletionProvider(monaco, editor)); monaco.languages.registerCompletionItemProvider('javascript', this.createCompletionProvider(monaco, editor));
let tsLib = await Zotero.File.getContentsAsync( let tsLib = await Zotero.File.getContentsAsync(
OS.Path.join(Scaffold_Translators.getDirectory(), 'index.d.ts')); PathUtils.join(Scaffold_Translators.getDirectory(), 'index.d.ts'));
let tsLibPath = 'ts:filename/index.d.ts'; let tsLibPath = 'ts:filename/index.d.ts';
monaco.languages.typescript.javascriptDefaults.addExtraLib(tsLib, tsLibPath); monaco.languages.typescript.javascriptDefaults.addExtraLib(tsLib, tsLibPath);
// this would allow peeking: // this would allow peeking:
@ -2233,7 +2233,7 @@ var Scaffold = new function () {
} }
function getDefaultESLintPath() { function getDefaultESLintPath() {
return OS.Path.join(Scaffold_Translators.getDirectory(), 'node_modules', '.bin', 'teslint'); return PathUtils.join(Scaffold_Translators.getDirectory(), 'node_modules', '.bin', 'teslint');
} }
async function getESLintPath() { async function getESLintPath() {
@ -2243,7 +2243,7 @@ var Scaffold = new function () {
let eslintPath = getDefaultESLintPath(); let eslintPath = getDefaultESLintPath();
while (!await OS.File.exists(eslintPath)) { while (!await IOUtils.exists(eslintPath)) {
let ps = Services.prompt; let ps = Services.prompt;
let buttonFlags = ps.BUTTON_POS_0 * ps.BUTTON_TITLE_IS_STRING let buttonFlags = ps.BUTTON_POS_0 * ps.BUTTON_TITLE_IS_STRING
+ ps.BUTTON_POS_1 * ps.BUTTON_TITLE_IS_STRING + ps.BUTTON_POS_1 * ps.BUTTON_TITLE_IS_STRING

View file

@ -1,5 +1,3 @@
Components.utils.import("resource://gre/modules/osfile.jsm");
var Scaffold_Translators = { var Scaffold_Translators = {
// Keep in sync with translator.js // Keep in sync with translator.js
TRANSLATOR_TYPES: { import: 1, export: 2, web: 4, search: 8 }, TRANSLATOR_TYPES: { import: 1, export: 2, web: 4, search: 8 },
@ -35,7 +33,7 @@ var Scaffold_Translators = {
fmtime = entry.winLastWriteDate.getTime(); fmtime = entry.winLastWriteDate.getTime();
} }
else { else {
fmtime = (await OS.File.stat(entry.path)).lastModificationDate.getTime(); fmtime = (await IOUtils.stat(entry.path)).lastModified;
} }
let translatorID = this._translatorFiles.get(entry.name); let translatorID = this._translatorFiles.get(entry.name);
let loadFile = true; let loadFile = true;
@ -92,7 +90,7 @@ var Scaffold_Translators = {
Zotero.debug("Scaffold: Can't delete missing translator"); Zotero.debug("Scaffold: Can't delete missing translator");
return; return;
} }
await OS.File.delete(OS.Path.join(this.getDirectory(), translator.filename)); await IOUtils.remove(PathUtils.join(this.getDirectory(), translator.filename));
this._translators.delete(translatorID); this._translators.delete(translatorID);
this._translatorFiles.delete(translator.filename); this._translatorFiles.delete(translator.filename);
}, },

View file

@ -320,15 +320,15 @@ var Zotero_File_Interface = new function() {
Components.classes["@mozilla.org/net/osfileconstantsservice;1"] Components.classes["@mozilla.org/net/osfileconstantsservice;1"]
.getService(Components.interfaces.nsIOSFileConstantsService) .getService(Components.interfaces.nsIOSFileConstantsService)
.init(); .init();
var path = OS.Constants.Path.homeDir; var path = FileUtils.getDir('Home', []).path;
if (Zotero.isMac) { if (Zotero.isMac) {
path = OS.Path.join(path, 'Library', 'Application Support', 'Mendeley Desktop'); path = PathUtils.join(path, ['Library', 'Application Support', 'Mendeley Desktop']);
} }
else if (Zotero.isWin) { else if (Zotero.isWin) {
path = OS.Path.join(path, 'AppData', 'Local', 'Mendeley Ltd', 'Mendeley Desktop'); path = PathUtils.join(path, ['AppData', 'Local', 'Mendeley Ltd', 'Mendeley Desktop']);
} }
else if (Zotero.isLinux) { else if (Zotero.isLinux) {
path = OS.Path.join(path, '.local', 'share', 'data', 'Mendeley Ltd.', 'Mendeley Desktop'); path = PathUtils.join(path, ['.local', 'share', 'data', 'Mendeley Ltd.', 'Mendeley Desktop']);
} }
else { else {
throw new Error("Invalid platform"); throw new Error("Invalid platform");
@ -634,7 +634,7 @@ var Zotero_File_Interface = new function() {
progressWin.changeHeadline(Zotero.getString('fileInterface.importing')); progressWin.changeHeadline(Zotero.getString('fileInterface.importing'));
let icon = 'chrome://zotero/skin/treesource-unfiled' + (Zotero.hiDPI ? "@2x" : "") + '.png'; let icon = 'chrome://zotero/skin/treesource-unfiled' + (Zotero.hiDPI ? "@2x" : "") + '.png';
progress = new progressWin.ItemProgress( progress = new progressWin.ItemProgress(
icon, translation.path ? OS.Path.basename(translation.path) : translators[0].label icon, translation.path ? PathUtils.filename(translation.path) : translators[0].label
); );
progressWin.show(); progressWin.show();

View file

@ -3,7 +3,7 @@
var EXPORTED_SYMBOLS = ["Zotero_Import_Mendeley"]; //eslint-disable-line no-unused-vars var EXPORTED_SYMBOLS = ["Zotero_Import_Mendeley"]; //eslint-disable-line no-unused-vars
Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://gre/modules/osfile.jsm"); var { OS } = ChromeUtils.importESModule("chrome://zotero/content/osfile.mjs");
Services.scriptloader.loadSubScript("chrome://zotero/content/include.js"); Services.scriptloader.loadSubScript("chrome://zotero/content/include.js");
Services.scriptloader.loadSubScript("chrome://zotero/content/import/mendeley/mendeleyOnlineMappings.js"); Services.scriptloader.loadSubScript("chrome://zotero/content/import/mendeley/mendeleyOnlineMappings.js");
Services.scriptloader.loadSubScript("chrome://zotero/content/import/mendeley/mendeleyAPIUtils.js"); Services.scriptloader.loadSubScript("chrome://zotero/content/import/mendeley/mendeleyAPIUtils.js");
@ -766,7 +766,7 @@ Zotero_Import_Mendeley.prototype._getDocumentFilesDB = async function (groupID)
}; };
Zotero_Import_Mendeley.prototype._fetchFile = async function (fileID, filePath) { Zotero_Import_Mendeley.prototype._fetchFile = async function (fileID, filePath) {
const fileDir = OS.Path.dirname(filePath); const fileDir = PathUtils.parent(filePath);
await Zotero.File.createDirectoryIfMissingAsync(fileDir); await Zotero.File.createDirectoryIfMissingAsync(fileDir);
const xhr = await apiFetch(this._tokens, `files/${fileID}`, {}, {}, { responseType: 'blob', followRedirects: false }); const xhr = await apiFetch(this._tokens, `files/${fileID}`, {}, {}, { responseType: 'blob', followRedirects: false });
const uri = xhr.getResponseHeader('location'); const uri = xhr.getResponseHeader('location');
@ -1577,7 +1577,7 @@ Zotero_Import_Mendeley.prototype._findExistingFile = function (parentItemID, fil
}; };
Zotero_Import_Mendeley.prototype._isDownloadedFile = function (path) { Zotero_Import_Mendeley.prototype._isDownloadedFile = function (path) {
var parentDir = OS.Path.dirname(path); var parentDir = PathUtils.parent(path);
return parentDir.endsWith(OS.Path.join('Application Support', 'Mendeley Desktop', 'Downloaded')) return parentDir.endsWith(OS.Path.join('Application Support', 'Mendeley Desktop', 'Downloaded'))
|| parentDir.endsWith(OS.Path.join('Local', 'Mendeley Ltd', 'Mendeley Desktop', 'Downloaded')) || parentDir.endsWith(OS.Path.join('Local', 'Mendeley Ltd', 'Mendeley Desktop', 'Downloaded'))
|| parentDir.endsWith(OS.Path.join('Local', 'Mendeley Ltd.', 'Mendeley Desktop', 'Downloaded')) || parentDir.endsWith(OS.Path.join('Local', 'Mendeley Ltd.', 'Mendeley Desktop', 'Downloaded'))
@ -1606,8 +1606,8 @@ Zotero_Import_Mendeley.prototype._getRealFilePath = async function (path) {
} }
// For file paths in Downloaded folder, try relative to database if not found at the // For file paths in Downloaded folder, try relative to database if not found at the
// absolute location, in case this is a DB backup // absolute location, in case this is a DB backup
var dataDir = OS.Path.dirname(this._file); var dataDir = PathUtils.parent(this._file);
var altPath = OS.Path.join(dataDir, 'Downloaded', OS.Path.basename(path)); var altPath = OS.Path.join(dataDir, 'Downloaded', PathUtils.filename(path));
if (altPath != path && await OS.File.exists(altPath)) { if (altPath != path && await OS.File.exists(altPath)) {
return altPath; return altPath;
} }

View file

@ -33,8 +33,8 @@ const { renderCell, formatColumnName } = VirtualizedTable;
const Icons = require('components/icons'); const Icons = require('components/icons');
const { getDOMElement, getCSSIcon, getCSSItemTypeIcon } = Icons; const { getDOMElement, getCSSIcon, getCSSItemTypeIcon } = Icons;
const { COLUMNS } = require("zotero/itemTreeColumns"); const { COLUMNS } = require("zotero/itemTreeColumns");
const { Cc, Ci, Cu } = require('chrome'); const { Cc, Ci, Cu, ChromeUtils } = require('chrome');
Cu.import("resource://gre/modules/osfile.jsm"); const { OS } = ChromeUtils.importESModule("chrome://zotero/content/osfile.mjs");
/** /**
* @typedef {import("./itemTreeColumns.jsx").ItemTreeColumnOptions} ItemTreeColumnOptions * @typedef {import("./itemTreeColumns.jsx").ItemTreeColumnOptions} ItemTreeColumnOptions
@ -2404,7 +2404,7 @@ var ItemTree = class ItemTree extends LibraryTree {
} }
); );
// Update path in case the name was changed to be unique // Update path in case the name was changed to be unique
file = OS.Path.join(OS.Path.dirname(file), newName); file = PathUtils.join(PathUtils.parent(file), newName);
} }
} }
catch (e) { catch (e) {

View file

@ -201,7 +201,7 @@ FilePicker.prototype.filterVideo = 0x200;
switch (prop) { switch (prop) {
case 'file': case 'file':
// Convert from nsIFile // Convert from nsIFile
val = OS.Path.normalize(val.path); val = PathUtils.normalize(val.path);
break; break;
case 'files': case 'files':
@ -209,7 +209,7 @@ FilePicker.prototype.filterVideo = 0x200;
while (val.hasMoreElements()) { while (val.hasMoreElements()) {
let file = val.getNext(); let file = val.getNext();
file.QueryInterface(Ci.nsIFile); file.QueryInterface(Ci.nsIFile);
files.push(file.path); files.push(PathUtils.normalize(file.path));
} }
val = files; val = files;
break; break;

View file

@ -111,19 +111,19 @@ Zotero_Preferences.Advanced = {
// If there's a migration marker, point data directory back to the current location and remove // If there's a migration marker, point data directory back to the current location and remove
// it to trigger the migration again // it to trigger the migration again
var marker = OS.Path.join(defaultDir, Zotero.DataDirectory.MIGRATION_MARKER); var marker = PathUtils.join(defaultDir, Zotero.DataDirectory.MIGRATION_MARKER);
if (yield OS.File.exists(marker)) { if (yield IOUtils.exists(marker)) {
Zotero.Prefs.clear('dataDir'); Zotero.Prefs.clear('dataDir');
Zotero.Prefs.clear('useDataDir'); Zotero.Prefs.clear('useDataDir');
yield OS.File.remove(marker); yield IOUtils.remove(marker);
try { try {
yield OS.File.remove(OS.Path.join(defaultDir, '.DS_Store')); yield IOUtils.remove(PathUtils.join(defaultDir, '.DS_Store'));
} }
catch (e) {} catch (e) {}
} }
// ~/Zotero exists and is non-empty // ~/Zotero exists and is non-empty
if ((yield OS.File.exists(defaultDir)) && !(yield Zotero.File.directoryIsEmpty(defaultDir))) { if ((yield IOUtils.exists(defaultDir)) && !(yield Zotero.File.directoryIsEmpty(defaultDir))) {
let buttonFlags = (ps.BUTTON_POS_0) * (ps.BUTTON_TITLE_IS_STRING) let buttonFlags = (ps.BUTTON_POS_0) * (ps.BUTTON_TITLE_IS_STRING)
+ (ps.BUTTON_POS_1) * (ps.BUTTON_TITLE_CANCEL); + (ps.BUTTON_POS_1) * (ps.BUTTON_TITLE_CANCEL);
let index = ps.confirmEx( let index = ps.confirmEx(
@ -139,7 +139,7 @@ Zotero_Preferences.Advanced = {
if (index == 0) { if (index == 0) {
yield Zotero.File.reveal( yield Zotero.File.reveal(
// Windows opens the directory, which might be confusing here, so open parent instead // Windows opens the directory, which might be confusing here, so open parent instead
Zotero.isWin ? OS.Path.dirname(defaultDir) : defaultDir Zotero.isWin ? PathUtils.parent(defaultDir) : defaultDir
); );
} }
return; return;
@ -546,7 +546,7 @@ Zotero_Preferences.Attachment_Base_Directory = {
var oldPath = Zotero.Prefs.get('baseAttachmentPath'); var oldPath = Zotero.Prefs.get('baseAttachmentPath');
if (oldPath) { if (oldPath) {
try { try {
return OS.Path.normalize(oldPath); return PathUtils.normalize(oldPath);
} }
catch (e) { catch (e) {
Zotero.logError(e); Zotero.logError(e);
@ -638,7 +638,7 @@ Zotero_Preferences.Attachment_Base_Directory = {
// If a file with the same relative path exists within the new base directory, // If a file with the same relative path exists within the new base directory,
// don't touch the attachment, since it will continue to work // don't touch the attachment, since it will continue to work
if (relPath) { if (relPath) {
if (yield OS.File.exists(OS.Path.join(basePath, relPath))) { if (yield IOUtils.exists(PathUtils.join(basePath, relPath))) {
numNewAttachments++; numNewAttachments++;
continue; continue;
} }
@ -821,8 +821,7 @@ Zotero_Preferences.Attachment_Base_Directory = {
updateUI: async function () { updateUI: async function () {
var filefield = document.getElementById('baseAttachmentPath'); var filefield = document.getElementById('baseAttachmentPath');
var path = Zotero.Prefs.get('baseAttachmentPath'); var path = Zotero.Prefs.get('baseAttachmentPath');
Components.utils.import("resource://gre/modules/osfile.jsm"); if (path && await IOUtils.exists(path)) {
if (await OS.File.exists(path)) {
filefield.style.backgroundImage = 'url(moz-icon://' + Zotero.File.pathToFileURI(path) + '?size=16)'; filefield.style.backgroundImage = 'url(moz-icon://' + Zotero.File.pathToFileURI(path) + '?size=16)';
filefield.value = path; filefield.value = path;
} }

View file

@ -26,7 +26,6 @@
"use strict"; "use strict";
Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://gre/modules/osfile.jsm");
var { FilePicker } = ChromeUtils.importESModule('chrome://zotero/content/modules/filePicker.mjs'); var { FilePicker } = ChromeUtils.importESModule('chrome://zotero/content/modules/filePicker.mjs');
Zotero_Preferences.General = { Zotero_Preferences.General = {
@ -153,7 +152,7 @@ Zotero_Preferences.General = {
var fp = new FilePicker(); var fp = new FilePicker();
if (currentPath && currentPath != 'system') { if (currentPath && currentPath != 'system') {
fp.displayDirectory = OS.Path.dirname(currentPath); fp.displayDirectory = PathUtils.parent(currentPath);
} }
fp.init( fp.init(
window, window,
@ -196,7 +195,7 @@ Zotero_Preferences.General = {
Zotero.logError(e); Zotero.logError(e);
} }
let handlerFilename = OS.Path.basename(handler); let handlerFilename = PathUtils.filename(handler);
if (Zotero.isMac) { if (Zotero.isMac) {
handlerFilename = handlerFilename.replace(/\.app$/, ''); handlerFilename = handlerFilename.replace(/\.app$/, '');
} }

View file

@ -25,7 +25,6 @@
"use strict"; "use strict";
Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://gre/modules/osfile.jsm");
Components.utils.import("resource://zotero/config.js"); Components.utils.import("resource://zotero/config.js");
var React = require('react'); var React = require('react');

View file

@ -74,7 +74,7 @@ Zotero.Attachments = new function () {
var newName = fileBaseName + (ext != '' ? '.' + ext : ''); var newName = fileBaseName + (ext != '' ? '.' + ext : '');
} }
else { else {
var newName = Zotero.File.getValidFileName(OS.Path.basename(leafName)); var newName = Zotero.File.getValidFileName(leafName);
} }
if (leafName.endsWith(".lnk")) { if (leafName.endsWith(".lnk")) {
@ -328,7 +328,7 @@ Zotero.Attachments = new function () {
var storageDir = Zotero.getStorageDirectory(); var storageDir = Zotero.getStorageDirectory();
destDir = this.getStorageDirectory(attachmentItem); destDir = this.getStorageDirectory(attachmentItem);
await OS.File.removeDir(destDir.path); await IOUtils.remove(destDir.path, { recursive: true, ignoreAbsent: true });
newPath = OS.Path.join(destDir.path, fileName); newPath = OS.Path.join(destDir.path, fileName);
// Copy single file to new directory // Copy single file to new directory
if (options.singleFile) { if (options.singleFile) {
@ -1747,7 +1747,7 @@ Zotero.Attachments = new function () {
attachmentItem = await this.createURLAttachmentFromTemporaryStorageDirectory({ attachmentItem = await this.createURLAttachmentFromTemporaryStorageDirectory({
directory: tmpDir, directory: tmpDir,
libraryID: item.libraryID, libraryID: item.libraryID,
filename: OS.Path.basename(tmpFile), filename: PathUtils.filename(tmpFile),
title: _getPDFTitleFromVersion(props.articleVersion), title: _getPDFTitleFromVersion(props.articleVersion),
url, url,
contentType: 'application/pdf', contentType: 'application/pdf',
@ -2454,10 +2454,13 @@ Zotero.Attachments = new function () {
return false; return false;
} }
return this.fixPathSlashes(OS.Path.join( basePath = this.fixPathSlashes(OS.Path.normalize(basePath));
OS.Path.normalize(basePath), path = this.fixPathSlashes(path);
return PathUtils.joinRelative(
basePath,
path.substr(Zotero.Attachments.BASE_PATH_PLACEHOLDER.length) path.substr(Zotero.Attachments.BASE_PATH_PLACEHOLDER.length)
)); );
} }
@ -2494,7 +2497,7 @@ Zotero.Attachments = new function () {
} }
var numFiles = 0; var numFiles = 0;
var parent = OS.Path.dirname(path); var parent = PathUtils.parent(path);
var iterator = new OS.File.DirectoryIterator(parent); var iterator = new OS.File.DirectoryIterator(parent);
try { try {
yield iterator.forEach((entry) => { yield iterator.forEach((entry) => {
@ -2546,7 +2549,7 @@ Zotero.Attachments = new function () {
} }
var numFiles = 0; var numFiles = 0;
var parent = OS.Path.dirname(path); var parent = PathUtils.parent(path);
var iterator = new OS.File.DirectoryIterator(parent); var iterator = new OS.File.DirectoryIterator(parent);
try { try {
yield iterator.forEach(function (entry) { yield iterator.forEach(function (entry) {
@ -2594,7 +2597,7 @@ Zotero.Attachments = new function () {
} }
var size = 0; var size = 0;
var parent = OS.Path.dirname(path); var parent = PathUtils.parent(path);
let iterator = new OS.File.DirectoryIterator(parent); let iterator = new OS.File.DirectoryIterator(parent);
try { try {
yield iterator.forEach(function (entry) { yield iterator.forEach(function (entry) {
@ -2737,7 +2740,7 @@ Zotero.Attachments = new function () {
var json = item.toJSON(); var json = item.toJSON();
json.linkMode = 'imported_file'; json.linkMode = 'imported_file';
delete json.path; delete json.path;
json.filename = OS.Path.basename(file); json.filename = PathUtils.filename(file);
var newItem = new Zotero.Item('attachment'); var newItem = new Zotero.Item('attachment');
newItem.libraryID = item.libraryID; newItem.libraryID = item.libraryID;
newItem.fromJSON(json); newItem.fromJSON(json);
@ -2798,9 +2801,9 @@ Zotero.Attachments = new function () {
Zotero.logError(e); Zotero.logError(e);
} }
if (newFile && json.filename != OS.Path.basename(newFile)) { if (newFile && json.filename != PathUtils.filename(newFile)) {
Zotero.debug("Filename was changed"); Zotero.debug("Filename was changed");
newItem.attachmentFilename = OS.Path.basename(newFile); newItem.attachmentFilename = PathUtils.filename(newFile);
await newItem.saveTx(); await newItem.saveTx();
} }

View file

@ -2694,6 +2694,7 @@ Zotero.Item.prototype.getFilePathAsync = Zotero.Promise.coroutine(function* () {
return file.path; return file.path;
} }
// NOTE: Test for platform slashes before changing to IOUtils.exists()
if (!(yield OS.File.exists(path))) { if (!(yield OS.File.exists(path))) {
Zotero.debug("Attachment file '" + path + "' not found", 2); Zotero.debug("Attachment file '" + path + "' not found", 2);
this._updateAttachmentStates(false); this._updateAttachmentStates(false);
@ -2803,7 +2804,7 @@ Zotero.Item.prototype.renameAttachmentFile = async function (newName, overwrite
} }
try { try {
let origName = OS.Path.basename(origPath); let origName = PathUtils.filename(origPath);
if (this.isStoredFileAttachment()) { if (this.isStoredFileAttachment()) {
var origModDate = (await OS.File.stat(origPath)).lastModificationDate; var origModDate = (await OS.File.stat(origPath)).lastModificationDate;
} }
@ -2832,7 +2833,7 @@ Zotero.Item.prototype.renameAttachmentFile = async function (newName, overwrite
if (newName === false) { if (newName === false) {
return -1; return -1;
} }
let destPath = OS.Path.join(OS.Path.dirname(origPath), newName); let destPath = OS.Path.join(PathUtils.parent(origPath), newName);
await this.relinkAttachmentFile(destPath); await this.relinkAttachmentFile(destPath);
@ -2880,7 +2881,7 @@ Zotero.Item.prototype.relinkAttachmentFile = Zotero.Promise.coroutine(function*
throw new Error('Cannot relink linked URL'); throw new Error('Cannot relink linked URL');
} }
var fileName = OS.Path.basename(path); var fileName = PathUtils.filename(path);
if (fileName.endsWith(".lnk")) { if (fileName.endsWith(".lnk")) {
throw new Error("Cannot relink to Windows shortcut"); throw new Error("Cannot relink to Windows shortcut");
} }
@ -2893,7 +2894,7 @@ Zotero.Item.prototype.relinkAttachmentFile = Zotero.Promise.coroutine(function*
// If selected file isn't in the attachment's storage directory, // If selected file isn't in the attachment's storage directory,
// copy it in and use that one instead // copy it in and use that one instead
var storageDir = Zotero.Attachments.getStorageDirectory(this).path; var storageDir = Zotero.Attachments.getStorageDirectory(this).path;
if (this.isStoredFileAttachment() && OS.Path.dirname(path) != storageDir) { if (this.isStoredFileAttachment() && PathUtils.parent(path) != storageDir) {
newPath = OS.Path.join(storageDir, newName); newPath = OS.Path.join(storageDir, newName);
// If file with same name already exists in the storage directory, // If file with same name already exists in the storage directory,
@ -2927,16 +2928,18 @@ Zotero.Item.prototype.relinkAttachmentFile = Zotero.Promise.coroutine(function*
} }
} }
else { else {
newPath = OS.Path.join(OS.Path.dirname(path), newName); newPath = OS.Path.join(PathUtils.parent(path), newName);
// Rename file to filtered name if necessary // Rename file to filtered name if necessary
if (fileName != newName) { if (fileName != newName) {
Zotero.debug("Renaming file '" + fileName + "' to '" + newName + "'"); Zotero.debug("Renaming file '" + fileName + "' to '" + newName + "'");
try { try {
yield OS.File.move(path, newPath, { noOverwrite: true }); yield IOUtils.move(path, newPath, { noOverwrite: true });
} }
catch (e) { catch (e) {
if (e instanceof OS.File.Error && e.becauseExists && fileName.normalize() == newName) { if (DOMException.isInstance(e)
&& e.name == 'NoModificationAllowedError'
&& fileName.normalize() == newName) {
// Ignore normalization differences that the filesystem ignores // Ignore normalization differences that the filesystem ignores
} }
else { else {
@ -3187,7 +3190,7 @@ Zotero.defineProperty(Zotero.Item.prototype, 'attachmentFilename', {
if (prefixedPath) { if (prefixedPath) {
return prefixedPath[1].split('/').pop(); return prefixedPath[1].split('/').pop();
} }
return OS.Path.basename(path); return PathUtils.filename(path);
}, },
set: function (val) { set: function (val) {
if (!this.isAttachment()) { if (!this.isAttachment()) {
@ -3265,7 +3268,7 @@ Zotero.defineProperty(Zotero.Item.prototype, 'attachmentPath', {
if (!val.startsWith(storagePath)) { if (!val.startsWith(storagePath)) {
throw new Error("Imported file path must be within storage directory"); throw new Error("Imported file path must be within storage directory");
} }
val = 'storage:' + OS.Path.basename(val); val = 'storage:' + PathUtils.filename(val);
} }
} }

View file

@ -65,13 +65,7 @@ Zotero.DataDirectory = {
} }
// Absolute path // Absolute path
else { else {
// Ignore non-absolute paths if (!PathUtils.isAbsolute(dir)) {
if ("winIsAbsolute" in OS.Path) {
if (!OS.Path.winIsAbsolute(dir)) {
dir = false;
}
}
else if (!dir.startsWith('/')) {
dir = false; dir = false;
} }
if (!dir) { if (!dir) {
@ -79,7 +73,7 @@ Zotero.DataDirectory = {
} }
// Require parent directory to exist // Require parent directory to exist
if (!(yield OS.File.exists(OS.Path.dirname(dir)))) { if (!(yield OS.File.exists(PathUtils.parent(dir)))) {
throw `Parent directory of -datadir ${dir} not found`; throw `Parent directory of -datadir ${dir} not found`;
} }
@ -104,9 +98,9 @@ Zotero.DataDirectory = {
nsIFile.persistentDescriptor = prefVal; nsIFile.persistentDescriptor = prefVal;
} }
catch (e) { catch (e) {
Zotero.debug("Persistent descriptor in extensions.zotero.dataDir did not resolve", 1); let msg = "Persistent descriptor in extensions.zotero.dataDir did not resolve";
e = { name: "NS_ERROR_FILE_NOT_FOUND" }; Zotero.debug(msg, 1);
throw e; throw new DOMException(msg, 'NotFoundError');
} }
// This removes lastDataDir // This removes lastDataDir
this.set(nsIFile.path); this.set(nsIFile.path);
@ -127,8 +121,9 @@ Zotero.DataDirectory = {
} }
catch (e) { catch (e) {
Zotero.logError(e); Zotero.logError(e);
Zotero.debug(`Invalid marker file:\n\n${contents}`, 1); let msg = `Invalid marker file:\n\n${contents}`;
throw { name: "NS_ERROR_FILE_NOT_FOUND" }; Zotero.debug(msg, 1);
throw new DOMException(msg, 'NotFoundError');
} }
} }
else { else {
@ -137,8 +132,9 @@ Zotero.DataDirectory = {
} }
catch (e) { catch (e) {
Zotero.logError(e); Zotero.logError(e);
Zotero.debug(`Invalid path '${prefVal}' in dataDir pref`, 1); let msg = `Invalid path '${prefVal}' in dataDir pref`;
throw { name: "NS_ERROR_FILE_NOT_FOUND" }; Zotero.debug(msg, 1);
throw new DOMException(msg, 'NotFoundError');
} }
} }
} }
@ -156,8 +152,9 @@ Zotero.DataDirectory = {
} }
// For other custom directories that don't exist, show not-found dialog // For other custom directories that don't exist, show not-found dialog
else { else {
Zotero.debug(`Custom data directory ${dataDir} not found`, 1); let msg = `Custom data directory ${dataDir} not found`;
throw { name: "NS_ERROR_FILE_NOT_FOUND" }; Zotero.debug(msg, 1);
throw new DOMException(msg, 'NotFoundError');
} }
} }
@ -194,7 +191,7 @@ Zotero.DataDirectory = {
// one does and it contains a database // one does and it contains a database
try { try {
if ((yield Zotero.Profile.findOtherProfilesUsingDataDirectory(dataDir, false)).length) { if ((yield Zotero.Profile.findOtherProfilesUsingDataDirectory(dataDir, false)).length) {
let profileName = OS.Path.basename(Zotero.Profile.dir).match(/[^.]+\.(.+)/)[1]; let profileName = PathUtils.filename(Zotero.Profile.dir).match(/[^.]+\.(.+)/)[1];
let newDataDir = this.defaultDir + ' ' + profileName; let newDataDir = this.defaultDir + ' ' + profileName;
if (!(yield OS.File.exists(newDataDir)) if (!(yield OS.File.exists(newDataDir))
|| (yield OS.File.exists(OS.Path.join(newDataDir, dbFilename)))) { || (yield OS.File.exists(OS.Path.join(newDataDir, dbFilename)))) {
@ -224,13 +221,13 @@ Zotero.DataDirectory = {
try { try {
let dir = OS.Path.join(Zotero.Profile.dir, this.legacyDirName); let dir = OS.Path.join(Zotero.Profile.dir, this.legacyDirName);
let dbFile = OS.Path.join(dir, dbFilename); let dbFile = OS.Path.join(dir, dbFilename);
profileSubdirModTime = (yield OS.File.stat(dbFile)).lastModificationDate; profileSubdirModTime = new Date((yield IOUtils.stat(dbFile)).lastModified);
Zotero.debug(`Database found at ${dbFile}, last modified ${profileSubdirModTime}`); Zotero.debug(`Database found at ${dbFile}, last modified ${profileSubdirModTime}`);
dataDir = dir; dataDir = dir;
useProfile = true; useProfile = true;
} }
catch (e) { catch (e) {
if (!(e instanceof OS.File.Error && e.becauseNoSuchFile)) { if (e.name != 'NotFoundError') {
throw e; throw e;
} }
} }
@ -242,7 +239,7 @@ Zotero.DataDirectory = {
// Get default profile in Firefox dir // Get default profile in Firefox dir
let defProfile; let defProfile;
let profilesDir = Zotero.Profile.getOtherAppProfilesDir(); let profilesDir = Zotero.Profile.getOtherAppProfilesDir();
let profilesParent = profilesDir ? OS.Path.dirname(profilesDir) : null; let profilesParent = profilesDir ? PathUtils.parent(profilesDir) : null;
if (profilesParent) { if (profilesParent) {
Zotero.debug("Looking for Firefox profile in " + profilesParent); Zotero.debug("Looking for Firefox profile in " + profilesParent);
try { try {
@ -276,14 +273,15 @@ Zotero.DataDirectory = {
catch (e) { catch (e) {
Zotero.logError(e); Zotero.logError(e);
if (!useProfile) { if (!useProfile) {
Zotero.debug("Persistent descriptor in extensions.zotero.dataDir " let msg = "Persistent descriptor in extensions.zotero.dataDir "
+ "did not resolve", 1); + "did not resolve";
throw { name: "NS_ERROR_FILE_NOT_FOUND" }; Zotero.debug(msg, 1);
throw new DOMException(msg, 'NotFoundError');
} }
} }
try { try {
let dbFile = OS.Path.join(nsIFile.path, dbFilename); let dbFile = OS.Path.join(nsIFile.path, dbFilename);
let mtime = (yield OS.File.stat(dbFile)).lastModificationDate; let mtime = new Date((yield IOUtils.stat(dbFile)).lastModified);
Zotero.debug(`Database found at ${dbFile}, last modified ${mtime}`); Zotero.debug(`Database found at ${dbFile}, last modified ${mtime}`);
// If custom location has a newer DB, use that // If custom location has a newer DB, use that
if (!useProfile || mtime > profileSubdirModTime) { if (!useProfile || mtime > profileSubdirModTime) {
@ -311,7 +309,7 @@ Zotero.DataDirectory = {
try { try {
let dir = OS.Path.join(profileDir, this.legacyDirName); let dir = OS.Path.join(profileDir, this.legacyDirName);
let dbFile = OS.Path.join(dir, dbFilename); let dbFile = OS.Path.join(dir, dbFilename);
let mtime = (yield OS.File.stat(dbFile)).lastModificationDate; let mtime = new Date((yield IOUtils.stat(dbFile)).lastModified);
Zotero.debug(`Database found at ${dbFile}, last modified ${mtime}`); Zotero.debug(`Database found at ${dbFile}, last modified ${mtime}`);
// If newer than Zotero profile directory, use this one // If newer than Zotero profile directory, use this one
if (!useProfile || mtime > profileSubdirModTime) { if (!useProfile || mtime > profileSubdirModTime) {
@ -323,7 +321,7 @@ Zotero.DataDirectory = {
// Legacy subdirectory doesn't exist or there was a problem accessing it, so // Legacy subdirectory doesn't exist or there was a problem accessing it, so
// just fall through to default location // just fall through to default location
catch (e) { catch (e) {
if (!(e instanceof OS.File.Error && e.becauseNoSuchFile)) { if (e.name != 'NotFoundError') {
Zotero.logError(e); Zotero.logError(e);
Zotero.fxProfileAccessError = true; Zotero.fxProfileAccessError = true;
} }
@ -461,7 +459,7 @@ Zotero.DataDirectory = {
while (true) { while (true) {
let fp = new FilePicker(); let fp = new FilePicker();
fp.init(win, Zotero.getString('dataDir.selectDir'), fp.modeGetFolder); fp.init(win, Zotero.getString('dataDir.selectDir'), fp.modeGetFolder);
fp.displayDirectory = this._dir ? this._dir : OS.Path.dirname(this.defaultDir); fp.displayDirectory = this._dir ? this._dir : PathUtils.parent(this.defaultDir);
fp.appendFilters(fp.filterAll); fp.appendFilters(fp.filterAll);
if (await fp.show() == fp.returnOK) { if (await fp.show() == fp.returnOK) {
let file = Zotero.File.pathToFile(fp.file); let file = Zotero.File.pathToFile(fp.file);
@ -471,7 +469,7 @@ Zotero.DataDirectory = {
// If set to 'storage', offer to use the parent directory // If set to 'storage', offer to use the parent directory
if (await this.isStorageDirectory(file.path)) { if (await this.isStorageDirectory(file.path)) {
let buttonFlags = ps.STD_YES_NO_BUTTONS; let buttonFlags = ps.STD_YES_NO_BUTTONS;
let parentPath = OS.Path.dirname(file.path); let parentPath = PathUtils.parent(file.path);
let index = ps.confirmEx( let index = ps.confirmEx(
null, null,
Zotero.getString('general.error'), Zotero.getString('general.error'),
@ -653,11 +651,11 @@ Zotero.DataDirectory = {
isLegacy: function (dir) { isLegacy: function (dir) {
// 'zotero' // 'zotero'
return OS.Path.basename(dir) == this.legacyDirName return PathUtils.filename(dir) == this.legacyDirName
// '69pmactz.default' // '69pmactz.default'
&& OS.Path.basename(OS.Path.dirname(dir)).match(/^[0-9a-z]{8}\..+/) && PathUtils.filename(PathUtils.parent(dir)).match(/^[0-9a-z]{8}\..+/)
// 'Profiles' // 'Profiles'
&& OS.Path.basename(OS.Path.dirname(OS.Path.dirname(dir))) == 'Profiles'; && PathUtils.filename(PathUtils.parent(PathUtils.parent(dir))) == 'Profiles';
}, },
@ -693,10 +691,10 @@ Zotero.DataDirectory = {
isStorageDirectory: async function (dir) { isStorageDirectory: async function (dir) {
if (OS.Path.basename(dir) != 'storage') { if (PathUtils.filename(dir) != 'storage') {
return false; return false;
} }
let sqlitePath = OS.Path.join(OS.Path.dirname(dir), 'zotero.sqlite'); let sqlitePath = OS.Path.join(PathUtils.parent(dir), 'zotero.sqlite');
return OS.File.exists(sqlitePath); return OS.File.exists(sqlitePath);
}, },
@ -724,7 +722,7 @@ Zotero.DataDirectory = {
if (Zotero.Prefs.get('ignoreLegacyDataDir.auto') || Zotero.Prefs.get('ignoreLegacyDataDir.explicit')) return; if (Zotero.Prefs.get('ignoreLegacyDataDir.auto') || Zotero.Prefs.get('ignoreLegacyDataDir.explicit')) return;
try { try {
let profilesDir = Zotero.Profile.getOtherAppProfilesDir(); let profilesDir = Zotero.Profile.getOtherAppProfilesDir();
let profilesParent = profilesDir ? OS.Path.dirname(profilesDir) : null; let profilesParent = profilesDir ? PathUtils.parent(profilesDir) : null;
if (!profilesParent) { if (!profilesParent) {
return; return;
} }
@ -750,13 +748,13 @@ Zotero.DataDirectory = {
try { try {
dir = OS.Path.join(profileDir, this.legacyDirName); dir = OS.Path.join(profileDir, this.legacyDirName);
let dbFile = OS.Path.join(dir, this.getDatabaseFilename()); let dbFile = OS.Path.join(dir, this.getDatabaseFilename());
let info = await OS.File.stat(dbFile); let info = await IOUtils.stat(dbFile);
if (info.size < 1200000) { if (info.size < 1200000) {
Zotero.debug(`Legacy database is ${info.size} bytes -- ignoring`); Zotero.debug(`Legacy database is ${info.size} bytes -- ignoring`);
Zotero.Prefs.set('ignoreLegacyDataDir.auto', true); Zotero.Prefs.set('ignoreLegacyDataDir.auto', true);
return; return;
} }
mtime = info.lastModificationDate; mtime = new Date(info.lastModified);
if (mtime < new Date(2017, 6, 1)) { if (mtime < new Date(2017, 6, 1)) {
Zotero.debug(`Legacy database was last modified on ${mtime.toString()} -- ignoring`); Zotero.debug(`Legacy database was last modified on ${mtime.toString()} -- ignoring`);
Zotero.Prefs.set('ignoreLegacyDataDir.auto', true); Zotero.Prefs.set('ignoreLegacyDataDir.auto', true);
@ -766,7 +764,7 @@ Zotero.DataDirectory = {
} }
catch (e) { catch (e) {
Zotero.Prefs.set('ignoreLegacyDataDir.auto', true); Zotero.Prefs.set('ignoreLegacyDataDir.auto', true);
if (e.becauseNoSuchFile) { if (e.name == 'NotFoundError') {
return; return;
} }
throw e; throw e;
@ -921,8 +919,8 @@ Zotero.DataDirectory = {
let otherProfiles = yield Zotero.Profile.findOtherProfilesUsingDataDirectory(dataDir); let otherProfiles = yield Zotero.Profile.findOtherProfilesUsingDataDirectory(dataDir);
// 'touch' each prefs.js file to make sure we can access it // 'touch' each prefs.js file to make sure we can access it
for (let dir of otherProfiles) { for (let dir of otherProfiles) {
let prefs = OS.Path.join(dir, "prefs.js"); let prefsFile = OS.Path.join(dir, "prefs.js");
yield OS.File.setDates(prefs); yield IOUtils.setModificationTime(prefsFile);
} }
} }
catch (e) { catch (e) {
@ -1132,11 +1130,11 @@ Zotero.DataDirectory = {
// Create the new directory // Create the new directory
if (!partial) { if (!partial) {
yield OS.File.makeDir( yield IOUtils.makeDirectory(
newDir, newDir,
{ {
ignoreExisting: false, ignoreExisting: false,
unixMode: 0o755 permissions: 0o755
} }
); );
} }
@ -1201,7 +1199,7 @@ Zotero.DataDirectory = {
allowExistingTarget: true, allowExistingTarget: true,
// Don't overwrite root files (except for hidden files like .DS_Store) // Don't overwrite root files (except for hidden files like .DS_Store)
noOverwrite: path => { noOverwrite: path => {
return OS.Path.dirname(path) == oldDir && !OS.Path.basename(path).startsWith('.') return PathUtils.parent(path) == oldDir && !PathUtils.filename(path).startsWith('.')
}, },
} }
)); ));

View file

@ -75,7 +75,7 @@ Zotero.DBConnection = function(dbNameOrPath) {
// Absolute path to DB // Absolute path to DB
if (dbNameOrPath.startsWith('/') || (Zotero.isWin && dbNameOrPath.includes('\\'))) { if (dbNameOrPath.startsWith('/') || (Zotero.isWin && dbNameOrPath.includes('\\'))) {
this._dbName = OS.Path.basename(dbNameOrPath).replace(/\.sqlite$/, ''); this._dbName = PathUtils.filename(dbNameOrPath).replace(/\.sqlite$/, '');
this._dbPath = dbNameOrPath; this._dbPath = dbNameOrPath;
this._externalDB = true; this._externalDB = true;
} }
@ -1043,7 +1043,7 @@ Zotero.DBConnection.prototype.backupDatabase = async function (suffix, force) {
} }
catch (e) { catch (e) {
if (e.name == 'NS_ERROR_FILE_ACCESS_DENIED') { if (e.name == 'NS_ERROR_FILE_ACCESS_DENIED') {
alert("Cannot delete " + OS.Path.basename(tmpFile)); alert("Cannot delete " + PathUtils.filename(tmpFile));
} }
throw (e); throw (e);
} }
@ -1057,7 +1057,7 @@ Zotero.DBConnection.prototype.backupDatabase = async function (suffix, force) {
} }
storageService.backupDatabaseFile( storageService.backupDatabaseFile(
Zotero.File.pathToFile(file), Zotero.File.pathToFile(file),
OS.Path.basename(tmpFile), PathUtils.filename(tmpFile),
Zotero.File.pathToFile(file).parent Zotero.File.pathToFile(file).parent
); );
} }
@ -1077,7 +1077,7 @@ Zotero.DBConnection.prototype.backupDatabase = async function (suffix, force) {
} }
catch (e) { catch (e) {
Zotero.logError(e); Zotero.logError(e);
this._debug("Database file '" + OS.Path.basename(tmpFile) + "' can't be opened -- skipping backup"); this._debug("Database file '" + PathUtils.filename(tmpFile) + "' can't be opened -- skipping backup");
if (await OS.File.exists(tmpFile)) { if (await OS.File.exists(tmpFile)) {
await OS.File.remove(tmpFile); await OS.File.remove(tmpFile);
} }
@ -1115,8 +1115,8 @@ Zotero.DBConnection.prototype.backupDatabase = async function (suffix, force) {
continue; continue;
} }
Zotero.debug("Moving " + OS.Path.basename(sourceFile) Zotero.debug("Moving " + PathUtils.filename(sourceFile)
+ " to " + OS.Path.basename(targetFile)); + " to " + PathUtils.filename(targetFile));
await OS.File.move(sourceFile, targetFile); await OS.File.move(sourceFile, targetFile);
} }
} }
@ -1129,7 +1129,7 @@ Zotero.DBConnection.prototype.backupDatabase = async function (suffix, force) {
} }
await OS.File.move(tmpFile, backupFile); await OS.File.move(tmpFile, backupFile);
Zotero.debug("Backed up to " + OS.Path.basename(backupFile)); Zotero.debug("Backed up to " + PathUtils.filename(backupFile));
return true; return true;
} }
@ -1251,7 +1251,7 @@ Zotero.DBConnection.prototype._checkException = async function (e) {
const supportURL = 'https://zotero.org/support/kb/corrupted_database'; const supportURL = 'https://zotero.org/support/kb/corrupted_database';
var filename = OS.Path.basename(this._dbPath); var filename = PathUtils.filename(this._dbPath);
// Skip backups // Skip backups
this._dbIsCorrupt = true; this._dbIsCorrupt = true;
@ -1310,7 +1310,7 @@ Zotero.DBConnection.prototype._checkException = async function (e) {
*/ */
Zotero.DBConnection.prototype._handleCorruptionMarker = async function () { Zotero.DBConnection.prototype._handleCorruptionMarker = async function () {
var file = this._dbPath; var file = this._dbPath;
var fileName = OS.Path.basename(file); var fileName = PathUtils.filename(file);
var backupFile = this._dbPath + '.bak'; var backupFile = this._dbPath + '.bak';
var corruptMarker = this._dbPath + '.is.corrupt'; var corruptMarker = this._dbPath + '.is.corrupt';
@ -1348,7 +1348,7 @@ Zotero.DBConnection.prototype._handleCorruptionMarker = async function () {
Zotero.getString('startupError', Zotero.appName), Zotero.getString('startupError', Zotero.appName),
Zotero.getString( Zotero.getString(
'db.dbCorruptedNoBackup', 'db.dbCorruptedNoBackup',
[Zotero.appName, fileName, OS.Path.basename(damagedFile)] [Zotero.appName, fileName, PathUtils.filename(damagedFile)]
) )
); );
} }
@ -1380,7 +1380,7 @@ Zotero.DBConnection.prototype._handleCorruptionMarker = async function () {
Zotero.getString('general.error'), Zotero.getString('general.error'),
Zotero.getString( Zotero.getString(
'db.dbRestoreFailed', 'db.dbRestoreFailed',
[Zotero.appName, fileName, OS.Path.basename(damagedFile)] [Zotero.appName, fileName, PathUtils.filename(damagedFile)]
) )
); );
@ -1423,7 +1423,7 @@ Zotero.DBConnection.prototype._handleCorruptionMarker = async function () {
Zotero.getString('general.warning'), Zotero.getString('general.warning'),
Zotero.getString( Zotero.getString(
'db.dbRestored', 'db.dbRestored',
[Zotero.appName, fileName, backupDate, backupTime, OS.Path.basename(damagedFile)] [Zotero.appName, fileName, backupDate, backupTime, PathUtils.filename(damagedFile)]
) + '\n\n' ) + '\n\n'
+ Zotero.getString('db.dbRestored.cloudStorage') + Zotero.getString('db.dbRestored.cloudStorage')
); );

View file

@ -56,23 +56,18 @@ Zotero.Dictionaries = new function () {
if (!(await OS.File.exists(dictionariesDir))) { if (!(await OS.File.exists(dictionariesDir))) {
return; return;
} }
let iterator = new OS.File.DirectoryIterator(dictionariesDir);
try { for (let path of await IOUtils.getChildren(dictionariesDir)) {
await iterator.forEach(async function (entry) { let filename = PathUtils.filename(path);
if (entry.name.startsWith('.')) { if (filename.startsWith('.')) {
return; continue;
} }
try { try {
let dir = OS.Path.join(dictionariesDir, entry.name); await _loadDirectory(path);
await _loadDirectory(dir);
} }
catch (e) { catch (e) {
Zotero.logError(e); Zotero.logError(e);
} }
});
}
finally {
iterator.close();
} }
}; };

View file

@ -104,9 +104,9 @@ Zotero.File = new function(){
} }
} }
var dir = OS.Path.dirname(file); var dir = PathUtils.parent(file);
while (dir && dir != '/' && !await OS.File.exists(dir)) { while (dir && dir != '/' && !await OS.File.exists(dir)) {
dir = OS.Path.dirname(dir); dir = PathUtils.parent(dir);
} }
return (dir && dir != '/') ? dir : false; return (dir && dir != '/') ? dir : false;
@ -523,7 +523,7 @@ Zotero.File = new function(){
var unique = options.unique || false; var unique = options.unique || false;
var origPath = file; var origPath = file;
var origName = OS.Path.basename(origPath); var origName = PathUtils.filename(origPath);
newName = Zotero.File.getValidFileName(newName); newName = Zotero.File.getValidFileName(newName);
// Ignore if no change // Ignore if no change
@ -538,9 +538,9 @@ Zotero.File = new function(){
overwrite = true; overwrite = true;
} }
var parentDir = OS.Path.dirname(origPath); var parentDir = PathUtils.parent(origPath);
var destPath = OS.Path.join(parentDir, newName); var destPath = OS.Path.join(parentDir, newName);
var destName = OS.Path.basename(destPath); var destName = PathUtils.filename(destPath);
// Get root + extension, if there is one // Get root + extension, if there is one
var pos = destName.lastIndexOf('.'); var pos = destName.lastIndexOf('.');
if (pos > 0) { if (pos > 0) {
@ -566,7 +566,7 @@ Zotero.File = new function(){
} }
try { try {
Zotero.debug(`Renaming ${origPath} to ${OS.Path.basename(destPath)}`); Zotero.debug(`Renaming ${origPath} to ${PathUtils.filename(destPath)}`);
Zotero.debug(destPath); Zotero.debug(destPath);
await OS.File.move(origPath, destPath, { noOverwrite: !overwrite }) await OS.File.move(origPath, destPath, { noOverwrite: !overwrite })
} }
@ -686,14 +686,11 @@ Zotero.File = new function(){
// Throw certain known errors (no more disk space) to interrupt the operation // Throw certain known errors (no more disk space) to interrupt the operation
function checkError(e) { function checkError(e) {
if (!(e instanceof OS.File.Error)) { if (!(DOMException.isInstance(e))) {
return; return;
} }
Components.classes["@mozilla.org/net/osfileconstantsservice;1"] // DEBUG: Test this
.getService(Components.interfaces.nsIOSFileConstantsService) if (e.name == 'NotReadableError' && e.message.includes('Target device is full')) {
.init();
if ((e.unixErrno !== undefined && e.unixErrno == OS.Constants.libc.ENOSPC)
|| (e.winLastError !== undefined && e.winLastError == OS.Constants.libc.ENOSPC)) {
throw e; throw e;
} }
} }
@ -765,19 +762,12 @@ Zotero.File = new function(){
} }
// If can't use command, try moving with OS.File.move(). Technically this is // If can't use command, try moving with IOUtils.move()
// unsupported for directories, but it works on all platforms as long as noCopy
// is set (and on some platforms regardless)
if (!moved && useFunction) { if (!moved && useFunction) {
Zotero.debug(`Moving ${entry.path} with OS.File`); Zotero.debug(`Moving ${entry.path} with IOUtils`);
if (!await IOUtils.exists(dest)) {
try { try {
await OS.File.move( await IOUtils.move(entry.path, dest);
entry.path,
dest,
{
noCopy: true
}
);
moved = true; moved = true;
} }
catch (e) { catch (e) {
@ -785,6 +775,7 @@ Zotero.File = new function(){
Zotero.debug(e, 1); Zotero.debug(e, 1);
} }
} }
}
// Otherwise, recurse into subdirectories to copy files individually // Otherwise, recurse into subdirectories to copy files individually
if (!moved) { if (!moved) {
@ -830,7 +821,7 @@ Zotero.File = new function(){
throw new Error("contentType not provided"); throw new Error("contentType not provided");
} }
var buf = await OS.File.read(file, {}); var buf = await IOUtils.read(file);
buf = new Uint8Array(buf).buffer; buf = new Uint8Array(buf).buffer;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let blob = new Blob([buf], { type: contentType }); let blob = new Blob([buf], { type: contentType });
@ -846,19 +837,19 @@ Zotero.File = new function(){
}; };
this.setNormalFilePermissions = function (file) { this.setNormalFilePermissions = async function (path) {
return OS.File.setPermissions( await IOUtils.setPermissions(path, 0o644);
file, if (Zotero.isWin) {
await IOUtils.setWindowsAttributes(
path,
{ {
unixMode: 0o644,
winAttributes: {
readOnly: false, readOnly: false,
hidden: false, hidden: false,
system: false system: false
} }
}
); );
} };
};
this.createShortened = function (file, type, mode, maxBytes) { this.createShortened = function (file, type, mode, maxBytes) {
@ -982,7 +973,7 @@ Zotero.File = new function(){
* @return {String} - Path of new file * @return {String} - Path of new file
*/ */
this.moveToUnique = async function (file, newFile) { this.moveToUnique = async function (file, newFile) {
var targetDir = OS.Path.dirname(newFile); var targetDir = PathUtils.parent(newFile);
var newNSIFile = this.pathToFile(newFile); var newNSIFile = this.pathToFile(newFile);
newNSIFile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0o644); newNSIFile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0o644);
@ -1193,7 +1184,7 @@ Zotero.File = new function(){
return false; return false;
} }
Zotero.debug(`Creating ${OS.Path.basename(zipPath)} with ${entries.length} file(s)`); Zotero.debug(`Creating ${PathUtils.filename(zipPath)} with ${entries.length} file(s)`);
var context = { var context = {
zipWriter: zw, zipWriter: zw,
@ -1409,7 +1400,11 @@ Zotero.File = new function(){
// These show up on some Windows systems // These show up on some Windows systems
|| e.name == 'NS_ERROR_FAILURE' || e.name == 'NS_ERROR_FILE_NOT_FOUND' || e.name == 'NS_ERROR_FAILURE' || e.name == 'NS_ERROR_FILE_NOT_FOUND'
// OS.File.Error // OS.File.Error
|| e.becauseAccessDenied || e.becauseNoSuchFile) { || e.becauseAccessDenied || e.becauseNoSuchFile
// IOUtils
|| e.name == 'NotAllowedError'
|| e.name == 'ReadOnlyError'
|| e.name == 'NotFoundError') {
let checkFileWindows = Zotero.getString('file.accessError.message.windows'); let checkFileWindows = Zotero.getString('file.accessError.message.windows');
let checkFileOther = Zotero.getString('file.accessError.message.other'); let checkFileOther = Zotero.getString('file.accessError.message.other');
let msg = str + "\n\n" let msg = str + "\n\n"
@ -1440,7 +1435,7 @@ Zotero.File = new function(){
this.getEvictedICloudPath = function (path) { this.getEvictedICloudPath = function (path) {
return OS.Path.join(OS.Path.dirname(path), '.' + OS.Path.basename(path) + '.icloud'); return OS.Path.join(PathUtils.parent(path), '.' + PathUtils.filename(path) + '.icloud');
}; };
@ -1487,7 +1482,7 @@ Zotero.File = new function(){
let info = yield OS.File.stat(file); let info = yield OS.File.stat(file);
// Launch parent directory for files // Launch parent directory for files
if (!info.isDir) { if (!info.isDir) {
file = OS.Path.dirname(file); file = PathUtils.parent(file);
} }
Zotero.launchFile(file); Zotero.launchFile(file);
} }

View file

@ -159,7 +159,7 @@ Zotero.FileHandlers = {
} }
try { try {
if (await OS.File.exists(handler)) { if (await IOUtils.exists(handler)) {
Zotero.debug(`Opening with handler ${handler}`); Zotero.debug(`Opening with handler ${handler}`);
Zotero.launchFileWithApplication(path, handler); Zotero.launchFileWithApplication(path, handler);
return true; return true;
@ -222,7 +222,7 @@ Zotero.FileHandlers = {
'-e', `tell app "${appPath}" to open "${filePath}"` '-e', `tell app "${appPath}" to open "${filePath}"`
]; ];
if (page !== undefined) { if (page !== undefined) {
let filename = OS.Path.basename(filePath) let filename = PathUtils.filename(filePath)
.replace(quoteRE, '\\"'); .replace(quoteRE, '\\"');
args.push('-e', `tell document "${filename}" of application "${appPath}" to go to page ${page}`); args.push('-e', `tell document "${filename}" of application "${appPath}" to go to page ${page}`);
} }
@ -316,10 +316,10 @@ Zotero.FileHandlers = {
appPath = '/usr/bin/evince'; appPath = '/usr/bin/evince';
} }
} }
else if (await OS.File.exists('/usr/bin/okular')) { else if (await IOUtils.exists('/usr/bin/okular')) {
appPath = '/usr/bin/okular'; appPath = '/usr/bin/okular';
} }
else if (await OS.File.exists('/usr/bin/evince')) { else if (await IOUtils.exists('/usr/bin/evince')) {
appPath = '/usr/bin/evince'; appPath = '/usr/bin/evince';
} }
else { else {

View file

@ -376,7 +376,7 @@ Zotero.Fulltext = Zotero.FullText = new function(){
var parentDirPath = await Zotero.Attachments.createDirectoryForItem(item); var parentDirPath = await Zotero.Attachments.createDirectoryForItem(item);
} }
else { else {
var parentDirPath = OS.Path.dirname(filePath); var parentDirPath = PathUtils.parent(filePath);
} }
var cacheFilePath = OS.Path.join(parentDirPath, this.fulltextCacheFile); var cacheFilePath = OS.Path.join(parentDirPath, this.fulltextCacheFile);
try { try {
@ -831,7 +831,7 @@ Zotero.Fulltext = Zotero.FullText = new function(){
var itemCacheFile = this.getItemCacheFile(item).path; // .zotero-ft-cache var itemCacheFile = this.getItemCacheFile(item).path; // .zotero-ft-cache
// If a storage directory doesn't exist, create it // If a storage directory doesn't exist, create it
if (!(yield OS.File.exists(OS.Path.dirname(processorCacheFile)))) { if (!(yield OS.File.exists(PathUtils.parent(processorCacheFile)))) {
yield Zotero.Attachments.createDirectoryForItem(item); yield Zotero.Attachments.createDirectoryForItem(item);
} }
@ -1645,7 +1645,7 @@ Zotero.Fulltext = Zotero.FullText = new function(){
} }
var cacheFile = this.getItemCacheFile(item).path; var cacheFile = this.getItemCacheFile(item).path;
Zotero.debug("Writing converted full-text content to " + cacheFile); Zotero.debug("Writing converted full-text content to " + cacheFile);
if (!await OS.File.exists(OS.Path.dirname(cacheFile))) { if (!await OS.File.exists(PathUtils.parent(cacheFile))) {
await Zotero.Attachments.createDirectoryForItem(item); await Zotero.Attachments.createDirectoryForItem(item);
} }
try { try {

View file

@ -474,7 +474,7 @@ Zotero.LocateManager = new function() {
if (await OS.File.exists(iconFile)) { if (await OS.File.exists(iconFile)) {
for (let i = 0; await OS.File.exists(iconFile); i++) { for (let i = 0; await OS.File.exists(iconFile); i++) {
iconFile = OS.Path.join( iconFile = OS.Path.join(
OS.Path.dirname(iconFile), PathUtils.parent(iconFile),
sanitizedAlias + "_" + i + "." + extension sanitizedAlias + "_" + i + "." + extension
); );
} }

View file

@ -24,8 +24,7 @@
*/ */
"use strict"; "use strict";
var { OS } = ChromeUtils.importESModule("chrome://zotero/content/osfile.mjs");
Components.utils.import("resource://gre/modules/osfile.jsm");
Zotero.Profile = { Zotero.Profile = {
dir: OS.Constants.Path.profileDir, dir: OS.Constants.Path.profileDir,
@ -87,7 +86,7 @@ Zotero.Profile = {
getProfilesDir: function () { getProfilesDir: function () {
return OS.Path.dirname(this.dir); return PathUtils.parent(this.dir);
}, },
@ -97,13 +96,13 @@ Zotero.Profile = {
* @return {String|null} - Path, or null if none due to filesystem location * @return {String|null} - Path, or null if none due to filesystem location
*/ */
getOtherAppProfilesDir: function () { getOtherAppProfilesDir: function () {
var dir = OS.Path.dirname(OS.Path.dirname(OS.Path.dirname(this.dir))); var dir = PathUtils.parent(PathUtils.parent(PathUtils.parent(this.dir)));
if (dir === '' || dir == '.') { if (dir === '' || dir == '.') {
return null; return null;
} }
if (Zotero.isWin) { if (Zotero.isWin) {
dir = OS.Path.join(OS.Path.dirname(dir), "Mozilla", "Firefox"); dir = OS.Path.join(PathUtils.parent(dir), "Mozilla", "Firefox");
} }
else if (Zotero.isMac) { else if (Zotero.isMac) {
dir = OS.Path.join(dir, "Firefox"); dir = OS.Path.join(dir, "Firefox");
@ -143,7 +142,7 @@ Zotero.Profile = {
// to the list, which addresses the situation where the source directory is a custom // to the list, which addresses the situation where the source directory is a custom
// location for the current profile but is a default in the other app (meaning it wouldn't // location for the current profile but is a default in the other app (meaning it wouldn't
// be added above). // be added above).
let dataDirParent = OS.Path.dirname(dataDir); let dataDirParent = PathUtils.parent(dataDir);
if (otherAppProfiles.includes(dataDirParent) && !otherProfiles.includes(dataDirParent)) { if (otherAppProfiles.includes(dataDirParent) && !otherProfiles.includes(dataDirParent)) {
otherProfiles.push(dataDirParent); otherProfiles.push(dataDirParent);
} }
@ -199,7 +198,7 @@ Zotero.Profile = {
if (!profilesDir) { if (!profilesDir) {
return true; return true;
} }
let profilesParent = OS.Path.dirname(profilesDir); let profilesParent = PathUtils.parent(profilesDir);
Zotero.debug("Looking for Firefox profile in " + profilesParent); Zotero.debug("Looking for Firefox profile in " + profilesParent);
let defProfile = await this.getDefaultInProfilesDir(profilesParent); let defProfile = await this.getDefaultInProfilesDir(profilesParent);
if (defProfile) { if (defProfile) {

View file

@ -284,7 +284,7 @@ Zotero.RecognizeDocument = new function () {
var originalTitle = attachment.getField('title'); var originalTitle = attachment.getField('title');
var path = attachment.getFilePath(); var path = attachment.getFilePath();
var originalFilename = OS.Path.basename(path); var originalFilename = PathUtils.filename(path);
// Rename attachment file to match new metadata // Rename attachment file to match new metadata
if (Zotero.Attachments.shouldAutoRenameFile(attachment.attachmentLinkMode == Zotero.Attachments.LINK_MODE_LINKED_FILE)) { if (Zotero.Attachments.shouldAutoRenameFile(attachment.attachmentLinkMode == Zotero.Attachments.LINK_MODE_LINKED_FILE)) {
@ -405,7 +405,7 @@ Zotero.RecognizeDocument = new function () {
async function _recognizePDF(item, filePath) { async function _recognizePDF(item, filePath) {
let json = await extractPDFJSON(item.id); let json = await extractPDFJSON(item.id);
json.fileName = OS.Path.basename(filePath); json.fileName = PathUtils.filename(filePath);
let containingTextPages = 0; let containingTextPages = 0;

View file

@ -327,12 +327,9 @@ Zotero.Sync.Storage.Local = {
Zotero.debug("Marking pathless attachment " + lk + " as in-sync"); Zotero.debug("Marking pathless attachment " + lk + " as in-sync");
return this.SYNC_STATE_IN_SYNC; return this.SYNC_STATE_IN_SYNC;
} }
var fileName = OS.Path.basename(path); var fileName = PathUtils.filename(path);
var file;
try { try {
file = yield OS.File.open(path);
// If file is already marked for upload, skip check. Even if the file was changed // If file is already marked for upload, skip check. Even if the file was changed
// both locally and remotely, conflicts are checked at upload time, so we don't need // both locally and remotely, conflicts are checked at upload time, so we don't need
// to worry about it here. // to worry about it here.
@ -343,10 +340,9 @@ Zotero.Sync.Storage.Local = {
return false; return false;
} }
let info = yield file.stat(); let { lastModified: fmtime } = yield IOUtils.stat(path);
//Zotero.debug("Memory usage: " + memmgr.resident); //Zotero.debug("Memory usage: " + memmgr.resident);
let fmtime = info.lastModificationDate.getTime();
//Zotero.debug("File modification time for item " + lk + " is " + fmtime); //Zotero.debug("File modification time for item " + lk + " is " + fmtime);
if (fmtime < 0) { if (fmtime < 0) {
@ -365,20 +361,15 @@ Zotero.Sync.Storage.Local = {
} }
// If file hash matches stored hash, only the mod time changed, so skip // If file hash matches stored hash, only the mod time changed, so skip
let fileHash = yield Zotero.Utilities.Internal.md5Async(file); let fileHash = yield Zotero.Utilities.Internal.md5Async(path);
var hash = attachmentData ? attachmentData.hash : (yield this.getSyncedHash(item.id)); var hash = attachmentData ? attachmentData.hash : (yield this.getSyncedHash(item.id));
if (hash && hash == fileHash) { if (hash && hash == fileHash) {
// We have to close the file before modifying it from the main
// thread (at least on Windows, where assigning lastModifiedTime
// throws an NS_ERROR_FILE_IS_LOCKED otherwise)
yield file.close();
Zotero.debug("Mod time didn't match (" + fmtime + " != " + mtime + ") " Zotero.debug("Mod time didn't match (" + fmtime + " != " + mtime + ") "
+ "but hash did for " + fileName + " for item " + lk + "but hash did for " + fileName + " for item " + lk
+ " -- updating file mod time"); + " -- updating file mod time");
try { try {
yield OS.File.setDates(path, null, mtime); yield IOUtils.setModificationTime(path, mtime);
} }
catch (e) { catch (e) {
Zotero.File.checkFileAccessError(e, path, 'update'); Zotero.File.checkFileAccessError(e, path, 'update');
@ -392,47 +383,17 @@ Zotero.Sync.Storage.Local = {
return this.SYNC_STATE_TO_UPLOAD; return this.SYNC_STATE_TO_UPLOAD;
} }
catch (e) { catch (e) {
if (e instanceof OS.File.Error) { if (DOMException.isInstance(e)) {
let missing = e.becauseNoSuchFile let missing = e.name == 'NotFoundError';
// ERROR_PATH_NOT_FOUND: This can happen if a path is too long on Windows, e.g. a
// file is being accessed on a VM through a share (and probably in other cases)
|| e.winLastError == 3
// ERROR_INVALID_NAME: This can happen if there's a colon in the name from before
// we were filtering
|| e.winLastError == 123
// ERROR_BAD_PATHNAME
|| e.winLastError == 161;
if (!missing) {
Components.classes["@mozilla.org/net/osfileconstantsservice;1"]
.getService(Components.interfaces.nsIOSFileConstantsService)
.init();
missing = e.unixErrno == OS.Constants.libc.ENOTDIR
// Handle long filenames on OS X/Linux
|| e.unixErrno == OS.Constants.libc.ENAMETOOLONG;
}
if (missing) { if (missing) {
if (!e.becauseNoSuchFile) {
Zotero.debug(e, 1);
}
Zotero.debug("Marking attachment " + lk + " as missing"); Zotero.debug("Marking attachment " + lk + " as missing");
return this.SYNC_STATE_TO_DOWNLOAD; return this.SYNC_STATE_TO_DOWNLOAD;
} }
if (e.becauseClosed) {
Zotero.debug("File was closed", 2);
}
Zotero.debug(e, 1); Zotero.debug(e, 1);
Zotero.debug(e.unixErrno, 1);
Zotero.debug(e.winLastError, 1);
throw new Error(`Error for operation '${e.operation}' for ${path}: ${e}`); throw new Error(`Error for operation '${e.operation}' for ${path}: ${e}`);
} }
throw e; throw e;
} }
finally {
if (file) {
//Zotero.debug("Closing file for item " + lk);
file.close();
}
}
}), }),
/** /**
@ -723,7 +684,7 @@ Zotero.Sync.Storage.Local = {
} }
var path = OS.Path.join(attachmentDir, filename); var path = OS.Path.join(attachmentDir, filename);
Zotero.debug("Moving download file " + OS.Path.basename(tempFilePath) Zotero.debug("Moving download file " + PathUtils.filename(tempFilePath)
+ ` into attachment directory as '${filename}'`); + ` into attachment directory as '${filename}'`);
try { try {
var finalFilename = Zotero.File.createShortened( var finalFilename = Zotero.File.createShortened(
@ -882,7 +843,7 @@ Zotero.Sync.Storage.Local = {
Zotero.debug(msg, 2); Zotero.debug(msg, 2);
Components.utils.reportError(msg); Components.utils.reportError(msg);
filePath = itemFileName; filePath = itemFileName;
destPath = OS.Path.join(OS.Path.dirname(destPath), itemFileName); destPath = OS.Path.join(PathUtils.parent(destPath), itemFileName);
renamed = true; renamed = true;
primaryFile = true; primaryFile = true;
} }
@ -915,8 +876,8 @@ Zotero.Sync.Storage.Local = {
Zotero.File.checkFileAccessError(e, destPath, 'create'); Zotero.File.checkFileAccessError(e, destPath, 'create');
} }
if (OS.Path.basename(destPath) != shortened) { if (PathUtils.filename(destPath) != shortened) {
Zotero.debug(`Changed filename '${OS.Path.basename(destPath)}' to '${shortened}'`); Zotero.debug(`Changed filename '${PathUtils.filename(destPath)}' to '${shortened}'`);
// Abort if Windows path limitation would cause filenames to be overly truncated // Abort if Windows path limitation would cause filenames to be overly truncated
if (Zotero.isWin && shortened < 40) { if (Zotero.isWin && shortened < 40) {
@ -936,7 +897,7 @@ Zotero.Sync.Storage.Local = {
throw new Error(msg); throw new Error(msg);
} }
destPath = OS.Path.join(OS.Path.dirname(destPath), shortened); destPath = OS.Path.join(PathUtils.parent(destPath), shortened);
if (primaryFile) { if (primaryFile) {
renamed = true; renamed = true;
@ -955,7 +916,7 @@ Zotero.Sync.Storage.Local = {
// For advertising junk files, ignore a bug on Windows where // For advertising junk files, ignore a bug on Windows where
// destFile.create() works but zipReader.extract() doesn't // destFile.create() works but zipReader.extract() doesn't
// when the path length is close to 255. // when the path length is close to 255.
if (OS.Path.basename(destPath).match(/[a-zA-Z0-9+=]{130,}/)) { if (PathUtils.filename(destPath).match(/[a-zA-Z0-9+=]{130,}/)) {
var msg = "Ignoring error extracting '" + destPath + "'"; var msg = "Ignoring error extracting '" + destPath + "'";
Zotero.debug(msg, 2); Zotero.debug(msg, 2);
Zotero.debug(e, 2); Zotero.debug(e, 2);

View file

@ -41,7 +41,7 @@ Zotero.Sync.Storage.Utilities = {
zipFile, zipFile,
{ {
onStopRequest: function (req, context, status) { onStopRequest: function (req, context, status) {
var zipFileName = OS.Path.basename(zipFile); var zipFileName = PathUtils.filename(zipFile);
var originalSize = 0; var originalSize = 0;
for (let entry of context.entries) { for (let entry of context.entries) {

View file

@ -66,10 +66,7 @@ Zotero.Sync.Storage.Mode.ZFS.prototype = {
// saveURI() below appears not to create empty files for Content-Length: 0, // saveURI() below appears not to create empty files for Content-Length: 0,
// so we create one here just in case, which also lets us check file access // so we create one here just in case, which also lets us check file access
try { try {
let file = yield OS.File.open(destPath, { yield IOUtils.write(destPath, new Uint8Array());
truncate: true
});
file.close();
} }
catch (e) { catch (e) {
Zotero.File.checkFileAccessError(e, destPath, 'create'); Zotero.File.checkFileAccessError(e, destPath, 'create');
@ -367,7 +364,7 @@ Zotero.Sync.Storage.Mode.ZFS.prototype = {
var funcName = "Zotero.Sync.Storage.ZFS._getFileUploadParameters()"; var funcName = "Zotero.Sync.Storage.ZFS._getFileUploadParameters()";
var path = item.getFilePath(); var path = item.getFilePath();
var filename = OS.Path.basename(path); var filename = PathUtils.filename(path);
var zip = yield this._isZipUpload(item); var zip = yield this._isZipUpload(item);
if (zip) { if (zip) {
var uploadPath = OS.Path.join(Zotero.getTempDirectory().path, item.key + '.zip'); var uploadPath = OS.Path.join(Zotero.getTempDirectory().path, item.key + '.zip');
@ -430,7 +427,7 @@ Zotero.Sync.Storage.Mode.ZFS.prototype = {
}; };
if (zip) { if (zip) {
params.zipMD5 = yield Zotero.Utilities.Internal.md5Async(uploadPath); params.zipMD5 = yield Zotero.Utilities.Internal.md5Async(uploadPath);
params.zipFilename = OS.Path.basename(uploadPath); params.zipFilename = PathUtils.filename(uploadPath);
} }
var body = []; var body = [];
for (let i in params) { for (let i in params) {

View file

@ -636,7 +636,7 @@ Zotero.Style = function (style, path) {
if (path) { if (path) {
this.path = path; this.path = path;
this.fileName = OS.Path.basename(path); this.fileName = PathUtils.filename(path);
} }
else { else {
this.string = style; this.string = style;
@ -934,7 +934,7 @@ Zotero.Style.prototype.remove = Zotero.Promise.coroutine(function* () {
// copy dependent styles to hidden directory // copy dependent styles to hidden directory
let hiddenDir = OS.Path.join(Zotero.getStylesDirectory().path, 'hidden'); let hiddenDir = OS.Path.join(Zotero.getStylesDirectory().path, 'hidden');
yield Zotero.File.createDirectoryIfMissingAsync(hiddenDir); yield Zotero.File.createDirectoryIfMissingAsync(hiddenDir);
yield OS.File.move(this.path, OS.Path.join(hiddenDir, OS.Path.basename(this.path))); yield OS.File.move(this.path, OS.Path.join(hiddenDir, PathUtils.filename(this.path)));
} else { } else {
// remove defunct files // remove defunct files
yield OS.File.remove(this.path); yield OS.File.remove(this.path);

View file

@ -386,7 +386,7 @@ Zotero.Sync.Runner_Module = function (options = {}) {
Zotero.getString('general.warning'), Zotero.getString('general.warning'),
Zotero.getString( Zotero.getString(
'account.warning.emptyLibrary', 'account.warning.emptyLibrary',
[Zotero.clientName, OS.Path.basename(Zotero.DB.path)] [Zotero.clientName, PathUtils.filename(Zotero.DB.path)]
) + "\n\n" ) + "\n\n"
+ Zotero.getString( + Zotero.getString(
'account.warning.emptyLibrary.dataWillBeDownloaded', 'account.warning.emptyLibrary.dataWillBeDownloaded',

View file

@ -326,7 +326,7 @@ Zotero.Translators = new function() {
return this.load(infoRe.exec(source)[0], path, source); return this.load(infoRe.exec(source)[0], path, source);
} }
catch (e) { catch (e) {
throw new Error("Invalid or missing translator metadata JSON object in " + OS.Path.basename(path)); throw new Error("Invalid or missing translator metadata JSON object in " + PathUtils.filename(path));
} }
} }

View file

@ -559,7 +559,7 @@ Zotero.Utilities.Internal = {
encodingFlags |= nsIWBP.ENCODE_FLAGS_ENCODE_BASIC_ENTITIES; encodingFlags |= nsIWBP.ENCODE_FLAGS_ENCODE_BASIC_ENTITIES;
// Save auxiliary files to the same folder // Save auxiliary files to the same folder
filesFolder = OS.Path.dirname(destFile); filesFolder = PathUtils.parent(destFile);
} }
const wrapColumn = 80; const wrapColumn = 80;

View file

@ -276,7 +276,7 @@ Services.scriptloader.loadSubScript("resource://zotero/polyfill.js");
} }
catch (e) { catch (e) {
// Zotero dir not found // Zotero dir not found
if ((e instanceof OS.File.Error && e.becauseNoSuchFile) || e.name == 'NS_ERROR_FILE_NOT_FOUND') { if (e.name == 'NotFoundError') {
let foundInDefault = false; let foundInDefault = false;
try { try {
foundInDefault = (await OS.File.exists(Zotero.DataDirectory.defaultDir)) foundInDefault = (await OS.File.exists(Zotero.DataDirectory.defaultDir))
@ -781,8 +781,8 @@ Services.scriptloader.loadSubScript("resource://zotero/polyfill.js");
let dbfile = Zotero.DataDirectory.getDatabase(); let dbfile = Zotero.DataDirectory.getDatabase();
// Test write access on Zotero data directory // Test write access on Zotero data directory
if (!Zotero.File.pathToFile(OS.Path.dirname(dbfile)).isWritable()) { if (!Zotero.File.pathToFile(PathUtils.parent(dbfile)).isWritable()) {
var msg = 'Cannot write to ' + OS.Path.dirname(dbfile) + '/'; var msg = 'Cannot write to ' + PathUtils.parent(dbfile) + '/';
} }
// Test write access on Zotero database // Test write access on Zotero database
else if (!Zotero.File.pathToFile(dbfile).isWritable()) { else if (!Zotero.File.pathToFile(dbfile).isWritable()) {

View file

@ -4530,7 +4530,7 @@ var ZoteroPane = new function()
} }
); );
// Update path in case the name was changed to be unique // Update path in case the name was changed to be unique
file = OS.Path.join(OS.Path.dirname(file), newName); file = PathUtils.join(PathUtils.parent(file), newName);
} }
} }
catch (e) { catch (e) {
@ -4953,7 +4953,7 @@ var ZoteroPane = new function()
); );
return; return;
} }
let fileExists = await OS.File.exists(path); let fileExists = await IOUtils.exists(path);
// If the file is an evicted iCloud Drive file, launch that to trigger a download. // If the file is an evicted iCloud Drive file, launch that to trigger a download.
// As of 10.13.6, launching an .icloud file triggers the download and opens the // As of 10.13.6, launching an .icloud file triggers the download and opens the
@ -4964,7 +4964,7 @@ var ZoteroPane = new function()
if (!fileExists && Zotero.isMac && isLinkedFile) { if (!fileExists && Zotero.isMac && isLinkedFile) {
// Get the path to the .icloud file // Get the path to the .icloud file
let iCloudPath = Zotero.File.getEvictedICloudPath(path); let iCloudPath = Zotero.File.getEvictedICloudPath(path);
if (await OS.File.exists(iCloudPath)) { if (await IOUtils.exists(iCloudPath)) {
Zotero.debug("Triggering download of iCloud file"); Zotero.debug("Triggering download of iCloud file");
await launchFile(iCloudPath, item); await launchFile(iCloudPath, item);
let time = new Date(); let time = new Date();
@ -4995,7 +4995,7 @@ var ZoteroPane = new function()
// Wait a bit for the download and check again // Wait a bit for the download and check again
await Zotero.Promise.delay(250); await Zotero.Promise.delay(250);
Zotero.debug("Checking for downloaded file"); Zotero.debug("Checking for downloaded file");
if (await OS.File.exists(path)) { if (await IOUtils.exists(path)) {
Zotero.debug("File is ready"); Zotero.debug("File is ready");
fileExists = true; fileExists = true;
break; break;
@ -5112,12 +5112,12 @@ var ZoteroPane = new function()
if (attachment.attachmentLinkMode == Zotero.Attachments.LINK_MODE_LINKED_URL) return; if (attachment.attachmentLinkMode == Zotero.Attachments.LINK_MODE_LINKED_URL) return;
var path = attachment.getFilePath(); var path = attachment.getFilePath();
var fileExists = await OS.File.exists(path); var fileExists = await IOUtils.exists(path);
// If file doesn't exist but an evicted iCloud Drive file does, reveal that instead // If file doesn't exist but an evicted iCloud Drive file does, reveal that instead
if (!fileExists && Zotero.isMac && !attachment.isStoredFileAttachment()) { if (!fileExists && Zotero.isMac && !attachment.isStoredFileAttachment()) {
let iCloudPath = Zotero.File.getEvictedICloudPath(path); let iCloudPath = Zotero.File.getEvictedICloudPath(path);
if (await OS.File.exists(iCloudPath)) { if (await IOUtils.exists(iCloudPath)) {
path = iCloudPath; path = iCloudPath;
fileExists = true; fileExists = true;
} }
@ -5777,8 +5777,8 @@ var ZoteroPane = new function()
if (rv === fp.returnOK || rv === fp.returnReplace) { if (rv === fp.returnOK || rv === fp.returnReplace) {
let folder = fp.file; let folder = fp.file;
for (let item of items) { for (let item of items) {
let outputFile = OS.Path.join(folder, item.attachmentFilename); let outputFile = PathUtils.join(folder, item.attachmentFilename);
if (await OS.File.exists(outputFile)) { if (await IOUtils.exists(outputFile)) {
let newNSIFile = Zotero.File.pathToFile(outputFile); let newNSIFile = Zotero.File.pathToFile(outputFile);
newNSIFile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0o644); newNSIFile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0o644);
outputFile = newNSIFile.path; outputFile = newNSIFile.path;
@ -5963,7 +5963,7 @@ var ZoteroPane = new function()
return false; return false;
} }
// We can't use OS.Path.dirname because that function expects paths valid for the current platform... // We can't use PathUtils.parent because that function expects paths valid for the current platform...
// but we can't normalize first because we're going to be comparing it to other un-normalized paths // but we can't normalize first because we're going to be comparing it to other un-normalized paths
let unNormalizedDirname = item.getFilePath(); let unNormalizedDirname = item.getFilePath();
let lastSlash = Math.max( let lastSlash = Math.max(
@ -5978,7 +5978,7 @@ var ZoteroPane = new function()
for (let segmentsToDrop = 0; segmentsToDrop < parts.length; segmentsToDrop++) { for (let segmentsToDrop = 0; segmentsToDrop < parts.length; segmentsToDrop++) {
let correctedPath = join(basePath, ...parts.slice(segmentsToDrop)); let correctedPath = join(basePath, ...parts.slice(segmentsToDrop));
if (!(await OS.File.exists(correctedPath))) { if (!(await IOUtils.exists(correctedPath))) {
Zotero.debug('Does not exist: ' + correctedPath); Zotero.debug('Does not exist: ' + correctedPath);
continue; continue;
} }
@ -6001,7 +6001,7 @@ var ZoteroPane = new function()
.slice(segmentsToDrop); .slice(segmentsToDrop);
if (!otherParts.length) continue; if (!otherParts.length) continue;
let otherCorrectedPath = join(basePath, ...otherParts); let otherCorrectedPath = join(basePath, ...otherParts);
if (await OS.File.exists(otherCorrectedPath)) { if (await IOUtils.exists(otherCorrectedPath)) {
if (Zotero.isWin) { if (Zotero.isWin) {
otherCorrectedPath = otherCorrectedPath.replace(/\//g, '\\'); otherCorrectedPath = otherCorrectedPath.replace(/\//g, '\\');
} }

View file

@ -34,7 +34,6 @@ const ZOTERO_PROTOCOL_NAME = "Zotero Chrome Extension Protocol";
Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://gre/modules/ComponentUtils.jsm"); Components.utils.import("resource://gre/modules/ComponentUtils.jsm");
Components.utils.import("resource://gre/modules/osfile.jsm")
const { NetUtil } = ChromeUtils.import("resource://gre/modules/NetUtil.jsm"); const { NetUtil } = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
const Cc = Components.classes; const Cc = Components.classes;

View file

@ -73,7 +73,6 @@ ZoteroCommandLineHandler.prototype = {
} }
// See below // See below
else if (uri.schemeIs("file")) { else if (uri.schemeIs("file")) {
Components.utils.import("resource://gre/modules/osfile.jsm")
fileToOpen = OS.Path.fromFileURI(uri.spec) fileToOpen = OS.Path.fromFileURI(uri.spec)
} }
else { else {

View file

@ -13,7 +13,7 @@ chai.config.truncateThreshold = 0
function quit(failed) { function quit(failed) {
// Quit with exit status // Quit with exit status
if(!failed) { if(!failed) {
OS.File.writeAtomic(OS.Path.join(OS.Constants.Path.profileDir, "success"), new Uint8Array(0)); IOUtils.write(PathUtils.join(FileUtils.getDir("ProfD", []).path, "success"), new Uint8Array(0));
} }
if(!TestOptions.noquit) { if(!TestOptions.noquit) {
setTimeout(function () { setTimeout(function () {
@ -64,8 +64,8 @@ if (TestOptions.makeTestData) {
if (!first) dump('\n'); if (!first) dump('\n');
dump('Generating data for ' + params.name + '...'); dump('Generating data for ' + params.name + '...');
let filePath = OS.Path.join(dataPath, params.name + '.js'); let filePath = PathUtils.join(dataPath, params.name + '.js');
let exists = yield OS.File.exists(filePath); let exists = yield IOUtils.exists(filePath);
let currentData; let currentData;
if (exists) { if (exists) {
currentData = loadSampleData(params.name); currentData = loadSampleData(params.name);
@ -79,8 +79,8 @@ if (TestOptions.makeTestData) {
} }
let str = stableStringify(newData); let str = stableStringify(newData);
yield OS.File.writeAtomic(OS.Path.join(dataPath, params.name + '.js'), str); yield IOUtils.writeUTF8(PathUtils.join(dataPath, params.name + '.js'), str);
dump('\nWritten to ' + OS.Path.join(dataPath, params.name + '.js\n')); dump('\nWritten to ' + PathUtils.join(dataPath, params.name + '.js\n'));
} }
dump("\n"); dump("\n");
})() })()
@ -286,7 +286,7 @@ if(run) {
// Make a copy of the database that can be used in resetDB() // Make a copy of the database that can be used in resetDB()
var dbFile = Zotero.DataDirectory.getDatabase(); var dbFile = Zotero.DataDirectory.getDatabase();
await OS.File.copy(dbFile, dbFile + '-test-template'); await IOUtils.copy(dbFile, dbFile + '-test-template');
initPDFToolsPath(); initPDFToolsPath();

View file

@ -599,10 +599,10 @@ function initPDFToolsPath() {
pdfInfoFileName += '-linux-' + cpu; pdfInfoFileName += '-linux-' + cpu;
} }
let pdfToolsPath = OS.Path.join(Zotero.Profile.dir, 'pdftools'); let pdfToolsPath = PathUtils.join(Zotero.Profile.dir, 'pdftools');
let pdfConverterPath = OS.Path.join(pdfToolsPath, pdfConvertedFileName); let pdfConverterPath = PathUtils.join(pdfToolsPath, pdfConvertedFileName);
let pdfInfoPath = OS.Path.join(pdfToolsPath, pdfInfoFileName); let pdfInfoPath = PathUtils.join(pdfToolsPath, pdfInfoFileName);
let pdfDataPath = OS.Path.join(pdfToolsPath, 'poppler-data'); let pdfDataPath = PathUtils.join(pdfToolsPath, 'poppler-data');
Zotero.FullText.setPDFConverterPath(pdfConverterPath); Zotero.FullText.setPDFConverterPath(pdfConverterPath);
Zotero.FullText.setPDFInfoPath(pdfInfoPath); Zotero.FullText.setPDFInfoPath(pdfInfoPath);
@ -636,9 +636,9 @@ var getTempDirectory = Zotero.Promise.coroutine(function* getTempDirectory() {
attempts = 3, attempts = 3,
zoteroTmpDirPath = Zotero.getTempDirectory().path; zoteroTmpDirPath = Zotero.getTempDirectory().path;
while (attempts--) { while (attempts--) {
path = OS.Path.join(zoteroTmpDirPath, Zotero.Utilities.randomString()); path = PathUtils.join(zoteroTmpDirPath, Zotero.Utilities.randomString());
try { try {
yield OS.File.makeDir(path, { ignoreExisting: false }); yield IOUtils.makeDirectory(path, { ignoreExisting: false });
break; break;
} catch (e) { } catch (e) {
if (!attempts) throw e; // Throw on last attempt if (!attempts) throw e; // Throw on last attempt
@ -685,7 +685,7 @@ async function resetDB(options = {}) {
// Otherwise swap in the initial copy we made of the DB, or an alternative non-zip file // Otherwise swap in the initial copy we made of the DB, or an alternative non-zip file
// if given // if given
else { else {
await OS.File.copy(options.dbFile || db + '-test-template', db); await IOUtils.copy(options.dbFile || db + '-test-template', db);
} }
_defaultGroup = null; _defaultGroup = null;
}, },
@ -1048,7 +1048,7 @@ async function createAnnotation(type, parentItem, options = {}) {
async function createEmbeddedImage(parentItem, options = {}) { async function createEmbeddedImage(parentItem, options = {}) {
var attachment = await Zotero.Attachments.importEmbeddedImage({ var attachment = await Zotero.Attachments.importEmbeddedImage({
blob: await File.createFromFileName( blob: await File.createFromFileName(
OS.Path.join(getTestDataDirectory().path, 'test.png') PathUtils.join(getTestDataDirectory().path, 'test.png')
), ),
parentItemID: parentItem.id parentItemID: parentItem.id
}); });
@ -1061,7 +1061,7 @@ async function createEmbeddedImage(parentItem, options = {}) {
async function getImageBlob() { async function getImageBlob() {
var path = OS.Path.join(getTestDataDirectory().path, 'test.png'); var path = PathUtils.join(getTestDataDirectory().path, 'test.png');
var imageData = await Zotero.File.getBinaryContentsAsync(path); var imageData = await Zotero.File.getBinaryContentsAsync(path);
var array = new Uint8Array(imageData.length); var array = new Uint8Array(imageData.length);
for (let i = 0; i < imageData.length; i++) { for (let i = 0; i < imageData.length; i++) {

View file

@ -1,5 +1,4 @@
new function() { new function() {
Components.utils.import("resource://gre/modules/osfile.jsm");
Components.utils.import("resource://zotero-unit/httpd.js"); Components.utils.import("resource://zotero-unit/httpd.js");
const { HiddenBrowser } = ChromeUtils.import('chrome://zotero/content/HiddenBrowser.jsm'); const { HiddenBrowser } = ChromeUtils.import('chrome://zotero/content/HiddenBrowser.jsm');

View file

@ -373,12 +373,8 @@ describe("Zotero.Sync.Storage.Mode.WebDAV", function () {
Zotero.getTempDirectory().path, Zotero.getTempDirectory().path,
Zotero.Utilities.randomString() + '.zip' Zotero.Utilities.randomString() + '.zip'
); );
let file = yield OS.File.open(tmpZipPath, { let contents = new Uint8Array(reader.result);
create: true yield IOUtils.write(tmpZipPath, contents);
});
var contents = new Uint8Array(reader.result);
yield file.write(contents);
yield file.close();
// Make sure ZIP file contains the necessary entries // Make sure ZIP file contains the necessary entries
var zr = Components.classes["@mozilla.org/libjar/zip-reader;1"] var zr = Components.classes["@mozilla.org/libjar/zip-reader;1"]

View file

@ -512,15 +512,9 @@ describe("Zotero.Sync.Storage.Mode.ZFS", function () {
var reader = new FileReader(); var reader = new FileReader();
reader.addEventListener("loadend", Zotero.Promise.coroutine(function* () { reader.addEventListener("loadend", Zotero.Promise.coroutine(function* () {
try { try {
let contents = new Uint8Array(reader.result);
let file = yield OS.File.open(tmpZipPath, {
create: true
});
var contents = new Uint8Array(reader.result);
contents = contents.slice(prefix2.length, suffix2.length * -1); contents = contents.slice(prefix2.length, suffix2.length * -1);
yield file.write(contents); yield IOUtils.write(tmpZipPath, contents);
yield file.close();
var zr = Components.classes["@mozilla.org/libjar/zip-reader;1"] var zr = Components.classes["@mozilla.org/libjar/zip-reader;1"]
.createInstance(Components.interfaces.nsIZipReader); .createInstance(Components.interfaces.nsIZipReader);