void app_sig_for_pathname(const char * path, BString * signature) { *signature = ZK_APP_SIG; BNode node (path); attr_info info; char buffer [B_MIME_TYPE_LENGTH]; if (node.GetAttrInfo("BEOS:APP_SIG", & info) == B_OK) { PRINT(("node.GetAttrInfo(BEOS:APP_SIG, & info) == B_OK\n")); if (node.ReadAttr("BEOS:APP_SIG", info.type, 0, & buffer, info.size) == info.size) { PRINT(("node.ReadAttr(BEOS:APP_SIG, info.type, 0, & buffer, info.size) == B_OK\n")); PRINT(("attribute: %s \n", buffer)); *signature = buffer; } else PRINT(("No BEOS:APP_SIG attribute. Fallback to default.\n")); } else PRINT(("No BEOS:APP_SIG attribute. Fallback to default.\n")); }
bool ResourceData::SetFromAttribute(const char *name, BNode &node) { attr_info info; if (node.GetAttrInfo(name, &info) != B_OK) { *this = ResourceData(); return false; } fType = info.type; fID = -1; fIDString = "(attr)"; fName = name; fLength = info.size; fAttr = true; fTypeString = MakeTypeString(fType); fData = (char *)malloc(fLength); if (fData) { ssize_t size = node.ReadAttr(name, info.type, 0, (void*)fData, fLength); if (size >= 0) { fLength = (size_t) size; return true; } } *this = ResourceData(); return false; }
/* copy atribytes */ bool BF_GUI_FilesPanel_CopyTask::Copy_Atributes(BNode & o_NodeSrc,BNode & o_NodeDest) { char pcName[B_ATTR_NAME_LENGTH]; attr_info uAttrInfo; uint32 iBufMaxSize=255; char *pcBuf = (char*)malloc(iBufMaxSize); o_NodeSrc.RewindAttrs(); // while(B_OK==o_NodeSrc.GetNextAttrName(pcName)) { if(B_OK==o_NodeSrc.GetAttrInfo(pcName,&uAttrInfo)) { /* check buffer size */ if(uAttrInfo.size>iBufMaxSize) { DELETE(pcBuf); iBufMaxSize = uAttrInfo.size; pcBuf = (char*)malloc(iBufMaxSize); } /* read attr */ o_NodeSrc.ReadAttr(pcName,uAttrInfo.type,0, (void*)pcBuf,uAttrInfo.size); /* write attr */ o_NodeDest.WriteAttr(pcName,uAttrInfo.type, 0,(void*)pcBuf,uAttrInfo.size); /* check for cancel_process */ if(Canceled()) return false; } } DELETE(pcBuf); return true; }/* end of atributes */
/* * this method is not currently being used, but it may be useful in the future... */ status_t DefaultCatalog::ReadFromAttribute(const entry_ref &appOrAddOnRef) { BNode node; status_t res = node.SetTo(&appOrAddOnRef); if (res != B_OK) return B_ENTRY_NOT_FOUND; attr_info attrInfo; res = node.GetAttrInfo(BLocaleRoster::kEmbeddedCatAttr, &attrInfo); if (res != B_OK) return B_NAME_NOT_FOUND; if (attrInfo.type != B_MESSAGE_TYPE) return B_BAD_TYPE; size_t size = attrInfo.size; auto_ptr<char> buf(new(std::nothrow) char [size]); if (buf.get() == NULL) return B_NO_MEMORY; res = node.ReadAttr(BLocaleRoster::kEmbeddedCatAttr, B_MESSAGE_TYPE, 0, buf.get(), size); if (res < (ssize_t)size) return res < B_OK ? res : B_BAD_DATA; BMemoryIO memIO(buf.get(), size); res = Unflatten(&memIO); return res; }
void ActivityView::_LoadBackgroundInfo(bool watch) { fCachedOutline = false; fCachedWorkspace = -1; BPath path; if (find_directory(B_DESKTOP_DIRECTORY, &path) == B_OK) { BNode desktopNode = BNode(path.Path()); attr_info info; if (desktopNode.GetAttrInfo(kDesktopAttrName, &info) != B_OK) return; char* buffer = new char[info.size]; if (desktopNode.ReadAttr(kDesktopAttrName, B_MESSAGE_TYPE, 0, buffer, (size_t)info.size) == info.size) { BMessage message; if (message.Unflatten(buffer) == B_OK) fBackgroundInfo = message; } delete[] buffer; if (watch) { node_ref nref; desktopNode.GetNodeRef(&nref); watch_node(&nref, B_WATCH_ATTR, this); } } }
/*! \brief Fetches the vector icon used by an application of this type for files of the given type. The type of the \c BMimeType object is not required to actually be a subtype of \c "application/"; that is the intended use however, and calling \c get_icon_for_type() on a non-application type will likely return \c B_ENTRY_NOT_FOUND. The icon data is allocated and returned in \a data. \param type The MIME type \param fileType Pointer to a pre-allocated string containing the MIME type whose custom icon you wish to fetch. If NULL, works just like get_icon(). \param data Pointer in which the icon data is returned on success. \param size Pointer in which the size of the icon data is returned. \return - \c B_OK: Success - \c B_ENTRY_NOT_FOUND: No vector icon exists for the given type - "error code": Failure */ status_t get_icon_for_type(const char* type, const char* fileType, uint8** data, size_t* size) { if (!type || !data || !size) return B_BAD_VALUE; // open the node for the given type BNode node; ssize_t err = open_type(type, &node); if (err < B_OK) return (status_t)err; // construct our attribute name std::string iconAttrName; if (fileType) iconAttrName = kIconAttrPrefix + BPrivate::Storage::to_lower(fileType); else iconAttrName = kIconAttr; // get info about attribute for that name attr_info info; if (!err) err = node.GetAttrInfo(iconAttrName.c_str(), &info); // validate attribute type if (!err) err = (info.type == B_VECTOR_ICON_TYPE) ? B_OK : B_BAD_VALUE; // allocate a buffer and read the attribute data into it if (!err) { uint8* buffer = new(std::nothrow) uint8[info.size]; if (!buffer) err = B_NO_MEMORY; if (!err) { err = node.ReadAttr(iconAttrName.c_str(), B_VECTOR_ICON_TYPE, 0, buffer, info.size); } if (err >= 0) err = (err == info.size) ? (ssize_t)B_OK : (ssize_t)B_FILE_ERROR; if (!err) { // success, set data pointer and size *data = buffer; *size = info.size; } else { delete[] buffer; } } return err; }
/* * this method is not currently being used, but it may be useful in the future... */ status_t DefaultCatalog::ReadFromAttribute(entry_ref *appOrAddOnRef) { BNode node; status_t res = node.SetTo(appOrAddOnRef); if (res != B_OK) { log_team(LOG_ERR, "couldn't find app or add-on (dev=%lu, dir=%Lu, name=%s)", appOrAddOnRef->device, appOrAddOnRef->directory, appOrAddOnRef->name); return B_ENTRY_NOT_FOUND; } log_team(LOG_DEBUG, "looking for embedded catalog-attribute in app/add-on" "(dev=%lu, dir=%Lu, name=%s)", appOrAddOnRef->device, appOrAddOnRef->directory, appOrAddOnRef->name); attr_info attrInfo; res = node.GetAttrInfo(BLocaleRoster::kEmbeddedCatAttr, &attrInfo); if (res != B_OK) { log_team(LOG_DEBUG, "no embedded catalog found"); return B_NAME_NOT_FOUND; } if (attrInfo.type != B_MESSAGE_TYPE) { log_team(LOG_ERR, "attribute %s has incorrect type and is ignored!", BLocaleRoster::kEmbeddedCatAttr); return B_BAD_TYPE; } size_t size = attrInfo.size; auto_ptr<char> buf(new(std::nothrow) char [size]); if (buf.get() == NULL) { log_team(LOG_ERR, "couldn't allocate array of %d chars", size); return B_NO_MEMORY; } res = node.ReadAttr(BLocaleRoster::kEmbeddedCatAttr, B_MESSAGE_TYPE, 0, buf.get(), size); if (res < (ssize_t)size) { log_team(LOG_ERR, "unable to read embedded catalog from attribute"); return res < B_OK ? res : B_BAD_DATA; } BMemoryIO memIO(buf.get(), size); res = Unflatten(&memIO); return res; }
/* ReadSetting * this method can read attributes from a File, just give the name of the * attribute to the method (const char) and it returns a pointer to the content of the attribute. * It's importent that you know the type of the content because the method returns * a void pointer and you have to make a typ caste to the return value to the expected * type of the attribute. * If there are errors the method throws exceptions */ void *IOSettings::ReadSetting(const char* Setting) { if(!SettingsFileExists()) CreateSettingsFile(); BNode objNode; char buffer[500]; attr_info info; memset(buffer, 0, sizeof(buffer)); //content pointer BString *strCont; int32 *int32Cont; int64 *int64Cont; double *dbCont; bool *blCont; objNode.SetTo(fSettingsFile.String()); objNode.GetAttrInfo(Setting, &info); switch(info.type) { case B_STRING_TYPE: { if(objNode.ReadAttr(Setting, info.type, 0, buffer, sizeof(buffer)) == B_ENTRY_NOT_FOUND) throw new IOSettingsException(new BString("an Attr. doesn't exsist by some folder (LavaProjectManager::_readPorject)")); strCont = new BString(buffer); return strCont; } break; case B_INT32_TYPE: { int32Cont = new int32(); if(objNode.ReadAttr(Setting, info.type, 0, int32Cont, sizeof(int32Cont)) == B_ENTRY_NOT_FOUND) throw new IOSettingsException(new BString("an Attr. doesn't exsist by some folder (LavaProjectManager::_readPorject)")); return int32Cont; } break; case B_INT64_TYPE: { int64Cont = new int64(); if(objNode.ReadAttr(Setting, info.type, 0, int64Cont, sizeof(int64Cont)) == B_ENTRY_NOT_FOUND) throw new IOSettingsException(new BString("an Attr. doesn't exsist by some folder (LavaProjectManager::_readPorject)")); return int64Cont; } break; case B_DOUBLE_TYPE: { dbCont = new double(); if(objNode.ReadAttr(Setting, info.type, 0, dbCont, sizeof(dbCont)) == B_ENTRY_NOT_FOUND) throw new IOSettingsException(new BString("an Attr. doesn't exsist by some folder (LavaProjectManager::_readPorject)")); return dbCont; } break; case B_BOOL_TYPE: { blCont = new bool(); if(objNode.ReadAttr(Setting, info.type, 0, blCont, sizeof(blCont)) == B_ENTRY_NOT_FOUND) throw new IOSettingsException(new BString("an Attr. doesn't exsist by some folder (LavaProjectManager::_readPorject)")); return blCont; } break; default: throw new IOSettingsException(new BString("not supported attribute type was read")); break; } }
QueryEntryListCollection::QueryEntryListCollection(Model* model, BHandler* target, PoseList* oldPoseList) : fQueryListRep(new QueryListRep(new BObjectList<BQuery>(5, true))) { Rewind(); attr_info info; BQuery query; BNode* modelNode = model->Node(); if (modelNode == NULL) { fStatus = B_ERROR; return; } // read the actual query string fStatus = modelNode->GetAttrInfo(kAttrQueryString, &info); if (fStatus != B_OK) return; BString buffer; if (modelNode->ReadAttr(kAttrQueryString, B_STRING_TYPE, 0, buffer.LockBuffer((int32)info.size), (size_t)info.size) != info.size) { fStatus = B_ERROR; return; } buffer.UnlockBuffer(); // read the extra options MoreOptionsStruct saveMoreOptions; if (ReadAttr(modelNode, kAttrQueryMoreOptions, kAttrQueryMoreOptionsForeign, B_RAW_TYPE, 0, &saveMoreOptions, sizeof(MoreOptionsStruct), &MoreOptionsStruct::EndianSwap) != kReadAttrFailed) { fQueryListRep->fShowResultsFromTrash = saveMoreOptions.searchTrash; } fStatus = query.SetPredicate(buffer.String()); fQueryListRep->fOldPoseList = oldPoseList; fQueryListRep->fDynamicDateQuery = false; fQueryListRep->fRefreshEveryHour = false; fQueryListRep->fRefreshEveryMinute = false; if (modelNode->ReadAttr(kAttrDynamicDateQuery, B_BOOL_TYPE, 0, &fQueryListRep->fDynamicDateQuery, sizeof(bool)) != sizeof(bool)) { fQueryListRep->fDynamicDateQuery = false; } if (fQueryListRep->fDynamicDateQuery) { // only refresh every minute on debug builds fQueryListRep->fRefreshEveryMinute = buffer.IFindFirst("second") != -1 || buffer.IFindFirst("minute") != -1; fQueryListRep->fRefreshEveryHour = fQueryListRep->fRefreshEveryMinute || buffer.IFindFirst("hour") != -1; #if !DEBUG // don't refresh every minute unless we are running debug build fQueryListRep->fRefreshEveryMinute = false; #endif } if (fStatus != B_OK) return; bool searchAllVolumes = true; status_t result = B_OK; // get volumes to perform query on if (modelNode->GetAttrInfo(kAttrQueryVolume, &info) == B_OK) { char* buffer = NULL; if ((buffer = (char*)malloc((size_t)info.size)) != NULL && modelNode->ReadAttr(kAttrQueryVolume, B_MESSAGE_TYPE, 0, buffer, (size_t)info.size) == info.size) { BMessage message; if (message.Unflatten(buffer) == B_OK) { for (int32 index = 0; ;index++) { ASSERT(index < 100); BVolume volume; // match a volume with the info embedded in // the message result = MatchArchivedVolume(&volume, &message, index); if (result == B_OK) { // start the query on this volume result = FetchOneQuery(&query, target, fQueryListRep->fQueryList, &volume); if (result != B_OK) continue; searchAllVolumes = false; } else if (result != B_DEV_BAD_DRIVE_NUM) { // if B_DEV_BAD_DRIVE_NUM, the volume just isn't // mounted this time around, keep looking for more // if other error, bail break; } } } } free(buffer); } if (searchAllVolumes) { // no specific volumes embedded in query, search everything BVolumeRoster roster; BVolume volume; roster.Rewind(); while (roster.GetNextVolume(&volume) == B_OK) if (volume.IsPersistent() && volume.KnowsQuery()) { result = FetchOneQuery(&query, target, fQueryListRep->fQueryList, &volume); if (result != B_OK) continue; } } fStatus = B_OK; return; }
status_t AGMSBayesianSpamFilter::ProcessMailMessage ( BPositionIO** io_message, BEntry* io_entry, BMessage* io_headers, BPath* io_folder, const char* io_uid) { ssize_t amountRead; attr_info attributeInfo; const char *classificationString; off_t dataSize; BPositionIO *dataStreamPntr = *io_message; status_t errorCode = B_OK; int32 headerLength; BString headerString; BString newSubjectString; BNode nodeForOutputFile; bool nodeForOutputFileInitialised = false; const char *oldSubjectStringPntr; char percentageString [30]; BMessage replyMessage; BMessage scriptingMessage; team_id serverTeam; float spamRatio; char *stringBuffer = NULL; char tempChar; status_t tempErrorCode; const char *tokenizeModeStringPntr; // Set up a BNode to the final output file so that we can write custom // attributes to it. Non-custom attributes are stored separately in // io_headers. if (io_entry != NULL && B_OK == nodeForOutputFile.SetTo (io_entry)) nodeForOutputFileInitialised = true; // Get a connection to the spam database server. Launch if needed, should // only need it once, unless another e-mail thread shuts down the server // inbetween messages. This code used to be in InitCheck, but apparently // that isn't called. printf("Checking for Spam Server.\n"); if (fLaunchAttemptCount == 0 || !fMessengerToServer.IsValid ()) { if (fLaunchAttemptCount > 3) goto ErrorExit; // Don't try to start the server too many times. fLaunchAttemptCount++; // Make sure the server is running. if (!be_roster->IsRunning (kServerSignature)) { errorCode = be_roster->Launch (kServerSignature); if (errorCode != B_OK) { BPath path; entry_ref ref; directory_which places[] = {B_COMMON_BIN_DIRECTORY,B_BEOS_BIN_DIRECTORY}; for (int32 i = 0; i < 2; i++) { find_directory(places[i],&path); path.Append("spamdbm"); if (!BEntry(path.Path()).Exists()) continue; get_ref_for_path(path.Path(),&ref); if ((errorCode = be_roster->Launch (&ref)) == B_OK) break; } if (errorCode != B_OK) goto ErrorExit; } } // Set up the messenger to the database server. serverTeam = be_roster->TeamFor (kServerSignature); if (serverTeam < 0) goto ErrorExit; fMessengerToServer = BMessenger (kServerSignature, serverTeam, &errorCode); if (!fMessengerToServer.IsValid ()) goto ErrorExit; // Check if the server is running in headers only mode. If so, we only // need to download the header rather than the entire message. scriptingMessage.MakeEmpty (); scriptingMessage.what = B_GET_PROPERTY; scriptingMessage.AddSpecifier ("TokenizeMode"); replyMessage.MakeEmpty (); if ((errorCode = fMessengerToServer.SendMessage (&scriptingMessage, &replyMessage)) != B_OK) goto ErrorExit; if ((errorCode = replyMessage.FindInt32 ("error", &tempErrorCode)) != B_OK) goto ErrorExit; if ((errorCode = tempErrorCode) != B_OK) goto ErrorExit; if ((errorCode = replyMessage.FindString ("result", &tokenizeModeStringPntr)) != B_OK) goto ErrorExit; fHeaderOnly = (tokenizeModeStringPntr != NULL && strcmp (tokenizeModeStringPntr, "JustHeader") == 0); } // See if the message has already been classified. Happens for messages // which are partially downloaded when you have auto-training on. Could // untrain the partial part before training on the complete message, but we // don't know how big it was, so instead just ignore the message. if (nodeForOutputFileInitialised) { if (nodeForOutputFile.GetAttrInfo ("MAIL:classification", &attributeInfo) == B_OK) return B_OK; } // Copy the message to a string so that we can pass it to the spam database // (the even messier alternative is a temporary file). Do it in a fashion // which allows NUL bytes in the string. This method of course limits the // message size to a few hundred megabytes. If we're using header mode, // only read the header rather than the full message. if (fHeaderOnly) { // Read just the header, it ends with an empty CRLF line. dataStreamPntr->Seek (0, SEEK_SET); while ((errorCode = dataStreamPntr->Read (&tempChar, 1)) == 1) { headerString.Append (tempChar, 1); headerLength = headerString.Length(); if (headerLength >= 4 && strcmp (headerString.String() + headerLength - 4, "\r\n\r\n") == 0) break; } if (errorCode < 0) goto ErrorExit; dataSize = headerString.Length(); stringBuffer = new char [dataSize + 1]; memcpy (stringBuffer, headerString.String(), dataSize); stringBuffer[dataSize] = 0; } else { // Read the whole file. The seek to the end may take a while since // that triggers downloading of the entire message (and caching in a // slave file - see the MessageIO class). dataSize = dataStreamPntr->Seek (0, SEEK_END); if (dataSize <= 0) goto ErrorExit; try { stringBuffer = new char [dataSize + 1]; } catch (...) { errorCode = ENOMEM; goto ErrorExit; } dataStreamPntr->Seek (0, SEEK_SET); amountRead = dataStreamPntr->Read (stringBuffer, dataSize); if (amountRead != dataSize) goto ErrorExit; stringBuffer[dataSize] = 0; // Add an end of string NUL, just in case. } // Send off a scripting command to the database server, asking it to // evaluate the string for spaminess. Note that it can return ENOMSG // when there are no words (a good indicator of spam which is pure HTML // if you are using plain text only tokenization), so we could use that // as a spam marker too. Code copied for the reevaluate stuff below. scriptingMessage.MakeEmpty (); scriptingMessage.what = B_SET_PROPERTY; scriptingMessage.AddSpecifier ("EvaluateString"); errorCode = scriptingMessage.AddData ("data", B_STRING_TYPE, stringBuffer, dataSize + 1, false /* fixed size */); if (errorCode != B_OK) goto ErrorExit; replyMessage.MakeEmpty (); errorCode = fMessengerToServer.SendMessage (&scriptingMessage, &replyMessage); if (errorCode != B_OK || replyMessage.FindInt32 ("error", &errorCode) != B_OK) goto ErrorExit; // Unable to read the return code. if (errorCode == ENOMSG && fNoWordsMeansSpam) spamRatio = fSpamCutoffRatio; // Yes, no words and that means spam. else if (errorCode != B_OK || replyMessage.FindFloat ("result", &spamRatio) != B_OK) goto ErrorExit; // Classification failed in one of many ways. // If we are auto-training, feed back the message to the server as a // training example (don't train if it is uncertain). Also redo the // evaluation after training. if (fAutoTraining) { if (spamRatio >= fSpamCutoffRatio || spamRatio < fGenuineCutoffRatio) { scriptingMessage.MakeEmpty (); scriptingMessage.what = B_SET_PROPERTY; scriptingMessage.AddSpecifier ((spamRatio >= fSpamCutoffRatio) ? "SpamString" : "GenuineString"); errorCode = scriptingMessage.AddData ("data", B_STRING_TYPE, stringBuffer, dataSize + 1, false /* fixed size */); if (errorCode != B_OK) goto ErrorExit; replyMessage.MakeEmpty (); errorCode = fMessengerToServer.SendMessage (&scriptingMessage, &replyMessage); if (errorCode != B_OK || replyMessage.FindInt32 ("error", &errorCode) != B_OK) goto ErrorExit; // Unable to read the return code. if (errorCode != B_OK) goto ErrorExit; // Failed to set a good example. } // Note the kind of example made so that the user doesn't reclassify // the message twice (the spam server looks for this attribute). classificationString = (spamRatio >= fSpamCutoffRatio) ? "Spam" : ((spamRatio < fGenuineCutoffRatio) ? "Genuine" : "Uncertain"); if (nodeForOutputFileInitialised) nodeForOutputFile.WriteAttr ("MAIL:classification", B_STRING_TYPE, 0 /* offset */, classificationString, strlen (classificationString) + 1); // Now that the database has changed due to training, recompute the // spam ratio. Hopefully it will have become more extreme in the // correct direction (not switched from being spam to being genuine). // Code copied from above. scriptingMessage.MakeEmpty (); scriptingMessage.what = B_SET_PROPERTY; scriptingMessage.AddSpecifier ("EvaluateString"); errorCode = scriptingMessage.AddData ("data", B_STRING_TYPE, stringBuffer, dataSize + 1, false /* fixed size */); if (errorCode != B_OK) goto ErrorExit; replyMessage.MakeEmpty (); errorCode = fMessengerToServer.SendMessage (&scriptingMessage, &replyMessage); if (errorCode != B_OK || replyMessage.FindInt32 ("error", &errorCode) != B_OK) goto ErrorExit; // Unable to read the return code. if (errorCode == ENOMSG && fNoWordsMeansSpam) spamRatio = fSpamCutoffRatio; // Yes, no words and that means spam. else if (errorCode != B_OK || replyMessage.FindFloat ("result", &spamRatio) != B_OK) goto ErrorExit; // Classification failed in one of many ways. } // Store the spam ratio in an attribute called MAIL:ratio_spam, // attached to the eventual output file. if (nodeForOutputFileInitialised) nodeForOutputFile.WriteAttr ("MAIL:ratio_spam", B_FLOAT_TYPE, 0 /* offset */, &spamRatio, sizeof (spamRatio)); // Also add it to the subject, if requested. if (fAddSpamToSubject && spamRatio >= fSpamCutoffRatio && io_headers->FindString ("Subject", &oldSubjectStringPntr) == B_OK) { newSubjectString.SetTo ("[Spam "); sprintf (percentageString, "%05.2f", spamRatio * 100.0); newSubjectString << percentageString << "%] "; newSubjectString << oldSubjectStringPntr; io_headers->ReplaceString ("Subject", newSubjectString); } // Beep using different sounds for spam and genuine, as Jeremy Friesner // nudged me to get around to implementing. And add uncertain to that, as // "BiPolar" suggested. If the user doesn't want to hear the sound, they // can turn it off in the system sound preferences. if (spamRatio >= fSpamCutoffRatio) { system_beep (kAGMSBayesBeepSpamName); } else if (spamRatio < fGenuineCutoffRatio) { system_beep (kAGMSBayesBeepGenuineName); } else { system_beep (kAGMSBayesBeepUncertainName); } return B_OK; ErrorExit: fprintf (stderr, "Error exit from " "SpamFilter::ProcessMailMessage, code maybe %ld (%s).\n", errorCode, strerror (errorCode)); delete [] stringBuffer; return B_OK; // Not MD_ERROR so the message doesn't get left on server. }
/*! Convert the plain text (UTF8) from inSource to plain or styled text in outDestination */ status_t translate_from_text(BPositionIO* source, const char* encoding, bool forceEncoding, BPositionIO* destination, uint32 outType) { if (outType != B_TRANSLATOR_TEXT && outType != B_STYLED_TEXT_FORMAT) return B_BAD_VALUE; // find the length of the text off_t size = source->Seek(0, SEEK_END); if (size < 0) return (status_t)size; if (size > UINT32_MAX && outType == B_STYLED_TEXT_FORMAT) return B_NOT_SUPPORTED; status_t status = source->Seek(0, SEEK_SET); if (status < B_OK) return status; if (outType == B_STYLED_TEXT_FORMAT) { // output styled text headers status = output_headers(destination, (uint32)size); if (status != B_OK) return status; } class MallocBuffer { public: MallocBuffer() : fBuffer(NULL), fSize(0) {} ~MallocBuffer() { free(fBuffer); } void* Buffer() { return fBuffer; } size_t Size() const { return fSize; } status_t Allocate(size_t size) { fBuffer = malloc(size); if (fBuffer != NULL) { fSize = size; return B_OK; } return B_NO_MEMORY; } private: void* fBuffer; size_t fSize; } encodingBuffer; BMallocIO encodingIO; uint32 encodingID = 0; // defaults to UTF-8 or no encoding BNode* node = dynamic_cast<BNode*>(source); if (node != NULL) { // determine encoding, if available const BCharacterSet* characterSet = NULL; bool hasAttribute = false; if (encoding != NULL && !forceEncoding) { BString name; if (node->ReadAttrString("be:encoding", &name) == B_OK) { encoding = name.String(); hasAttribute = true; } else { int32 value; ssize_t bytesRead = node->ReadAttr("be:encoding", B_INT32_TYPE, 0, &value, sizeof(value)); if (bytesRead == (ssize_t)sizeof(value)) { hasAttribute = true; if (value != 65535) characterSet = BCharacterSetRoster::GetCharacterSetByConversionID(value); } } } else { hasAttribute = true; // we don't write the encoding in this case } if (characterSet == NULL && encoding != NULL) characterSet = BCharacterSetRoster::FindCharacterSetByName(encoding); if (characterSet != NULL) { encodingID = characterSet->GetConversionID(); encodingBuffer.Allocate(READ_BUFFER_SIZE * 4); } if (!hasAttribute && encoding != NULL) { // add encoding attribute, so that someone opening the file can // retrieve it for persistance node->WriteAttr("be:encoding", B_STRING_TYPE, 0, encoding, strlen(encoding)); } } off_t outputSize = 0; ssize_t bytesRead; int32 state = 0; // output the actual text part of the data do { uint8 buffer[READ_BUFFER_SIZE]; bytesRead = source->Read(buffer, READ_BUFFER_SIZE); if (bytesRead < B_OK) return bytesRead; if (bytesRead == 0) break; if (encodingBuffer.Size() == 0) { // default, no encoding ssize_t bytesWritten = destination->Write(buffer, bytesRead); if (bytesWritten != bytesRead) { if (bytesWritten < B_OK) return bytesWritten; return B_ERROR; } outputSize += bytesRead; } else { // decode text file to UTF-8 char* pos = (char*)buffer; int32 encodingLength = encodingIO.BufferLength(); int32 bytesLeft = bytesRead; int32 bytes; do { encodingLength = READ_BUFFER_SIZE * 4; bytes = bytesLeft; status = convert_to_utf8(encodingID, pos, &bytes, (char*)encodingBuffer.Buffer(), &encodingLength, &state); if (status < B_OK) return status; ssize_t bytesWritten = destination->Write(encodingBuffer.Buffer(), encodingLength); if (bytesWritten < encodingLength) { if (bytesWritten < B_OK) return bytesWritten; return B_ERROR; } pos += bytes; bytesLeft -= bytes; outputSize += encodingLength; } while (encodingLength > 0 && bytesLeft > 0); } } while (bytesRead > 0); if (outType != B_STYLED_TEXT_FORMAT) return B_OK; if (encodingBuffer.Size() != 0 && size != outputSize) { if (outputSize > UINT32_MAX) return B_NOT_SUPPORTED; // we need to update the header as the decoded text size has changed status = destination->Seek(0, SEEK_SET); if (status == B_OK) status = output_headers(destination, (uint32)outputSize); if (status == B_OK) status = destination->Seek(0, SEEK_END); if (status < B_OK) return status; } // Read file attributes if outputting styled data // and source is a BNode object if (node == NULL) return B_OK; // Try to read styles - we only propagate an error if the actual on-disk // data is likely to be okay const char *kAttrName = "styles"; attr_info info; if (node->GetAttrInfo(kAttrName, &info) != B_OK) return B_OK; if (info.type != B_RAW_TYPE || info.size < 160) { // styles seem to be broken, but since we got the text, // we don't propagate the error return B_OK; } uint8* flatRunArray = new (std::nothrow) uint8[info.size]; if (flatRunArray == NULL) return B_NO_MEMORY; bytesRead = node->ReadAttr(kAttrName, B_RAW_TYPE, 0, flatRunArray, info.size); if (bytesRead != info.size) return B_OK; output_styles(destination, size, flatRunArray, info.size); delete[] flatRunArray; return B_OK; }
status_t CreateAppMetaMimeThread::DoMimeUpdate(const entry_ref* ref, bool* _entryIsDir) { if (ref == NULL) return B_BAD_VALUE; BNode typeNode; BFile file; status_t status = file.SetTo(ref, B_READ_ONLY); if (status < B_OK) return status; bool isDir = file.IsDirectory(); if (_entryIsDir != NULL) *_entryIsDir = isDir; if (isDir) return B_OK; BAppFileInfo appInfo(&file); status = appInfo.InitCheck(); if (status < B_OK) return status; // Read the app sig (which consequently keeps us from updating // non-applications, since we get an error if the file has no // app sig) BString signature; status = file.ReadAttrString("BEOS:APP_SIG", &signature); if (status < B_OK) return B_BAD_TYPE; // Init our various objects BMimeType mime; status = mime.SetTo(signature.String()); if (status < B_OK) return status; InstallNotificationDeferrer _(fDatabase, signature.String()); if (!mime.IsInstalled()) mime.Install(); BString path = "/"; path.Append(signature); path.ToLower(); // Signatures and MIME types are case insensitive, but we want to // preserve the case wherever possible path.Prepend(get_database_directory().c_str()); status = typeNode.SetTo(path.String()); if (status < B_OK) return status; // Preferred App attr_info info; if (status == B_OK && (fForce || typeNode.GetAttrInfo(kPreferredAppAttr, &info) != B_OK)) status = mime.SetPreferredApp(signature.String()); // Short Description (name of the application) if (status == B_OK && (fForce || typeNode.GetAttrInfo(kShortDescriptionAttr, &info) != B_OK)) status = mime.SetShortDescription(ref->name); // App Hint if (status == B_OK && (fForce || typeNode.GetAttrInfo(kAppHintAttr, &info) != B_OK)) status = mime.SetAppHint(ref); // Vector Icon if (status == B_OK && (fForce || typeNode.GetAttrInfo(kIconAttr, &info) != B_OK)) { uint8* data = NULL; size_t size = 0; if (appInfo.GetIcon(&data, &size) == B_OK) { status = mime.SetIcon(data, size); free(data); } } // Mini Icon BBitmap miniIcon(BRect(0, 0, 15, 15), B_BITMAP_NO_SERVER_LINK, B_CMAP8); if (status == B_OK && (fForce || typeNode.GetAttrInfo(kMiniIconAttr, &info) != B_OK)) { if (appInfo.GetIcon(&miniIcon, B_MINI_ICON) == B_OK) status = mime.SetIcon(&miniIcon, B_MINI_ICON); } // Large Icon BBitmap largeIcon(BRect(0, 0, 31, 31), B_BITMAP_NO_SERVER_LINK, B_CMAP8); if (status == B_OK && (fForce || typeNode.GetAttrInfo(kLargeIconAttr, &info) != B_OK)) { if (appInfo.GetIcon(&largeIcon, B_LARGE_ICON) == B_OK) status = mime.SetIcon(&largeIcon, B_LARGE_ICON); } // Supported Types bool setSupportedTypes = false; BMessage supportedTypes; if (status == B_OK && (fForce || typeNode.GetAttrInfo(kSupportedTypesAttr, &info) != B_OK)) { if (appInfo.GetSupportedTypes(&supportedTypes) == B_OK) setSupportedTypes = true; } // defer notifications for supported types const char* type; for (int32 i = 0; supportedTypes.FindString("types", i, &type) == B_OK; i++) fDatabase->DeferInstallNotification(type); // set supported types if (setSupportedTypes) status = mime.SetSupportedTypes(&supportedTypes); // Icons for supported types for (int32 i = 0; supportedTypes.FindString("types", i, &type) == B_OK; i++) { // vector icon uint8* data = NULL; size_t size = 0; if (status == B_OK && appInfo.GetIconForType(type, &data, &size) == B_OK) { status = mime.SetIconForType(type, data, size); free(data); } // mini icon if (status == B_OK && appInfo.GetIconForType(type, &miniIcon, B_MINI_ICON) == B_OK) status = mime.SetIconForType(type, &miniIcon, B_MINI_ICON); // large icon if (status == B_OK && appInfo.GetIconForType(type, &largeIcon, B_LARGE_ICON) == B_OK) status = mime.SetIconForType(type, &largeIcon, B_LARGE_ICON); } // undefer notifications for supported types for (int32 i = 0; supportedTypes.FindString("types", i, &type) == B_OK; i++) fDatabase->UndeferInstallNotification(type); return status; }