2 * Copyright 2003-2009, Haiku.
3 * Distributed under the terms of the MIT License.
6 * Oliver Tappe, zooey@hirschkaefer.de
7 * Adrien Destugues, pulkomandy@gmail.com
15 #include <AppFileInfo.h>
16 #include <Application.h>
18 #include <Directory.h>
20 #include <FindDirectory.h>
25 #include <Resources.h>
28 #include <DefaultCatalog.h>
29 #include <LocaleRoster.h>
34 using BPrivate::DefaultCatalog
;
38 /*! This file implements the default catalog-type for the opentracker locale
39 kit. Alternatively, this could be used as a full add-on, but currently this
40 is provided as part of liblocale.so.
47 // several attributes/resource-IDs used within the Locale Kit:
49 const char *kCatLangAttr
= "BEOS:LOCALE_LANGUAGE";
50 // name of catalog language, lives in every catalog file
51 const char *kCatSigAttr
= "BEOS:LOCALE_SIGNATURE";
52 // catalog signature, lives in every catalog file
53 const char *kCatFingerprintAttr
= "BEOS:LOCALE_FINGERPRINT";
54 // catalog fingerprint, may live in catalog file
56 const char *DefaultCatalog::kCatMimeType
57 = "locale/x-vnd.Be.locale-catalog.default";
59 static int16 kCatArchiveVersion
= 1;
60 // version of the catalog archive structure, bump this if you change it!
63 /*! Constructs a DefaultCatalog with given signature and language and reads
64 the catalog from disk.
65 InitCheck() will be B_OK if catalog could be loaded successfully, it will
66 give an appropriate error-code otherwise.
68 DefaultCatalog::DefaultCatalog(const entry_ref
&catalogOwner
,
69 const char *language
, uint32 fingerprint
)
71 HashMapCatalog("", language
, fingerprint
)
73 fInitCheck
= B_NOT_SUPPORTED
;
75 "trying to load default-catalog(lang=%s) results in %s",
76 language
, strerror(fInitCheck
));
80 /*! Constructs a DefaultCatalog and reads it from the resources of the
81 given entry-ref (which usually is an app- or add-on-file).
82 InitCheck() will be B_OK if catalog could be loaded successfully, it will
83 give an appropriate error-code otherwise.
85 DefaultCatalog::DefaultCatalog(entry_ref
*appOrAddOnRef
)
87 HashMapCatalog("", "", 0)
89 fInitCheck
= ReadFromResource(*appOrAddOnRef
);
91 // "trying to load embedded catalog from resources results in %s",
92 // strerror(fInitCheck));
96 /*! Constructs an empty DefaultCatalog with given sig and language.
97 This is used for editing/testing purposes.
98 InitCheck() will always be B_OK.
100 DefaultCatalog::DefaultCatalog(const char *path
, const char *signature
,
101 const char *language
)
103 HashMapCatalog(signature
, language
, 0),
110 DefaultCatalog::~DefaultCatalog()
116 DefaultCatalog::SetSignature(const entry_ref
&catalogOwner
)
118 // Not allowed for the build-tool version.
124 DefaultCatalog::SetRawString(const CatKey
& key
, const char *translated
)
126 return fCatMap
.Put(key
, translated
);
131 DefaultCatalog::ReadFromFile(const char *path
)
134 path
= fPath
.String();
137 status_t res
= catalogFile
.SetTo(path
, B_READ_ONLY
);
139 fprintf(stderr
, "no catalog at %s\n", path
);
140 return B_ENTRY_NOT_FOUND
;
144 fprintf(stderr
, "found catalog at %s\n", path
);
147 res
= catalogFile
.GetSize(&sz
);
149 fprintf(stderr
, "couldn't get size for catalog-file %s\n", path
);
153 auto_ptr
<char> buf(new(std::nothrow
) char [sz
]);
154 if (buf
.get() == NULL
) {
155 fprintf(stderr
, "couldn't allocate array of %Ld chars\n", sz
);
158 res
= catalogFile
.Read(buf
.get(), sz
);
160 fprintf(stderr
, "couldn't read from catalog-file %s\n", path
);
165 "only got %u instead of %Lu bytes from catalog-file %s\n", res
, sz
,
169 BMemoryIO
memIO(buf
.get(), sz
);
170 res
= Unflatten(&memIO
);
173 // some information living in member variables needs to be copied
174 // to attributes. Although these attributes should have been written
175 // when creating the catalog, we make sure that they exist there:
176 UpdateAttributes(catalogFile
);
183 /*! This method is not currently being used, but it may be useful in the
187 DefaultCatalog::ReadFromAttribute(const entry_ref
&appOrAddOnRef
)
189 return B_NOT_SUPPORTED
;
194 DefaultCatalog::ReadFromResource(const entry_ref
&appOrAddOnRef
)
196 return B_NOT_SUPPORTED
;
201 DefaultCatalog::WriteToFile(const char *path
)
206 status_t status
= catalogFile
.SetTo(fPath
.String(),
207 B_WRITE_ONLY
| B_CREATE_FILE
| B_ERASE_FILE
);
212 mallocIO
.SetBlockSize(max_c(fCatMap
.Size() * 20, 256));
213 // set a largish block-size in order to avoid reallocs
214 status
= Flatten(&mallocIO
);
219 = catalogFile
.Write(mallocIO
.Buffer(), mallocIO
.BufferLength());
220 if (bytesWritten
< 0)
222 if (bytesWritten
!= (ssize_t
)mallocIO
.BufferLength())
225 // set mimetype-, language- and signature-attributes:
226 UpdateAttributes(catalogFile
);
232 /*! This method is not currently being used, but it may be useful in the
236 DefaultCatalog::WriteToAttribute(const entry_ref
&appOrAddOnRef
)
238 return B_NOT_SUPPORTED
;
243 DefaultCatalog::WriteToResource(const entry_ref
&appOrAddOnRef
)
245 return B_NOT_SUPPORTED
;
249 /*! Writes mimetype, language-name and signature of catalog into the
253 DefaultCatalog::UpdateAttributes(BFile
& catalogFile
)
255 static const int bufSize
= 256;
258 if (catalogFile
.ReadAttr("BEOS:TYPE", B_MIME_STRING_TYPE
, 0, &buf
,
260 || strcmp(kCatMimeType
, buf
) != 0) {
261 catalogFile
.WriteAttr("BEOS:TYPE", B_MIME_STRING_TYPE
, 0,
262 kCatMimeType
, strlen(kCatMimeType
)+1);
264 if (catalogFile
.ReadAttr(kCatLangAttr
, B_STRING_TYPE
, 0,
266 || fLanguageName
!= buf
) {
267 catalogFile
.WriteAttr(kCatLangAttr
, B_STRING_TYPE
, 0,
268 fLanguageName
.String(), fLanguageName
.Length()+1);
270 if (catalogFile
.ReadAttr(kCatSigAttr
, B_STRING_TYPE
, 0,
272 || fSignature
!= buf
) {
273 catalogFile
.WriteAttr(kCatSigAttr
, B_STRING_TYPE
, 0,
274 fSignature
.String(), fSignature
.Length()+1);
276 if (catalogFile
.ReadAttr(kCatFingerprintAttr
, B_UINT32_TYPE
,
277 0, &temp
, sizeof(uint32
)) <= 0) {
278 catalogFile
.WriteAttr(kCatFingerprintAttr
, B_UINT32_TYPE
,
279 0, &fFingerprint
, sizeof(uint32
));
285 DefaultCatalog::Flatten(BDataIO
*dataIO
)
288 // make sure we have the correct fingerprint before we flatten it
292 uint32 count
= fCatMap
.Size();
293 res
= archive
.AddString("class", "DefaultCatalog");
295 res
= archive
.AddInt32("c:sz", count
);
297 res
= archive
.AddInt16("c:ver", kCatArchiveVersion
);
299 res
= archive
.AddString("c:lang", fLanguageName
.String());
301 res
= archive
.AddString("c:sig", fSignature
.String());
303 res
= archive
.AddInt32("c:fpr", fFingerprint
);
305 res
= archive
.Flatten(dataIO
);
307 CatMap::Iterator iter
= fCatMap
.GetIterator();
309 while (res
== B_OK
&& iter
.HasNext()) {
312 res
= archive
.AddString("c:ostr", entry
.key
.fString
.String());
314 res
= archive
.AddString("c:ctxt", entry
.key
.fContext
.String());
316 res
= archive
.AddString("c:comt", entry
.key
.fComment
.String());
318 res
= archive
.AddInt32("c:hash", entry
.key
.fHashVal
);
320 res
= archive
.AddString("c:tstr", entry
.value
.String());
322 res
= archive
.Flatten(dataIO
);
329 DefaultCatalog::Unflatten(BDataIO
*dataIO
)
335 status_t res
= archiveMsg
.Unflatten(dataIO
);
338 res
= archiveMsg
.FindInt16("c:ver", &version
)
339 || archiveMsg
.FindInt32("c:sz", &count
);
342 fLanguageName
= archiveMsg
.FindString("c:lang");
343 fSignature
= archiveMsg
.FindString("c:sig");
344 uint32 foundFingerprint
= archiveMsg
.FindInt32("c:fpr");
346 // if a specific fingerprint has been requested and the catalog does in
347 // fact have a fingerprint, both are compared. If they mismatch, we do
348 // not accept this catalog:
349 if (foundFingerprint
!= 0 && fFingerprint
!= 0
350 && foundFingerprint
!= fFingerprint
) {
351 fprintf(stderr
, "default-catalog(sig=%s, lang=%s) "
352 "has mismatching fingerprint (%d instead of the requested %d)"
353 ", so this catalog is skipped.\n",
354 fSignature
.String(), fLanguageName
.String(), foundFingerprint
,
356 res
= B_MISMATCHED_VALUES
;
358 fFingerprint
= foundFingerprint
;
361 if (res
== B_OK
&& count
> 0) {
366 const char *translated
;
368 // fCatMap.resize(count);
369 // There is no resize method in Haiku Hash Map to prealloc space
370 for (int i
=0; res
== B_OK
&& i
< count
; ++i
) {
371 res
= archiveMsg
.Unflatten(dataIO
);
373 res
= archiveMsg
.FindString("c:ostr", &keyStr
);
375 res
= archiveMsg
.FindString("c:ctxt", &keyCtx
);
377 res
= archiveMsg
.FindString("c:comt", &keyCmt
);
379 res
= archiveMsg
.FindInt32("c:hash", (int32
*)&key
.fHashVal
);
381 res
= archiveMsg
.FindString("c:tstr", &translated
);
383 key
.fString
= keyStr
;
384 key
.fContext
= keyCtx
;
385 key
.fComment
= keyCmt
;
386 fCatMap
.Put(key
, translated
);
389 uint32 checkFP
= ComputeFingerprint();
390 if (fFingerprint
!= checkFP
) {
391 fprintf(stderr
, "default-catalog(sig=%s, lang=%s) "
392 "has wrong fingerprint after load (%d instead of %d). "
393 "The catalog data may be corrupted, so this catalog is "
395 fSignature
.String(), fLanguageName
.String(), checkFP
,
405 DefaultCatalog::Instantiate(const entry_ref
&catalogOwner
, const char *language
,
408 DefaultCatalog
*catalog
409 = new(std::nothrow
) DefaultCatalog(catalogOwner
, language
, fingerprint
);
410 if (catalog
&& catalog
->InitCheck() != B_OK
) {
419 DefaultCatalog::Create(const char *signature
, const char *language
)
421 DefaultCatalog
*catalog
422 = new(std::nothrow
) DefaultCatalog("", signature
, language
);
423 if (catalog
&& catalog
->InitCheck() != B_OK
) {
431 const uint8
DefaultCatalog::kDefaultCatalogAddOnPriority
= 1;
432 // give highest priority to our embedded catalog-add-on
435 } // namespace BPrivate