status_t POP3Protocol::SyncMessages() { bool leaveOnServer; if (fSettings.FindBool("leave_mail_on_server", &leaveOnServer) != B_OK) leaveOnServer = true; // create directory if not exist create_directory(fDestinationDir, 0777); printf("POP3Protocol::SyncMessages()\n"); _ReadManifest(); SetTotalItems(2); ReportProgress(0, 1, "Connect to server..."); status_t error = Connect(); if (error < B_OK) { ResetProgress(); return error; } ReportProgress(0, 1, MDR_DIALECT_CHOICE("Getting UniqueIDs...", "固有のIDを取得中...")); error = _UniqueIDs(); if (error < B_OK) { ResetProgress(); return error; } BStringList toDownload; fManifest.NotHere(fUniqueIDs, &toDownload); int32 numMessages = toDownload.CountItems(); if (numMessages == 0) { CheckForDeletedMessages(); ResetProgress(); return B_OK; } ResetProgress(); SetTotalItems(toDownload.CountItems()); printf("POP3: Messages to download: %i\n", (int)toDownload.CountItems()); for (int32 i = 0; i < toDownload.CountItems(); i++) { const char* uid = toDownload.ItemAt(i); int32 toRetrieve = fUniqueIDs.IndexOf(uid); if (toRetrieve < 0) { // should not happen! error = B_NAME_NOT_FOUND; printf("POP3: uid %s index %i not found in fUniqueIDs!\n", uid, (int)toRetrieve); continue; } BPath path(fDestinationDir); BString fileName = "Downloading file... uid: "; fileName += uid; fileName.ReplaceAll("/", "_SLASH_"); path.Append(fileName); BEntry entry(path.Path()); BFile file(&entry, B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE); error = file.InitCheck(); if (error != B_OK) { printf("POP3: Can't create file %s\n ", path.Path()); break; } BMailMessageIO mailIO(this, &file, toRetrieve); entry_ref ref; entry.GetRef(&ref); // the ref becomes invalid after renaming the file thus we already // write the status here MarkMessageAsRead(ref, B_UNREAD); int32 size = MessageSize(toRetrieve); if (fFetchBodyLimit < 0 || size <= fFetchBodyLimit) { error = mailIO.Seek(0, SEEK_END); if (error < 0) { printf("POP3: Failed to download body %s\n ", uid); break; } NotifyHeaderFetched(ref, &file); NotifyBodyFetched(ref, &file); if (!leaveOnServer) Delete(toRetrieve); } else { int32 dummy; error = mailIO.ReadAt(0, &dummy, 1); if (error < 0) { printf("POP3: Failed to download header %s\n ", uid); break; } NotifyHeaderFetched(ref, &file); } ReportProgress(0, 1); if (file.WriteAttr("MAIL:unique_id", B_STRING_TYPE, 0, uid, strlen(uid)) < 0) { error = B_ERROR; } file.WriteAttr("MAIL:size", B_INT32_TYPE, 0, &size, sizeof(int32)); // save manifest in case we get disturbed fManifest += uid; _WriteManifest(); } ResetProgress(); CheckForDeletedMessages(); Disconnect(); return error; }
status_t POP3Protocol::DeleteMessage(const entry_ref& ref) { status_t error = Connect(); if (error < B_OK) return error; error = _UniqueIDs(); if (error < B_OK) { Disconnect(); return error; } char uidString[256]; BNode node(&ref); if (node.ReadAttr("MAIL:unique_id", B_STRING_TYPE, 0, uidString, 256) < 0) { Disconnect(); return B_ERROR; } #if DEBUG printf("DeleteMessage: ID is %d\n", (int)fUniqueIDs.IndexOf(uidString)); // What should we use for int32 instead of %d? #endif Delete(fUniqueIDs.IndexOf(uidString)); Disconnect(); return B_OK; }
status_t POP3Protocol::FetchBody(const entry_ref& ref) { ResetProgress("Fetch body"); SetTotalItems(1); status_t error = Connect(); if (error < B_OK) return error; error = _UniqueIDs(); if (error < B_OK) { Disconnect(); return error; } BFile file(&ref, B_READ_WRITE); status_t status = file.InitCheck(); if (status != B_OK) { Disconnect(); return status; } char uidString[256]; BNode node(&ref); if (node.ReadAttr("MAIL:unique_id", B_STRING_TYPE, 0, uidString, 256) < 0) { Disconnect(); return B_ERROR; } int32 toRetrieve = fUniqueIDs.IndexOf(uidString); if (toRetrieve < 0) { Disconnect(); return B_NAME_NOT_FOUND; } bool leaveOnServer; if (fSettings.FindBool("leave_mail_on_server", &leaveOnServer) != B_OK) leaveOnServer = true; // TODO: get rid of this BMailMessageIO! BMailMessageIO io(this, &file, toRetrieve); // read body status = io.Seek(0, SEEK_END); if (status < 0) { Disconnect(); return status; } NotifyBodyFetched(ref, &file); if (!leaveOnServer) Delete(toRetrieve); ReportProgress(0, 1); ResetProgress(); Disconnect(); return B_OK; }