Revision control
Copy as Markdown
Other Tools
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
/* notice that these valuse are octal. */
const PERM_IRWXU = 0o700; /* read, write, execute/search by owner */
const PERM_IRUSR = 0o400; /* read permission, owner */
const PERM_IWUSR = 0o200; /* write permission, owner */
const PERM_IXUSR = 0o100; /* execute/search permission, owner */
const PERM_IRWXG = 0o070; /* read, write, execute/search by group */
const PERM_IRGRP = 0o040; /* read permission, group */
const PERM_IWGRP = 0o020; /* write permission, group */
const PERM_IXGRP = 0o010; /* execute/search permission, group */
const PERM_IRWXO = 0o007; /* read, write, execute/search by others */
const PERM_IROTH = 0o004; /* read permission, others */
const PERM_IWOTH = 0o002; /* write permission, others */
const PERM_IXOTH = 0o001; /* execute/search permission, others */
const MODE_RDONLY = 0x01;
const MODE_WRONLY = 0x02;
const MODE_RDWR = 0x04;
const MODE_CREATE = 0x08;
const MODE_APPEND = 0x10;
const MODE_TRUNCATE = 0x20;
const MODE_SYNC = 0x40;
const MODE_EXCL = 0x80;
var futils = {};
futils.umask = PERM_IWOTH | PERM_IWGRP;
futils.lastSaveAsDir = null;
futils.lastOpenDir = null;
/**
* Internal function used by |pickSaveAs|, |pickOpen| and |pickGetFolder|.
*
* @param initialPath (*defaultDir* in |pick| functions) Sets the
* initial directory for the dialog. The user may browse
* to any other directory - it does not restrict anything.
* @param typeList Optional. An |Array| or space-separated string of allowed
* file types for the dialog. An item in the array may be a
* string (used as title and filter) or a two-element array
* (title and filter, respectively); when using a string,
* the following standard filters may be used: |$all|, |$html|,
* |$text|, |$images|, |$xml|, |$xul|, |$noAll| (prevents "All
* Files" filter being included).
* @param defaultString Optional. Sets the initial/default filename.
* @returns An |Object| with |ok| (Boolean), |file| (|nsIFile|) and
* |picker| (|nsIFilePicker|) properties.
*/
futils.getPicker = function (initialPath, typeList, defaultString) {
let picker = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
if (defaultString) {
picker.defaultString = defaultString;
}
if (initialPath) {
picker.displayDirectory = returnFile(initialPath);
}
let includeAll = true;
if (!typeList) {
typeList = [];
}
for (let type of typeList) {
switch (type[0]) {
case "$all":
picker.appendFilters(Ci.nsIFilePicker.filterAll);
includeAll = false;
break;
case "$noAll":
includeAll = false;
break;
case "$html":
picker.appendFilters(Ci.nsIFilePicker.filterHTML);
break;
case "$text":
picker.appendFilters(Ci.nsIFilePicker.filterText);
break;
case "$images":
picker.appendFilters(Ci.nsIFilePicker.filterImages);
break;
case "$xml":
picker.appendFilters(Ci.nsIFilePicker.filterXML);
break;
case "$xul":
picker.appendFilters(Ci.nsIFilePicker.filterXUL);
break;
default:
/* type should always be a pair but check anyway. */
let extns = type.length > 1 ? type[1] : "*.*";
picker.appendFilter(type[0], extns);
break;
}
}
if (includeAll) {
picker.appendFilters(Ci.nsIFilePicker.filterAll);
}
return picker;
};
function getPickerChoice(picker) {
var obj = {};
obj.picker = picker;
obj.ok = false;
obj.file = null;
try {
obj.reason = picker.show();
} catch (ex) {
dd("caught exception from file picker: " + ex);
return obj;
}
if (obj.reason != Ci.nsIFilePicker.returnCancel) {
obj.file = picker.file;
obj.ok = true;
}
return obj;
}
/**
* Displays a standard file save dialog.
*
* @param title Optional. The title for the dialog.
* @param typeList Optional. See |futils.getPicker| for details.
* @param defaultFile Optional. See |futils.getPicker| for details.
* @returns An |Object| with "ok" (Boolean), "file" (|nsIFile|) and
* "picker" (|nsIFilePicker|) properties.
*/
function pickSaveAs(title, typeList, defaultFile) {
let picker = futils.getPicker(futils.lastSaveAsDir, typeList, defaultFile);
picker.init(window, title, Ci.nsIFilePicker.modeSave);
var rv = getPickerChoice(picker);
if (rv.ok) {
futils.lastSaveAsDir = picker.file.parent;
}
return rv;
}
/**
* Displays a standard file open dialog.
*
* @param title Optional. The title for the dialog.
* @param typeList Optional. See |futils.getPicker| for details.
* @returns An |Object| with "ok" (Boolean), "file" (|nsIFile|) and
* "picker" (|nsIFilePicker|) properties.
*/
function pickOpen(title, typeList) {
let picker = futils.getPicker(futils.lastOpenDir, typeList);
picker.init(window, title, Ci.nsIFilePicker.modeOpen);
var rv = getPickerChoice(picker);
if (rv.ok) {
futils.lastOpenDir = picker.file.parent;
}
return rv;
}
/**
* Displays a standard directory selection dialog.
*
* @param title Optional. The title for the dialog.
* @param defaultDir Optional. See |futils.getPicker| for details.
* @returns An |Object| with "ok" (Boolean), "file" (|nsIFile|) and
* "picker" (|nsIFilePicker|) properties.
*/
function pickGetFolder(title, defaultDir) {
let picker = futils.getPicker(defaultDir ? defaultDir : futils.lastOpenDir);
picker.init(window, title, Ci.nsIFilePicker.modeGetFolder);
var rv = getPickerChoice(picker);
if (rv.ok) {
futils.lastOpenDir = picker.file;
}
return rv;
}
function mkdir(localFile) {
localFile.create(Ci.nsIFile.DIRECTORY_TYPE, 0o766 & ~futils.umask);
}
function getTempFile(path, name) {
var tempFile = new nsLocalFile(path);
tempFile.append(name);
tempFile.createUnique(0, 0o600);
return tempFile;
}
function nsLocalFile(path) {
let localFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
localFile.initWithPath(path);
return localFile;
}
function returnFile(file) {
if (typeof file == "string") {
return new nsLocalFile(file);
}
if (isinstance(file, Ci.nsIFile)) {
return file;
}
throw Components.Exception(
"bad type for argument |file|.",
Cr.NS_ERROR_INVALID_ARG
);
}
function LocalFile(file, mode) {
let perms = 0o666 & ~futils.umask;
if (typeof mode == "string") {
switch (mode) {
case ">":
mode = MODE_WRONLY | MODE_CREATE | MODE_TRUNCATE;
break;
case ">>":
mode = MODE_WRONLY | MODE_CREATE | MODE_APPEND;
break;
case "<":
mode = MODE_RDONLY;
break;
default:
throw Components.Exception(
"Invalid mode ``" + mode + "''",
Cr.NS_ERROR_INVALID_ARG
);
}
}
this.localFile = returnFile(file);
this.path = this.localFile.path;
if (mode & (MODE_WRONLY | MODE_RDWR)) {
this.outputStream = Cc[
"@mozilla.org/network/file-output-stream;1"
].createInstance(Ci.nsIFileOutputStream);
this.outputStream.init(this.localFile, mode, perms, 0);
}
if (mode & (MODE_RDONLY | MODE_RDWR)) {
this.baseInputStream = Cc[
"@mozilla.org/network/file-input-stream;1"
].createInstance(Ci.nsIFileInputStream);
this.baseInputStream.init(this.localFile, mode, perms, 0);
this.inputStream = Cc[
"@mozilla.org/scriptableinputstream;1"
].createInstance(Ci.nsIScriptableInputStream);
this.inputStream.init(this.baseInputStream);
}
}
LocalFile.prototype.write = function (buf) {
if (!("outputStream" in this)) {
throw Components.Exception(
"file not open for writing.",
Cr.NS_ERROR_FAILURE
);
}
return this.outputStream.write(buf, buf.length);
};
// Will return null if there is no more data in the file.
// Will block until it has some data to return.
// Will return an empty string if there is data, but it couldn't be read.
LocalFile.prototype.read = function (max) {
if (!("inputStream" in this)) {
throw Components.Exception(
"file not open for reading.",
Cr.NS_ERROR_FAILURE
);
}
if (typeof max == "undefined") {
max = this.inputStream.available();
}
try {
var rv = this.inputStream.read(max);
return rv != "" ? rv : null;
} catch (ex) {
return "";
}
};
LocalFile.prototype.close = function () {
if ("outputStream" in this) {
this.outputStream.close();
}
if ("inputStream" in this) {
this.inputStream.close();
}
};
LocalFile.prototype.flush = function () {
return this.outputStream.flush();
};