Skip to content

Instantly share code, notes, and snippets.

@brettz9
Forked from yajd/profilistCoreFunc.js
Created July 6, 2014 01:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brettz9/30ef4c0d4ed3bcb33066 to your computer and use it in GitHub Desktop.
Save brettz9/30ef4c0d4ed3bcb33066 to your computer and use it in GitHub Desktop.
var me = Services.wm.getMostRecentWindow(null);
Cu.import('resource://gre/modules/osfile.jsm');
var pathProfilesIni = OS.Path.join(OS.Constants.Path.userApplicationDataDir, 'profiles.ini');
me.alert(pathProfilesIni);
//apparently theres for profiles made in default prof dir:
//localDir = C:\Users\ali57233\AppData\Local\Mozilla\Firefox\Profiles\czbm1ps9.rnd1
//rootDir = C:\Users\ali57233\AppData\Roaming\Mozilla\Firefox\Profiles\czbm1ps9.rnd1
//for custom prof dir localDir and rootDir are same
var ini = {};
function readIni() {
let decoder = new TextDecoder(); // This decoder can be reused for several reads
let promise = OS.File.read(pathProfilesIni); // Read the complete file as an array
promise = promise.then(
function onSuccess(ArrayBuffer) {
var readStr = decoder.decode(ArrayBuffer); // Convert this array to a text
console.log(readStr);
ini = {};
var patt = /\[(.*?)(\d*?)\](?:\s+?([\S]+)=([\S]+))(?:\s+?([\S]+)=([\S]+))?(?:\s+?([\S]+)=([\S]+))?(?:\s+?([\S]+)=([\S]+))?(?:\s+?([\S]+)=([\S]+))?/mg;
var blocks = [];
var match;
while (match = patt.exec(readStr)) {
console.log('MAAAAAAAAAAATCH', match);
var group = match[1];
ini[group] = {};
if (group == 'Profile') {
ini[group]['num'] = match[2];
}
ini[group].props = {};
for (var i = 3; i < match.length; i = i + 2) {
var prop = match[i];
if (prop === undefined) {
break;
}
var propVal = match[i + 1]
ini[group].props[prop] = propVal;
}
if (group == 'Profile') {
//Object.defineProperty(ini, ini[group].props.Name, Object.getOwnPropertyDescriptor(ini[group], group));
ini[ini[group].props.Name] = ini[group];
delete ini[group];
}
}
console.log('successfully read ini = ', ini);
updateProfToolkit();
return ini;
},
function onReject() {
console.error('Read ini failed');
}
);
return promise;
}
var tps = Cc['@mozilla.org/toolkit/profile-service;1'].createInstance(Ci.nsIToolkitProfileService); //toolkitProfileService
//XPCOMUtils.defineLazyGetter(myServices, 'tps', function(){ return Cc['@mozilla.org/toolkit/profile-service;1'].createInstance(Ci.nsIToolkitProfileService) });
function initProfToolkit() {
profToolkit = {};
profToolkit.localPathDefault = OS.Path.dirname(OS.Constants.Path.localProfileDir); //will work as long as at least one profile is in the default profile folder //i havent tested when only custom profile
profToolkit.rootPathDefault = OS.Path.dirname(OS.Constants.Path.profileDir);
profToolkit.selectedProfile = {};
profToolkit.selectedProfile.name = tps.selectedProfile.name;
}
function updateProfToolkit() {
if (!profToolkit.selectedProfile) {
initProfToolkit();
}
var profileCount = 0;
var profileNames = [];
profToolkit.profiles = {};
for (var p in ini) {
if ('num' in p) {
profileCount++;
profileNames.push(p);
}
}
profToolkit.profileCount = profileCount;
profToolkit.profileNames = profileNames;
}
function writeIni() {
var writeStr = [];
var profileI = -1;
for (var p in ini) {
if ('num' in ini[p]) {
//is profile
profileI++; //because we init profileI at -1
var group = 'Profile' + profileI;
if (ini[p].num != profileI) {
console.log('profile I of profile changed from ' + ini[p].num + ' to ' + profileI + ' the object from ini read is =', ini[p]);
}
} else {
var group = p;
}
writeStr.push('[' + group + ']');
for (var p2 in ini[p].props) {
writeStr.push(p2 + '=' + ini[p].props[p2]);
}
writeStr.push('');
}
writeStr[writeStr.length - 1] = '\n'; //we want double new line at end of file
let encoder = new TextEncoder(); // This encoder can be reused for several writes
let BufferArray = encoder.encode(writeStr.join('\n')); // Convert the text to an array
let promise = OS.File.writeAtomic(pathProfilesIni, BufferArray, // Write the array atomically to "file.txt", using as temporary
{
tmpPath: pathProfilesIni + '.profilist.tmp'
}); // buffer "file.txt.tmp".
promise.then(
function() {},
function() {
console.error('writeIni failed');
}
);
return promise;
}
/*start - salt generator from http://mxr.mozilla.org/mozilla-aurora/source/toolkit/profile/content/createProfileWizard.js?raw=1*/
var kSaltTable = [
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'
];
var kSaltString = '';
for (var i = 0; i < 8; ++i) {
kSaltString += kSaltTable[Math.floor(Math.random() * kSaltTable.length)];
}
function saltName(aName) {
return kSaltString + '.' + aName;
}
/*end - salt generator*/
function createProfile(refreshIni, profName) {
//refreshIni is 0,1 or programmatically 2
if (refreshIni == 1) {
var promise = readIni();
promise.then(
function() {
createProfile(2, profName);
},
function() {
console.error('Failed to refresh ini object from file during renameProfile');
}
);
} else {
if (profName in ini) {
Services.prompt.alert(null, self.name + ' - ' + 'EXCEPTION', 'Cannot create profile with name "' + newName + '" because this name is already taken by another profile.');
return;
}
//create folder in root dir (in it, one file "times.json" with contents:
/*
{
"created": 1395861287491
}
*/
//todo: im curious i should ask at ask.m.o how come when profile is custom driectory, a folder in local path is not created, of course the one to the custom path will be root. b ut why not make a local folder? like is done for IsRelative createds?
//create folder in local dir if root dir is different (this one is empty)
//add to profiles ini
//check if profile exists first
var numProfiles = Object.keys(ini) - 1;
var dirName = saltName(profName);
ini[profName] = {
num: numProfiles,
props: {
Name: profName,
IsRelative: 1,
Path: 'Profiles/' + dirName
}
}
var rootPathDefaultDirName = OS.File.join(profToolkit.rootPathDefault, dirName);
var localPathDefaultDirName = OS.File.join(profToolkit.localPathDefault, dirName);
var promise = OS.File.makeDir(rootPathDefaultDirName);
promise.then(
function onSuc() {
console.log('successfully created root dir for profile ' + profName + ' the path is = ', rootPathDefaultDirName);
let encoder = new TextEncoder();
let BufferArray = encoder.encode('{\n"created": ' + new Date().getTime() + '}\n');
let promise3 = OS.File.writeAtomic(OS.Path.join(rootPathDefaultDirName, 'times.json'), BufferArray,
{
tmpPath: OS.Path.join(rootPathDefaultDirName, 'times.json') + '.profilist.tmp'
}
);
promise3.then(
function() {
console.log('succesfully created times.json for profName of ' + profName + ' path is = ', OS.Path.join(rootPathDefaultDirName, 'times.json'));
},
function() {
console.error('FAILED creating times.json for profName of ' + profName + ' failed times.json path is = ', OS.Path.join(rootPathDefaultDirName, 'times.json'));
}
);
return promise3;
},
function onRej() {
console.error('FAILED to create root dir for profile ' + profName + ' the path is = ', rootPathDefaultDirName);
}
);
if (profToolkit.rootPathDefault != profToolkit.localPathDefault) {
var promise2 = OS.File.makeDir(localPathDefaultDirName);
promise2.then(
function onSuc() {
console.log('successfully created local dir for profile ' + profName + ' the path is = ', localPathDefaultDirName);
},
function onRej() {
console.error('FAILED to create local dir for profile ' + profName + ' the path is = ', localPathDefaultDirName);
}
);
}
//see here: http://mxr.mozilla.org/mozilla-aurora/source/toolkit/profile/content/createProfileWizard.js
/*
29 var dirService = C["@mozilla.org/file/directory_service;1"].getService(I.nsIProperties);
30 gDefaultProfileParent = dirService.get("DefProfRt", I.nsIFile);
73 var defaultProfileDir = gDefaultProfileParent.clone();
74 defaultProfileDir.append(saltName(document.getElementById("profileName").value));
75 gProfileRoot = defaultProfileDir;
*/
//see here for internal: http://mxr.mozilla.org/mozilla-aurora/source/toolkit/profile/content/profileSelection.js#139
//actually see here for internal: http://mxr.mozilla.org/mozilla-central/source/toolkit/profile/nsToolkitProfileService.cpp#699
}
}
function renameProfile(refreshIni, profName, newName) {
//refreshIni is 0,1 or programmatically 2
if (refreshIni == 1) {
var promise = readIni();
promise.then(
function() {
renameProfile(2, profName, newName);
},
function() {
console.error('Failed to refresh ini object from file during renameProfile');
}
);
} else {
//check if name is taken
if (profName in ini == false) {
Services.prompt.alert(null, self.name + ' - ' + 'EXCEPTION', 'Cannot find this profile name, "' + profName + '" so cannot delete it.');
return;
}
if (newName in ini) {
Services.prompt.alert(null, self.name + ' - ' + 'EXCEPTION', 'Cannot rename to "' + newName + '" because this name is already taken by another profile.');
return;
}
ini[profName].props.Name = newName;
var promise = writeIni();
promise.then(
function onSuc() {
console.log('successfully edited name of ' + profName + ' to ' + newName + ' in Profiles.ini');
},
function onRej() {
console.error('FAILED to edit name of ' + profName + ' to ' + newName + ' in Profiles.ini');
}
);
}
}
function deleteProfile(refreshIni, profName) {
//refreshIni is 0,1 or programmatically 2
if (refreshIni == 1) {
var promise = readIni();
promise.then(
function() {
deleteProfile(2, profName);
},
function() {
console.error('Failed to refresh ini object from file on deleteProfile');
}
);
} else {
//before deleting check if its default profile
if (profName in ini == false) {
Services.prompt.alert(null, self.name + ' - ' + 'EXCEPTION', 'Cannot find this profile name, "' + profName + '" so cannot delete it.');
return;
}
//if (Object.keys(ini).length == 2) {
//Services.prompt.alert(null, self.name + ' - ' + 'EXCEPTION', 'Cannot delete this profile as it is the last profile remaining.');
//return;
//}
//todo: figure out how to check if the profile is running, if it is dont delete but msg its open
if (ini[profName].props.IsRelative == '1') {
var PathRootDir = OS.Path.join(profToolkit.rootPathDefault, profToolkit.profiles[profName].rootDirName;
var PathLocalDir = OS.Path.join(profToolkit.localPathDefault, profToolkit.profiles[profName].localDirName;
var promise = OS.File.remove(PathRootDir);
promise.then(
function() {
console.log('successfully removed PathRootDir for profName of ' + profName, 'PathRootDir=', PathRootDir);
},
function() {
console.warn('FAILED to remove PathRootDir for profName of ' + profName, 'PathRootDir=', PathRootDir);
}
);
var promise2 = OS.File.remove(PathLocalDir);
promise2.then(
function() {
console.info('successfully removed PathLocalDir for profName of ' + profName, 'PathLocalDir=', PathLocalDir);
},
function() {
console.warn('FAILED to remove PathLocalDir for profName of ' + profName, 'PathLocalDir=', PathLocalDir);
}
);
} else {
var Path = ini[profName].props.Path;
var promise = OS.File.remove(Path);
promise.then(
function() {
console.log('successfully removed Path for profName of ' + profName, 'Path=', Path);
},
function() {
console.warn('FAILED to remove Path for profName of ' + profName, 'Path=', Path);
}
);
}
delete ini[profName];
var promise0 = writeIni();
promise0.then(
function() {
console.log('successfully edited out profName of ' + profName + ' from Profiles.ini');
},
function() {
console.error('FAILED to edit out profName of ' + profName + ' from Profiles.ini');
}
);
}
}
var promise = readIni();
promise.then(function onSuc() {
me.alert('read done will now write')
var promise2 = writeIni();
promise2.then(function onSuc() {
me.alert('write done')
})
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment