1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: MNSProfileDiscover.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_connectivity.hxx"
34 #include "MNSProfileDiscover.hxx"
35 #ifndef MINIMAL_PROFILEDISCOVER
36 #include "MNSProfile.hxx"
43 #include "nsIEnumerator.h"
46 #include "nsIComponentManager.h"
48 #include "nsDirectoryServiceDefs.h"
49 #include "nsAppDirectoryServiceDefs.h"
50 #include "nsILocalFile.h"
51 #include "nsReadableUtils.h"
54 #if defined(XP_MAC) || defined(XP_MACOSX)
55 #include <Processes.h>
57 #include "nsILocalFileMac.h"
73 #include "nsICharsetConverterManager.h"
74 #include "nsIPlatformCharset.h"
78 #define USER_ENVIRONMENT_VARIABLE "USER"
79 #define LOGNAME_ENVIRONMENT_VARIABLE "LOGNAME"
80 #define HOME_ENVIRONMENT_VARIABLE "HOME"
81 #define PROFILE_NAME_ENVIRONMENT_VARIABLE "PROFILE_NAME"
82 #define PROFILE_HOME_ENVIRONMENT_VARIABLE "PROFILE_HOME"
83 #define DEFAULT_UNIX_PROFILE_NAME "default"
84 #ifndef XP_MACOSX /* Don't use symlink-based locking on OS X */
85 #define USE_SYMLINK_LOCKING
87 #elif defined (XP_BEOS)
90 // IID and CIDs of all the services needed
91 static NS_DEFINE_CID(kCharsetConverterManagerCID
, NS_ICHARSETCONVERTERMANAGER_CID
);
96 static ::rtl::OUString szProfileSubtreeString
=::rtl::OUString::createFromAscii("Profiles");
97 static ::rtl::OUString szCurrentProfileString
= ::rtl::OUString::createFromAscii("CurrentProfile");
98 static ::rtl::OUString szDirectoryString
=::rtl::OUString::createFromAscii("directory");
101 #define MAXPATHLEN 1024
103 #include <MNSFolders.hxx>
104 #include <MNSINIParser.hxx>
106 namespace connectivity
110 ProfileStruct::ProfileStruct(MozillaProductType aProduct
,::rtl::OUString aProfileName
,
111 #ifdef MINIMAL_PROFILEDISCOVER
112 const ::rtl::OUString
& aProfilePath
114 nsILocalFile
* aProfilePath
119 profileName
= aProfileName
;
120 profilePath
= aProfilePath
;
122 ::rtl::OUString
ProfileStruct::getProfilePath()
124 #ifdef MINIMAL_PROFILEDISCOVER
130 nsresult rv
= profilePath
->GetPath(path
);
131 NS_ENSURE_SUCCESS(rv
, ::rtl::OUString());
132 // PRUnichar != sal_Unicode in mingw
133 return ::rtl::OUString(reinterpret_cast_mingw_only
<const sal_Unicode
*>(path
.get()));
136 return ::rtl::OUString();
140 ProfileAccess::~ProfileAccess()
143 ProfileAccess::ProfileAccess()
148 sal_Int32
ProfileAccess::LoadProductsInfo()
150 #ifndef MINIMAL_PROFILEDISCOVER
151 //load mozilla profiles to m_ProductProfileList
152 LoadMozillaProfiles();
154 sal_Int32 count
=static_cast<sal_Int32
>(m_ProductProfileList
[MozillaProductType_Mozilla
].mProfileList
.size());
156 //load thunderbird profiles to m_ProductProfileList
157 count
+= LoadXPToolkitProfiles(MozillaProductType_Thunderbird
);
159 //load firefox profiles to m_ProductProfileList
160 //firefox profile does not containt address book, but maybe others need them
161 count
+= LoadXPToolkitProfiles(MozillaProductType_Firefox
);
164 #ifndef MINIMAL_PROFILEDISCOVER
165 nsresult
ProfileAccess::LoadMozillaProfiles()
167 sal_Int32 index
=MozillaProductType_Mozilla
;
168 ProductStruct
&m_Product
= m_ProductProfileList
[index
];
171 //step 1 : get mozilla registry file
172 nsCOMPtr
<nsILocalFile
> localFile
;
173 ::rtl::OUString
regDir( getRegistryFileName( MozillaProductType_Mozilla
) );
174 // PRUnichar != sal_Unicode in mingw
175 nsAutoString
registryDir(reinterpret_cast_mingw_only
<const PRUnichar
*>(regDir
.getStr()));
176 rv
= NS_NewLocalFile(registryDir
, PR_TRUE
,
177 getter_AddRefs(localFile
));
178 NS_ENSURE_SUCCESS(rv
,rv
);
180 rv
= localFile
->Exists(&bExist
);
181 NS_ENSURE_SUCCESS(rv
,rv
);
184 nsCOMPtr
<nsIRegistry
> registry(do_CreateInstance(NS_REGISTRY_CONTRACTID
, &rv
));
185 NS_ENSURE_SUCCESS(rv
,rv
);
186 //step 2: open mozilla registry file
187 rv
= registry
->Open(localFile
);
188 NS_ENSURE_SUCCESS(rv
,rv
);
190 nsCOMPtr
<nsIEnumerator
> enumKeys
;
191 nsRegistryKey profilesTreeKey
;
193 //step 3:Enumerator it
194 rv
= registry
->GetKey(nsIRegistry::Common
,
195 // PRUnichar != sal_Unicode in mingw
196 reinterpret_cast_mingw_only
<const PRUnichar
*>(szProfileSubtreeString
.getStr()),
198 if (NS_FAILED(rv
)) return rv
;
200 nsXPIDLString tmpCurrentProfile
;
202 // Get the current profile
203 rv
= registry
->GetString(profilesTreeKey
,
204 // PRUnichar != sal_Unicode in mingw
205 reinterpret_cast_mingw_only
<const PRUnichar
*>(szCurrentProfileString
.getStr()),
206 getter_Copies(tmpCurrentProfile
));
208 if (tmpCurrentProfile
)
210 // PRUnichar != sal_Unicode in mingw
211 m_Product
.setCurrentProfile ( reinterpret_cast_mingw_only
<const sal_Unicode
*>(NS_STATIC_CAST(const PRUnichar
*, tmpCurrentProfile
)));
215 rv
= registry
->EnumerateSubtrees( profilesTreeKey
, getter_AddRefs(enumKeys
));
216 NS_ENSURE_SUCCESS(rv
,rv
);
218 rv
= enumKeys
->First();
219 NS_ENSURE_SUCCESS(rv
,rv
);
221 while (NS_OK
!= enumKeys
->IsDone())
223 nsCOMPtr
<nsISupports
> base
;
225 rv
= enumKeys
->CurrentItem( getter_AddRefs(base
) );
226 NS_ENSURE_SUCCESS(rv
,rv
);
227 rv
= enumKeys
->Next();
228 NS_ENSURE_SUCCESS(rv
,rv
);
230 // Get specific interface.
231 nsCOMPtr
<nsIRegistryNode
> node
;
232 nsIID nodeIID
= NS_IREGISTRYNODE_IID
;
234 rv
= base
->QueryInterface( nodeIID
, getter_AddRefs(node
));
235 if (NS_FAILED(rv
)) continue;
238 nsXPIDLString profile
;
239 rv
= node
->GetName(getter_Copies(profile
));
240 if (NS_FAILED(rv
)) continue;
242 nsRegistryKey profKey
;
243 rv
= node
->GetKey(&profKey
);
244 if (NS_FAILED(rv
)) continue;
247 nsCOMPtr
<nsILocalFile
> tempLocal
;
249 nsXPIDLString regData
;
250 rv
= registry
->GetString(profKey
,
251 // PRUnichar != sal_Unicode in mingw
252 reinterpret_cast_mingw_only
<const PRUnichar
*>(szDirectoryString
.getStr()),
253 getter_Copies(regData
));
254 if (NS_FAILED(rv
)) continue;
256 #if defined(XP_MAC) || defined(XP_MACOSX) || defined(MACOSX)
257 rv
= NS_NewNativeLocalFile(nsCString(), PR_TRUE
, getter_AddRefs(tempLocal
));
258 if (NS_SUCCEEDED(rv
))
259 rv
= tempLocal
->SetPersistentDescriptor(NS_LossyConvertUCS2toASCII(regData
));
261 rv
= NS_NewLocalFile(regData
, PR_TRUE
, getter_AddRefs(tempLocal
));
263 //Add found profile to profile lists
264 if (NS_SUCCEEDED(rv
) && tempLocal
)
266 // PRUnichar != sal_Unicode in mingw
267 ProfileStruct
* profileItem
= new ProfileStruct(MozillaProductType_Mozilla
,reinterpret_cast_mingw_only
<const sal_Unicode
*>(NS_STATIC_CAST(const PRUnichar
*, profile
)),tempLocal
);
268 m_Product
.mProfileList
[profileItem
->getProfileName()] = profileItem
;
275 //Thunderbird and firefox profiles are saved in profiles.ini
276 sal_Int32
ProfileAccess::LoadXPToolkitProfiles(MozillaProductType product
)
278 sal_Int32 index
=product
;
279 ProductStruct
&m_Product
= m_ProductProfileList
[index
];
281 #ifndef MINIMAL_PROFILEDISCOVER
284 ::rtl::OUString regDir
= getRegistryDir(product
);
285 ::rtl::OUString
profilesIni( regDir
);
286 profilesIni
+= ::rtl::OUString::createFromAscii( "profiles.ini" );
287 IniParser
parser( profilesIni
);
288 IniSectionMap
&mAllSection
= *(parser
.getAllSection());
290 IniSectionMap::iterator iBegin
= mAllSection
.begin();
291 IniSectionMap::iterator iEnd
= mAllSection
.end();
292 for(;iBegin
!= iEnd
;iBegin
++)
294 ini_Section
*aSection
= &(*iBegin
).second
;
295 ::rtl::OUString profileName
;
296 ::rtl::OUString profilePath
;
297 ::rtl::OUString sIsRelative
;
298 ::rtl::OUString sIsDefault
;
300 for(NameValueList::iterator itor
=aSection
->lList
.begin();
301 itor
!= aSection
->lList
.end();
304 struct ini_NameValue
* aValue
= &(*itor
);
305 if (aValue
->sName
.equals(::rtl::OUString::createFromAscii("Name")))
307 profileName
= aValue
->sValue
;
309 else if (aValue
->sName
.equals(::rtl::OUString::createFromAscii("IsRelative")))
311 sIsRelative
= aValue
->sValue
;
313 else if (aValue
->sName
.equals(::rtl::OUString::createFromAscii("Path")))
315 profilePath
= aValue
->sValue
;
317 else if (aValue
->sName
.equals(::rtl::OUString::createFromAscii("Default")))
319 sIsDefault
= aValue
->sValue
;
322 if (profileName
.getLength() != 0 || profilePath
.getLength() != 0)
324 sal_Int32 isRelative
= 0;
325 if (sIsRelative
.getLength() != 0)
327 isRelative
= sIsRelative
.toInt32();
330 #ifndef MINIMAL_PROFILEDISCOVER
331 nsCOMPtr
<nsILocalFile
> rootDir
;
332 rv
= NS_NewLocalFile(EmptyString(), PR_TRUE
,
333 getter_AddRefs(rootDir
));
334 if (NS_FAILED(rv
)) continue;
336 OString sPath
= OUStringToOString(profilePath
, RTL_TEXTENCODING_UTF8
);
337 nsCAutoString
filePath(sPath
.getStr());
340 // PRUnichar != sal_Unicode in mingw
341 nsAutoString
registryDir( reinterpret_cast_mingw_only
<const PRUnichar
*>(regDir
.getStr()) );
342 nsCOMPtr
<nsILocalFile
> mAppData
;
343 rv
= NS_NewLocalFile(registryDir
, PR_TRUE
,
344 getter_AddRefs(mAppData
));
345 if (NS_FAILED(rv
)) continue;
346 rv
= rootDir
->SetRelativeDescriptor(mAppData
, filePath
);
348 rv
= rootDir
->SetPersistentDescriptor(filePath
);
350 if (NS_FAILED(rv
)) continue;
353 ProfileStruct
* profileItem
= new ProfileStruct(product
,profileName
,
354 #ifdef MINIMAL_PROFILEDISCOVER
360 m_Product
.mProfileList
[profileName
] = profileItem
;
362 sal_Int32 isDefault
= 0;
363 if (sIsDefault
.getLength() != 0)
365 isDefault
= sIsDefault
.toInt32();
368 m_Product
.mCurrentProfileName
= profileName
;
373 return static_cast< ::sal_Int32
>(m_Product
.mProfileList
.size());
376 ::rtl::OUString
ProfileAccess::getProfilePath( ::com::sun::star::mozilla::MozillaProductType product
, const ::rtl::OUString
& profileName
) throw (::com::sun::star::uno::RuntimeException
)
378 sal_Int32 index
=product
;
379 ProductStruct
&m_Product
= m_ProductProfileList
[index
];
380 if (!m_Product
.mProfileList
.size() || m_Product
.mProfileList
.find(profileName
) == m_Product
.mProfileList
.end())
383 return ::rtl::OUString();
386 return m_Product
.mProfileList
[profileName
]->getProfilePath();
389 ::sal_Int32
ProfileAccess::getProfileCount( ::com::sun::star::mozilla::MozillaProductType product
) throw (::com::sun::star::uno::RuntimeException
)
391 sal_Int32 index
=product
;
392 ProductStruct
&m_Product
= m_ProductProfileList
[index
];
393 return static_cast< ::sal_Int32
>(m_Product
.mProfileList
.size());
395 ::sal_Int32
ProfileAccess::getProfileList( ::com::sun::star::mozilla::MozillaProductType product
, ::com::sun::star::uno::Sequence
< ::rtl::OUString
>& list
) throw (::com::sun::star::uno::RuntimeException
)
397 sal_Int32 index
=product
;
398 ProductStruct
&m_Product
= m_ProductProfileList
[index
];
399 list
.realloc(static_cast<sal_Int32
>(m_Product
.mProfileList
.size()));
401 for(ProfileList::iterator itor
=m_Product
.mProfileList
.begin();
402 itor
!= m_Product
.mProfileList
.end();
405 ProfileStruct
* aProfile
= (*itor
).second
;
406 list
[i
] = aProfile
->getProfileName();
410 return static_cast< ::sal_Int32
>(m_Product
.mProfileList
.size());
413 ::rtl::OUString
ProfileAccess::getDefaultProfile( ::com::sun::star::mozilla::MozillaProductType product
) throw (::com::sun::star::uno::RuntimeException
)
415 sal_Int32 index
=product
;
416 ProductStruct
&m_Product
= m_ProductProfileList
[index
];
417 if (m_Product
.mCurrentProfileName
.getLength() != 0)
419 //default profile setted in mozilla registry
420 return m_Product
.mCurrentProfileName
;
422 if (m_Product
.mProfileList
.size() == 0)
424 //there are not any profiles
425 return ::rtl::OUString();
427 ProfileStruct
* aProfile
= (*m_Product
.mProfileList
.begin()).second
;
428 return aProfile
->getProfileName();
430 #ifndef MINIMAL_PROFILEDISCOVER
431 nsresult
ProfileAccess::isExistFileOrSymlink(nsILocalFile
* aFile
,PRBool
*bExist
)
435 aFile
->GetPath(path
);
436 rv
= aFile
->Exists(bExist
);
437 NS_ENSURE_SUCCESS(rv
, rv
);
440 rv
= aFile
->IsSymlink(bExist
);
441 NS_ENSURE_SUCCESS(rv
, rv
);
445 nsresult
ProfileAccess::isLockExist(nsILocalFile
* aFile
)
447 #if defined (XP_MACOSX)
448 NS_NAMED_LITERAL_STRING(LOCKFILE_NAME
, ".parentlock");
449 NS_NAMED_LITERAL_STRING(OLD_LOCKFILE_NAME
, "parent.lock");
450 #elif defined (XP_UNIX)
451 NS_ConvertASCIItoUTF16
OLD_LOCKFILE_NAME("lock");
452 NS_ConvertASCIItoUTF16
LOCKFILE_NAME(".parentlock");
454 NS_NAMED_LITERAL_STRING(OLD_LOCKFILE_NAME
, "parent.lock");
455 NS_NAMED_LITERAL_STRING(LOCKFILE_NAME
, "parent.lock");
461 rv
= aFile
->IsDirectory(&isDir
);
462 NS_ENSURE_SUCCESS(rv
, rv
);
464 return NS_ERROR_FILE_NOT_DIRECTORY
;
466 nsCOMPtr
<nsILocalFile
> lockFile
;
467 rv
= aFile
->Clone((nsIFile
**)((void **)getter_AddRefs(lockFile
)));
468 NS_ENSURE_SUCCESS(rv
, rv
);
470 rv
= lockFile
->Append(LOCKFILE_NAME
);
471 NS_ENSURE_SUCCESS(rv
, rv
);
472 PRBool nExist
=PR_FALSE
;
473 rv
= isExistFileOrSymlink(lockFile
,&nExist
);
474 NS_ENSURE_SUCCESS(rv
, rv
);
475 if (!nExist
) // Check OLD_LOCKFILE_NAME
477 nsCOMPtr
<nsILocalFile
> oldlockFile
;
478 rv
= aFile
->Clone((nsIFile
**)((void **)getter_AddRefs(oldlockFile
)));
479 NS_ENSURE_SUCCESS(rv
, rv
);
481 rv
= oldlockFile
->Append(OLD_LOCKFILE_NAME
);
482 NS_ENSURE_SUCCESS(rv
, rv
);
483 rv
= isExistFileOrSymlink(oldlockFile
,&nExist
);
484 NS_ENSURE_SUCCESS(rv
, rv
);
490 ::sal_Bool
ProfileAccess::isProfileLocked( ::com::sun::star::mozilla::MozillaProductType product
, const ::rtl::OUString
& profileName
) throw (::com::sun::star::uno::RuntimeException
)
492 #ifdef MINIMAL_PROFILEDISCOVER
493 (void)product
; /* avoid warning about unused parameter */
494 (void)profileName
; /* avoid warning about unused parameter */
497 ::rtl::OUString path
= getProfilePath(product
,profileName
);
498 if (!path
.getLength())
501 // PRUnichar != sal_Unicode in mingw
502 nsAutoString
filePath(reinterpret_cast_mingw_only
<const PRUnichar
*>(path
.getStr()));
505 nsCOMPtr
<nsILocalFile
> localFile
;
506 rv
= NS_NewLocalFile(filePath
, PR_TRUE
,
507 getter_AddRefs(localFile
));
508 NS_ENSURE_SUCCESS(rv
,sal_True
);
510 PRBool exists
= PR_FALSE
;
511 rv
= localFile
->Exists(&exists
);
512 NS_ENSURE_SUCCESS(rv
, sal_True
);
516 // If the profile is locked, we return true
517 rv
= isLockExist(localFile
);
524 ::sal_Bool
ProfileAccess::getProfileExists( ::com::sun::star::mozilla::MozillaProductType product
, const ::rtl::OUString
& profileName
) throw (::com::sun::star::uno::RuntimeException
)
526 sal_Int32 index
=product
;
527 ProductStruct
&m_Product
= m_ProductProfileList
[index
];
528 if (!m_Product
.mProfileList
.size() || m_Product
.mProfileList
.find(profileName
) == m_Product
.mProfileList
.end())