Odpowiedź
Enigmail Service Not Available (brak libenigmime.so)
Korzystam z przeglądarki Seamonkey, używam FreeBSD na platformie amd64. Miałem ciekawe problemy z instalacją rozszerzenia Enigmail z użyciem systemu portów FreeBSD (mail/enigmail-seamonkey).
Port FreeBSD tworzy plik rozszerzenia Mozilli z rozszerzeniem xpi. Gdy uruchomi się przeglądarkę z uprawnieniami administratora, można zainstalować to rozszerzenie w katalogu systemowym przeglądarki (a nie w profilu użytkownika). Po instalacji mam dostępne menu OpenPGP menus i ustawień. Niestety, przy próbie wykonania jakiejś operacji, dostaję komunikat wyświetalny na terminalu, z którego uruchomiłem przeglądarkę:
Enigmail Service Not Available
Zajrzałem do katalogu /usr/local/lib/seamonkey, i zauważyłem, że brakuje tam zawierającego ważne funkcje rozszerzenia pliku libenigmine.so. Co więc poszło nie tak?
Najpierw rozpakowałem plik XPI utworzony przez port (enigmail-0.95.6-freebsd-amd64.xpi) i przyjrzałem się jego zawartości:
chrome/enigmail-skin-tbird.jar
chrome/enigmail-locale.jar
chrome/enigmail-skin.jar
chrome.manifest
components/ipc.xpt
components/enigmail.xpt
components/enigmail.js
components/enigprefs-service.js
components/enigmime.xpt
defaults/pref/enigmail.js
defaults/preferences/enigmail.js
install.js
install.rdf
platform/FreeBSD/components/libenigmime.so
Jak widać, brakujący plik jest w archiwum. Po przekopiowaniu go do katalogu /usr/local/lib/seamonkey/components rozszerzenie zaczyna działać poprawnie. Przejrzałem kilka artykułów o tworzeniu plików XPI, dostępnych na
stronie Mozilla Developer Connection i przyjrzałem się bliżej plikowi install.js.
Ten fragment pliku decyduje o wyborze katalogu zawierającego bibliotekę z kodem binarnym zależnym od systemu, na którym rozszerzenie ma działać:
// which platform?
function getPlatform() {
var platformStr;
var platformNode = "";
if('platform' in Install) {
platformStr = new String(Install.platform);
if (!platformStr.search(/^Macintosh/))
platformNode = APP_PLATFORM_MAC;
else if (!platformStr.search(/^Win/))
platformNode = APP_PLATFORM_WIN;
else if (!platformStr.search(/Linux/))
platformNode = APP_PLATFORM_LINUX;
else if (!platformStr.search(/^OS\/2/))
platformNode = APP_PLATFORM_OS2;
else
platformNode = APP_PLATFORM_OTHER;
}
return platformNode;
}
Dokumentacja metody "search" podaje, że metoda zwraca pozycję, na której został o odnalezione poszukiwane wyrażenie. Jeżeli nic nie zostanie znalezione, to metoda zwraca -1. To wyrażenie if (!platformStr.search(/Linux/) będzie więc prawdziwe wtedy i tylko wtedy, gdy słowo "Linux" będzie znajdowało się na samym początku napisu przechowywanego w zmiennej platformStr. W moim przypadku, a jak sądzę również w przypadku Linuksa, nazwa platformy zaczyna się od X11; FreeBSD 7.... Z tego właśnie powodu mój system zostanie zakwalifikowany jako "inny" (APP_PLATFORM_OTHER).
Wygląda na to, że ten kawałek kodu pochodzi z przykładowego pliku na stronie mozilla.org, ale proszę zauważyć, że nie ma tam błędu - wszystkie wyrażenie regularne zaczynają się od "^" (początek wiersza) i dlatego ten przykładowy kod działa.
Co dzieje się dalej?
case APP_PLATFORM_LINUX:
addDirectory("", "platform/"+ABI_PLATFORM_LINUX+"/components", fComponents, "");
break;
case APP_PLATFORM_WIN:
addDirectory("", "platform/"+ABI_PLATFORM_WIN+"/components", fComponents, "");
break;
case APP_PLATFORM_MAC:
addDirectory("", "platform/"+ABI_PLATFORM_DARWIN_PPC+"/components", fComponents, "");
addDirectory("", "platform/"+ABI_PLATFORM_DARWIN_X86+"/components", fComponents, "");
break;
case APP_PLATFORM_OS2:
addDirectory("", "platform/"+ABI_PLATFORM_OS2+"/components", fComponents, "");
break;
}
err = getLastError();
if (err == DOES_NOT_EXIST) {
// error code: file does not exist
logComment("platform dependent directory does not exist: " + err);
resetError();
}
W wyniku wykonania powyższego kodu nie zostanie dodany żaden katalog ani też nie zostanie zgłoszony błąd - getLastError() nie zgłasza błędu, gdyż nie zostało wywołane addDirectory().
Następnie spojrzałem na skrypt <a href="http://www.mozdev.org/source/browse/enigmail/src/genxpi?annotate=1.9.2.2">genxpi</a>, który tworzy archiwum XPI po zakończeniu kompilacji rozszerzenia. Ten skrypt tworzy plik install.js odpowiedzialny za przeprowadzenie instalacji rozszerzenia.
Jednym ze sposobów naprawienia błędu jest usunięcie sprawdzania plaformy podczas instalacji rozszerzenia i zainstalowanie biblioteki z katalogu wybranego podczas kompilacji rozszerzenia:
+++ mailnews/extensions/enigmail/genxpi.new 2008-07-20 22:28:22.610449405 +0200
@@ -68,20 +68,6 @@
var err;
const APP_VERSION="${xpiVersion}.0";
-
-const ABI_PLATFORM_LINUX="Linux_x86-gcc3";
-const ABI_PLATFORM_WIN="WINNT_x86-msvc";
-const ABI_PLATFORM_DARWIN_PPC="Darwin_ppc-gcc3";
-const ABI_PLATFORM_DARWIN_X86="Darwin_x86-gcc3";
-const ABI_PLATFORM_OS2="OS2_x86-gcc3";
-
-const APP_PLATFORM_LINUX="linux";
-const APP_PLATFORM_WIN="win";
-const APP_PLATFORM_MAC="mac";
-const APP_PLATFORM_OS2="os2";
-const APP_PLATFORM_OTHER="other";
-
-
// this function verifies disk space in kilobytes
function verifyDiskSpace(dirPath, spaceRequired) {
var spaceAvailable;
@@ -103,30 +89,6 @@
return true;
}
-// OS type detection
-// which platform?
-function getPlatform() {
- var platformStr;
- var platformNode = "";
-
- if('platform' in Install) {
- platformStr = new String(Install.platform);
-
- if (!platformStr.search(/^Macintosh/))
- platformNode = APP_PLATFORM_MAC;
- else if (!platformStr.search(/^Win/))
- platformNode = APP_PLATFORM_WIN;
- else if (!platformStr.search(/Linux/))
- platformNode = APP_PLATFORM_LINUX;
- else if (!platformStr.search(/^OS\/2/))
- platformNode = APP_PLATFORM_OS2;
- else
- platformNode = APP_PLATFORM_OTHER;
- }
-
- return platformNode;
-}
-
err = initInstall("Enigmail v"+APP_VERSION, // name for install UI
"/enigmail", // registered name
APP_VERSION); // package version
@@ -157,22 +119,7 @@
File.remove(delFile);
}
- switch (getPlatform()) {
- case APP_PLATFORM_LINUX:
- addDirectory("", "platform/"+ABI_PLATFORM_LINUX+"/components", fComponents, "");
- break;
- case APP_PLATFORM_WIN:
- addDirectory("", "platform/"+ABI_PLATFORM_WIN+"/components", fComponents, "");
- break;
- case APP_PLATFORM_MAC:
- addDirectory("", "platform/"+ABI_PLATFORM_DARWIN_PPC+"/components", fComponents, "");
- addDirectory("", "platform/"+ABI_PLATFORM_DARWIN_X86+"/components", fComponents, "");
- break;
- case APP_PLATFORM_OS2:
- addDirectory("", "platform/"+ABI_PLATFORM_OS2+"/components", fComponents, "");
- break;
- }
-
+ addDirectory("", "platform/${platform}/components", fComponents, "");
err = getLastError();
if (err == DOES_NOT_EXIST) {
// error code: file does not exist
Ale to rozwiązanie ma tą wadę, że jeżeli Twój plik XPI zostanie zainstalowany na złej platformie (np. będziesz instalować plik XPI z Linuksa na Macu) - instalacja może się udać, ale przeglądarka odmówi posłuszeństwa.
Inny wariant:
+++ mailnews/extensions/enigmail/genxpi 2008-07-21 03:15:51.970437845 +0200
@@ -70,12 +70,14 @@
const ABI_PLATFORM_LINUX="Linux_x86-gcc3";
+const ABI_PLATFORM_FREEBSD="FreeBSD";
const ABI_PLATFORM_WIN="WINNT_x86-msvc";
const ABI_PLATFORM_DARWIN_PPC="Darwin_ppc-gcc3";
const ABI_PLATFORM_DARWIN_X86="Darwin_x86-gcc3";
const ABI_PLATFORM_OS2="OS2_x86-gcc3";
const APP_PLATFORM_LINUX="linux";
+const APP_PLATFORM_FREEBSD="FreeBSD";
const APP_PLATFORM_WIN="win";
const APP_PLATFORM_MAC="mac";
const APP_PLATFORM_OS2="os2";
@@ -107,21 +109,21 @@
// which platform?
function getPlatform() {
var platformStr;
- var platformNode = "";
+ var platformNode = APP_PLATFORM_OTHER;
if('platform' in Install) {
platformStr = new String(Install.platform);
- if (!platformStr.search(/^Macintosh/))
+ if (platformStr.search(/^Macintosh/) >= 0)
platformNode = APP_PLATFORM_MAC;
- else if (!platformStr.search(/^Win/))
+ else if (platformStr.search(/^Win/) >= 0)
platformNode = APP_PLATFORM_WIN;
- else if (!platformStr.search(/Linux/))
+ else if (platformStr.search(/Linux/) >= 0)
platformNode = APP_PLATFORM_LINUX;
- else if (!platformStr.search(/^OS\/2/))
+ else if (platformStr.search(/FreeBSD/) >= 0)
+ platformNode = APP_PLATFORM_FREEBSD;
+ else if (platformStr.search(/^OS\/2/) >= 0)
platformNode = APP_PLATFORM_OS2;
- else
- platformNode = APP_PLATFORM_OTHER;
}
return platformNode;
@@ -161,6 +163,9 @@
case APP_PLATFORM_LINUX:
addDirectory("", "platform/"+ABI_PLATFORM_LINUX+"/components", fComponents, "");
break;
+ case APP_PLATFORM_FREEBSD:
+ addDirectory("", "platform/"+ABI_PLATFORM_FREEBSD+"/components", fComponents, "");
+ break;
case APP_PLATFORM_WIN:
addDirectory("", "platform/"+ABI_PLATFORM_WIN+"/components", fComponents, "");
break;
@@ -171,6 +176,9 @@
case APP_PLATFORM_OS2:
addDirectory("", "platform/"+ABI_PLATFORM_OS2+"/components", fComponents, "");
break;
+ case APP_PLATFORM_OTHER:
+ alert("Unsupported platform, no Enigmail support currently available.");
+ cancelInstall(ACCESS_DENIED);
}
err = getLastError();
Ta poprawka dodaje wprost wsparcie dla FreeBSD i dodatkowo zgłasza błąd dla nieznanych systemów. Tak naprawdę skrypt powinien rozpoznawać różne platformy i ich wariant (np. Linuks trzydziestodwu- i sześćdzisięcioczterobitowy).
To zagadnienie wykracza jednak poza ramy tej notki.
Jeśli masz problem taki jak opisany tutaj i masz pod ręką archiwum XPI pasujące do Twojego systemu, możesz spróbować zastąpić plik install.js plikiem załączonym poniżej. Archiwa XPI są zwykłymi zipami, więc każde narzędzie do formatu ZIP pomoże Ci podmienić plik. Alternatywnie można wyciągnąć z archiwum bibliotekę enigmime (z rozszerzeniem .dll dla Windows, .so dla systemów uniksowych) i umieścić ją w katalogu components przeglądarki.
| Załącznik | Wielkość |
|---|---|
| install.js.txt | 7.7 KB |