/**
* MailArchiver is an application that provides services for storing and managing e-mail messages through a Web Services SOAP interface.
* Copyright (C) 2012 Marcio Andre Scholl Levien and Fernando Alberto Reuter Wendt and Jose Ronaldo Nogueira Fonseca Junior
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
/******************************************************************************\
*
* This product was developed by
*
* SERVIÇO FEDERAL DE PROCESSAMENTO DE DADOS (SERPRO),
*
* a government company established under Brazilian law (5.615/70),
* at Department of Development of Porto Alegre.
*
\******************************************************************************/
package serpro.mailarchiver.util;
import java.io.FileReader;
import java.io.FilterReader;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import com.sun.jna.Native;
import com.sun.jna.platform.win32.Advapi32Util;
import com.sun.jna.platform.win32.Advapi32Util.Account;
import com.sun.jna.platform.win32.Shell32;
import com.sun.jna.platform.win32.ShlObj;
import com.sun.jna.platform.win32.W32Errors;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.platform.win32.WinNT.HRESULT;
import org.jvnet.libpam.UnixUser;
@Configurable
public class SystemAccount {
private static final Logger log = Logger.getLocalLogger();
@Autowired
private Environment env;
private String username;
private Path homePath;
//-- Windows --
private String sid;
private String domain;
private Path appDataPath;
private Path localAppDataPath;
//-------------
//--- Unix ----
private int uid;
private int gid;
//-------------
public SystemAccount(HANDLE token) {
Account account = Advapi32Util.getTokenAccount(token);
username = account.name;
sid = account.sidString;
domain = account.domain;
homePath = getKnownFolderPath(token, ShlObj.CSIDL_PROFILE);
appDataPath = getKnownFolderPath(token, ShlObj.CSIDL_APPDATA);
localAppDataPath = getKnownFolderPath(token, ShlObj.CSIDL_LOCAL_APPDATA);
System.out.printf(
"Windows account\n"
+ "\tsid: %s\n"
+ "\tusername: %s\n"
+ "\tdomain: %s\n"
+ "\thome path: %s\n"
+ "\tappData path: %s\n"
+ "\tlocalAppData path: %s\n",
sid, username, domain, homePath, appDataPath, localAppDataPath);
}
public SystemAccount(UnixUser unixUser) {
username = unixUser.getUserName();
uid = unixUser.getUID();
gid = unixUser.getGID();
homePath = FileSystems.getDefault().getPath("/home").resolve(username);
System.out.printf(
"Unix account\n"
+ "\tuid: %d\n"
+ "\tgid: %d\n"
+ "\tusername: %s\n"
+ "\thome path: %s\n",
uid, gid, username, homePath);
}
private Path getKnownFolderPath(HANDLE token, int folder) {
char[] path = new char[WinDef.MAX_PATH];
HRESULT hr = Shell32.INSTANCE.SHGetFolderPath(null, folder, token, ShlObj.SHGFP_TYPE_CURRENT, path);
if(hr.equals(W32Errors.S_OK)) {
return Paths.get(Native.toString(path));
}
else {
log.error("getKnownFolderPath {username=%s, csidl=%s} error: %d", username, folder, hr.intValue());
}
return null;
}
public Path getFirefoxProfilesIniPath() {
switch(env.getOperatingSystem()) {
case WindowsXP:
case WindowsVista:
case Windows7:
return appDataPath
.resolve("Mozilla")
.resolve("Firefox")
.resolve("profiles.ini");
case MacOSX:
Path path = homePath
.resolve("Library")
.resolve("Application Support")
.resolve("Firefox")
.resolve("profiles.ini");
if(Files.exists(path)) {
return path;
}
return homePath
.resolve("Library")
.resolve("Mozilla")
.resolve("Firefox")
.resolve("profiles.ini");
case Linux:
return homePath
.resolve(".mozilla")
.resolve("firefox")
.resolve("profiles.ini");
default:
return null;
}
}
public Path getThunderbirdProfilesIniPath() {
Path path;
switch(env.getOperatingSystem()) {
case WindowsXP:
case WindowsVista:
case Windows7:
return appDataPath
.resolve("Thunderbird")
.resolve("profiles.ini");
case MacOSX:
path = homePath
.resolve("Library")
.resolve("Application Support")
.resolve("Thunderbird")
.resolve("profiles.ini");
if(Files.exists(path)) {
return path;
}
return homePath
.resolve("Library")
.resolve("Thunderbird")
.resolve("profiles.ini");
case Linux:
path = homePath
.resolve(".thunderbird")
.resolve("profiles.ini");
if(Files.exists(path)) {
return path;
}
return homePath
.resolve(".mozilla-thunderbird")
.resolve("profiles.ini");
default:
return null;
}
}
public Path getThunderbirdLocalFoldersPath() {
MozillaProfile profile = getDefaultThunderbirdProfile();
Path path;
switch(env.getOperatingSystem()) {
case WindowsXP:
case WindowsVista:
case Windows7:
if(profile.isRelative()) {
return localAppDataPath
.resolve("Thunderbird")
.resolve(profile.getPathStr())
.resolve("Mail")
.resolve("Local Folders");
}
else {
return Paths.get(profile.getPathStr(), "Mail", "Local Folders");
}
case MacOSX:
if(profile.isRelative()) {
path = homePath
.resolve("Library")
.resolve("Application Support")
.resolve("Thunderbird")
.resolve(profile.getPathStr())
.resolve("Mail")
.resolve("Local Folders");
if(Files.exists(path)) {
return path;
}
return homePath
.resolve("Library")
.resolve("Thunderbird")
.resolve(profile.getPathStr())
.resolve("Mail")
.resolve("Local Folders");
}
else {
return Paths.get(profile.getPathStr(), "Mail", "Local Folders");
}
case Linux:
if(profile.isRelative()) {
path = homePath
.resolve(".thunderbird")
.resolve(profile.getPathStr())
.resolve("Mail")
.resolve("Local Folders");
if(Files.exists(path)) {
return path;
}
return homePath
.resolve(".mozilla-thunderbird")
.resolve(profile.getPathStr())
.resolve("Mail")
.resolve("Local Folders");
}
else {
return Paths.get(profile.getPathStr(), "Mail", "Local Folders");
}
default:
return null;
}
}
public MozillaProfile getDefaultFirefoxProfile() {
Path iniPath = getFirefoxProfilesIniPath();
return ((iniPath != null) && Files.isReadable(iniPath))
? getDefaultMozillaProfile(iniPath)
: null;
}
public List getFirefoxProfiles() {
Path iniPath = getFirefoxProfilesIniPath();
return (List) (((iniPath != null) && Files.isReadable(iniPath))
? getMozillaProfiles(iniPath)
: Collections.emptyList());
}
public MozillaProfile getDefaultThunderbirdProfile() {
Path iniPath = getThunderbirdProfilesIniPath();
return ((iniPath != null) && Files.isReadable(iniPath))
? getDefaultMozillaProfile(iniPath)
: null;
}
public List getThunderbirdProfiles() {
Path iniPath = getThunderbirdProfilesIniPath();
return (List) (((iniPath != null) && Files.isReadable(iniPath))
? getMozillaProfiles(iniPath)
: Collections.emptyList());
}
private MozillaProfile getDefaultMozillaProfile(Path iniPath) {
Ini ini = null;
try {
ini = new Ini(iniPath);
}
catch (IOException ex) {
log.error(ex);
return null;
}
Ini.Section section = null;
for(Map.Entry entry : ini.entrySet()) {
if( ! entry.getKey().startsWith("Profile")) {
continue;
}
section = entry.getValue();
String def = section.get("Default");
if((def != null) && def.equals("1")) {
break;
}
}
//se nenhuma seção marcada como default, usa a última,
//provavelmente a única
if(section != null) {
return new MozillaProfile(
section.get("Name"),
section.get("Path"),
section.get("IsRelative").equals("1"));
}
return null;
}
private List getMozillaProfiles(Path iniPath) {
Ini ini = null;
try {
ini = new Ini(iniPath);
}
catch(IOException ex) {
log.error(ex);
return null;
}
List profiles = new ArrayList();
for(Map.Entry entry : ini.entrySet()) {
if( ! entry.getKey().startsWith("Profile")) {
continue;
}
Ini.Section section = entry.getValue();
profiles.add(new MozillaProfile(
section.get("Name"),
section.get("Path"),
section.get("IsRelative").equals("1")));
}
return profiles;
}
private class Ini extends org.ini4j.Ini {
public Ini(Path iniPath) throws IOException {
super(new FilterReader(new FileReader(iniPath.toFile())) {
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
// escape '\'
// necessario quando o perfil usa um caminho absoluto no Windows
// ex: Path=C:\perfis_firefox\perfil_X ==> Path=C:\\perfis_firefox\\perfil_X
int c = in.read();
if(c == -1) {
return -1;
}
if(c == '\\') {
cbuf[off] = '\\';
cbuf[off + 1] = '\\';
return 2;
}
else {
cbuf[off] = (char) c;
return 1;
}
}
});
}
}
public Path getGearsPath(Browser browser) {
OperatingSystem os = env.getOperatingSystem();
MozillaProfile profile;
switch(os.id|browser.id) {
case 0x501: // Windows7 + InternetExplorer
case 0x401: // WindowsVista + InternetExplorer
return homePath
.resolve("AppData")
.resolve("LocalLow")
.resolve("Google")
.resolve("Google Gears for Internet Explorer");
case 0x301: // WindowsXP + InternetExplorer
return localAppDataPath
.resolve("Google")
.resolve("Google Gears for Internet Explorer");
case 0x502: // Windows7 + Firefox
case 0x402: // WindowsVista + Firefox
case 0x302: // WindowsXP + Firefox
profile = getDefaultFirefoxProfile();
if(profile == null) {
return localAppDataPath
.resolve("Mozilla")
.resolve("Firefox")
.resolve("null")
.resolve("Google Gears for Firefox");
}
if(profile.isRelative()) {
return localAppDataPath
.resolve("Mozilla")
.resolve("Firefox")
.resolve(profile.getPathStr())
.resolve("Google Gears for Firefox");
}
else {
return Paths.get(profile.getPathStr(), "Google Gears for Firefox");
}
case 0x503: // Windows7 + Chrome
case 0x403: // WindowsVista + Chrome
case 0x303: // WindowsXP + Chrome
return localAppDataPath
.resolve("Google")
.resolve("Chrome")
.resolve("User Data")
.resolve("Default")
.resolve("Plugin Data")
.resolve("Google Gears");
case 0x202: // MacOSX + Firefox
profile = getDefaultFirefoxProfile();
if(profile == null) {
return homePath
.resolve("Library")
.resolve("Caches")
.resolve("Firefox")
.resolve("null")
.resolve("Google Gears for Firefox");
}
if(profile.isRelative()) {
return homePath
.resolve("Library")
.resolve("Caches")
.resolve("Firefox")
.resolve(profile.getPathStr())
.resolve("Google Gears for Firefox");
}
else {
return Paths.get(profile.getPathStr(), "Google Gears for Firefox");
}
case 0x204: // MacOSX + Safari
return homePath
.resolve("Library")
.resolve("Application Support")
.resolve("Google")
.resolve("Google Gears for Safari");
case 0x102: // Linux + Firefox
profile = getDefaultFirefoxProfile();
if(profile == null) {
return homePath
.resolve(".mozilla")
.resolve("firefox")
.resolve("null")
.resolve("Google Gears for Firefox");
}
if(profile.isRelative()) {
return homePath
.resolve(".mozilla")
.resolve("firefox")
.resolve(profile.getPathStr())
.resolve("Google Gears for Firefox");
}
else {
return Paths.get(profile.getPathStr(), "Google Gears for Firefox");
}
default:
return null;
}
}
public List getFirefoxGearsPaths() {
List paths = new ArrayList();
switch(env.getOperatingSystem()) {
case Windows7:
case WindowsVista:
case WindowsXP:
for(MozillaProfile profile : getFirefoxProfiles()) {
if(profile.isRelative()) {
paths.add(localAppDataPath
.resolve("Mozilla")
.resolve("Firefox")
.resolve(profile.getPathStr())
.resolve("Google Gears for Firefox"));
}
else {
paths.add(Paths.get(profile.getPathStr(), "Google Gears for Firefox"));
}
}
return paths;
case MacOSX:
for(MozillaProfile profile : getFirefoxProfiles()) {
if(profile.isRelative()) {
paths.add(homePath
.resolve("Library")
.resolve("Caches")
.resolve("Firefox")
.resolve(profile.getPathStr())
.resolve("Google Gears for Firefox"));
}
else {
paths.add(Paths.get(profile.getPathStr(), "Google Gears for Firefox"));
}
}
return paths;
case Linux:
for(MozillaProfile profile : getFirefoxProfiles()) {
if(profile.isRelative()) {
paths.add(homePath
.resolve(".mozilla")
.resolve("firefox")
.resolve(profile.getPathStr())
.resolve("Google Gears for Firefox"));
}
else {
paths.add(Paths.get(profile.getPathStr(), "Google Gears for Firefox"));
}
}
return paths;
default:
return null;
}
}
}