int RichTxt::GetVertMove(int pos, int gx, RichContext rc, int dir) const { ASSERT(dir == -1 || dir == 1); if(GetPartCount() == 0) return -1; int pi; int p = pos; if(pos >= 0) { pi = FindPart(p); pos -= p; } else { pi = dir > 0 ? 0 : GetPartCount() - 1; p = -1; pos = 0; } while(pi < GetPartCount()) { int q = IsTable(pi) ? GetTable(pi).GetVertMove(p, gx, rc, dir) : Get(pi, rc.styles).GetVertMove(p, gx, rc.page, dir); if(q >= 0) return q + pos; if(dir > 0) pos += GetPartLength(pi) + 1; p = -1; pi += dir; if(pi < 0) break; if(dir < 0) pos -= GetPartLength(pi) + 1; } return -1; }
void RichTxt::Normalize() { RichPara pa; if(GetPartCount() && IsTable(0)) { part.Insert(0); Put(0, pa, RichStyle::GetDefault()); Invalidate(); } if(GetPartCount() == 0 || IsTable(GetPartCount() - 1)) { Put(GetPartCount(), pa, RichStyle::GetDefault()); Invalidate(); } }
void RichTxt::RestoreFormat(int pi, const Formating& info, int& ii, const RichStyles& style) { Array<RichObject> dummy; while(ii < info.format.GetCount() && pi < GetPartCount()) { if(IsTable(pi)) { RichTable& tab = part[pi].Get<RichTable>(); for(int i = 0; i < tab.GetRows(); i++) for(int j = 0; j < tab.GetColumns(); j++) { if(tab(i, j)) { if(ii >= info.format.GetCount()) return; tab.InvalidateRefresh(i, j); tab[i][j].text.RestoreFormat(0, info, ii, style); } } pi++; } else { RichPara pa = Get(pi, style); RichPara pf; pf.Unpack(info.format[ii], dummy, GetStyle(style, info.styleid[ii]).format); RichPara t; t.format = pf.format; int si = 0; int sp = 0; for(int j = 0; j < pf.GetCount(); j++) { const RichPara::Part& q = pf[j]; for(int k = 0; k < q.text.GetLength(); k++) { int len = q.text[k] - 32; t.part.Add().format = q.format; while(len) { const RichPara::Part& p = pa[si]; if(p.IsText()) { int l = min(len, p.GetLength() - sp); t.part.Top().text.Cat(p.text.Mid(sp, l)); sp += l; len -= l; ASSERT(sp <= p.GetLength()); if(sp >= p.GetLength()) { sp = 0; si++; } } else { ASSERT(sp == 0); (t.part.Add() = pa[si++]).format = q.format; len--; sp = 0; } } } } ASSERT(si == pa.GetCount() && sp == 0); Put(pi, t, style); ii++; pi++; } } }
void RichTxt::ApplyZoom(Zoom z, const RichStyles& ostyle, const RichStyles& zstyle) { for(int i = 0; i < GetPartCount(); i++) if(IsTable(i)) part[i].Get<RichTable>().ApplyZoom(z, ostyle, zstyle); else { RichPara p = Get(i, ostyle); p.ApplyZoom(z); Set(i, p, zstyle); } }
bool CFileHashSet::SetHashSet(const QList<QByteArray>& HashSet) { ASSERT(!CanHashParts()); if(HashSet.size() != GetPartCount() || HashSet.isEmpty() || HashSet.at(0).size() != m_uSize) { ASSERT(0); return false; } m_HashSet.reserve(HashSet.size()); foreach(const QByteArray& Hash, HashSet) { byte* pHash = (byte*)hash_malloc(m_uSize); memcpy(pHash,Hash.data(),m_uSize); QWriteLocker Locker(&m_SetMutex); m_HashSet.append(pHash); }
WString RichTxt::GetPlainText() const { WString clip; for(int pi = 0; pi < GetPartCount(); pi++) { if(pi) { clip.Cat('\r'); clip.Cat('\n'); } if(IsTable(pi)) { const RichTable& tab = part[pi].Get<RichTable>(); for(int i = 0; i < tab.GetRows(); i++) for(int j = 0; j < tab.GetColumns(); j++) if(tab(i, j)) { if(i || j) { clip.Cat('\r'); clip.Cat('\n'); } clip << tab[i][j].text.GetPlainText(); } } else clip.Cat(Get(pi, RichStyle::GetDefault()).GetText()); } return clip; }
PageY RichTxt::GetHeight(RichContext rc) const { for(int i = 0; i < GetPartCount(); i++) rc.py = GetNextPageY(i, rc); return rc.py; }
CPacket* CKnownFile::CreateSrcInfoPacket(const CUpDownClient* forClient, uint8 byRequestedVersion, uint16 nRequestedOptions) { // Kad reviewed if (m_ClientUploadList.empty()) { return NULL; } if ((((CKnownFile*)forClient->GetRequestFile() != this) && ((CKnownFile*)forClient->GetUploadFile() != this)) || forClient->GetUploadFileID() != GetFileHash()) { wxString file1 = _("Unknown"); if (forClient->GetRequestFile() && forClient->GetRequestFile()->GetFileName().IsOk()) { file1 = forClient->GetRequestFile()->GetFileName().GetPrintable(); } else if (forClient->GetUploadFile() && forClient->GetUploadFile()->GetFileName().IsOk()) { file1 = forClient->GetUploadFile()->GetFileName().GetPrintable(); } wxString file2 = _("Unknown"); if (GetFileName().IsOk()) { file2 = GetFileName().GetPrintable(); } AddDebugLogLineM(false, logKnownFiles, wxT("File missmatch on source packet (K) Sending: ") + file1 + wxT(" From: ") + file2); return NULL; } const BitVector& rcvstatus = forClient->GetUpPartStatus(); bool SupportsUploadChunksState = !rcvstatus.empty(); //wxASSERT(rcvstatus.size() == GetPartCount()); // Obviously! if (rcvstatus.size() != GetPartCount()) { // Yuck. Same file but different part count? Seriously f****d up. AddDebugLogLineM(false, logKnownFiles, CFormat(wxT("Impossible situation: different partcounts for the same known file: %i (client) and %i (file)")) % rcvstatus.size() % GetPartCount()); return NULL; } CMemFile data(1024); uint8 byUsedVersion; bool bIsSX2Packet; if (forClient->SupportsSourceExchange2() && byRequestedVersion > 0){ // the client uses SourceExchange2 and requested the highest version he knows // and we send the highest version we know, but of course not higher than his request byUsedVersion = std::min(byRequestedVersion, (uint8)SOURCEEXCHANGE2_VERSION); bIsSX2Packet = true; data.WriteUInt8(byUsedVersion); // we don't support any special SX2 options yet, reserved for later use if (nRequestedOptions != 0) { AddDebugLogLineM(false, logKnownFiles, CFormat(wxT("Client requested unknown options for SourceExchange2: %u")) % nRequestedOptions); } } else { byUsedVersion = forClient->GetSourceExchange1Version(); bIsSX2Packet = false; if (forClient->SupportsSourceExchange2()) { AddDebugLogLineM(false, logKnownFiles, wxT("Client which announced to support SX2 sent SX1 packet instead")); } } uint16 nCount = 0; data.WriteHash(forClient->GetUploadFileID()); data.WriteUInt16(nCount); uint32 cDbgNoSrc = 0; SourceSet::iterator it = m_ClientUploadList.begin(); for ( ; it != m_ClientUploadList.end(); it++ ) { const CUpDownClient *cur_src = *it; if ( cur_src->HasLowID() || cur_src == forClient || !( cur_src->GetUploadState() == US_UPLOADING || cur_src->GetUploadState() == US_ONUPLOADQUEUE)) { continue; } bool bNeeded = false; if ( SupportsUploadChunksState ) { const BitVector& srcstatus = cur_src->GetUpPartStatus(); if ( !srcstatus.empty() ) { //wxASSERT(srcstatus.size() == GetPartCount()); // Obviously! if (srcstatus.size() != GetPartCount()) { continue; } if ( cur_src->GetUpPartCount() == forClient->GetUpPartCount() ) { for (int x = 0; x < GetPartCount(); x++ ) { if ( srcstatus.at(x) && !rcvstatus.at(x) ) { // We know the receiving client needs // a chunk from this client. bNeeded = true; break; } } } } else { cDbgNoSrc++; // This client doesn't support upload chunk status. // So just send it and hope for the best. bNeeded = true; } } else { // remote client does not support upload chunk status, // search sources which have at least one complete part // we could even sort the list of sources by available // chunks to return as much sources as possible which // have the most available chunks. but this could be // a noticeable performance problem. const BitVector& srcstatus = cur_src->GetUpPartStatus(); if ( !srcstatus.empty() ) { //wxASSERT(srcstatus.size() == GetPartCount()); if (srcstatus.size() != GetPartCount()) { continue; } for (int x = 0; x < GetPartCount(); x++ ) { if ( srcstatus.at(x) ) { // this client has at least one chunk bNeeded = true; break; } } } else { // This client doesn't support upload chunk status. // So just send it and hope for the best. bNeeded = true; } } if ( bNeeded ) { nCount++; uint32 dwID; if(byUsedVersion >= 3) { dwID = cur_src->GetUserIDHybrid(); } else { dwID = cur_src->GetIP(); } data.WriteUInt32(dwID); data.WriteUInt16(cur_src->GetUserPort()); data.WriteUInt32(cur_src->GetServerIP()); data.WriteUInt16(cur_src->GetServerPort()); if (byUsedVersion >= 2) { data.WriteHash(cur_src->GetUserHash()); } if (byUsedVersion >= 4){ // CryptSettings - SourceExchange V4 // 5 Reserved (!) // 1 CryptLayer Required // 1 CryptLayer Requested // 1 CryptLayer Supported const uint8 uSupportsCryptLayer = cur_src->SupportsCryptLayer() ? 1 : 0; const uint8 uRequestsCryptLayer = cur_src->RequestsCryptLayer() ? 1 : 0; const uint8 uRequiresCryptLayer = cur_src->RequiresCryptLayer() ? 1 : 0; const uint8 byCryptOptions = (uRequiresCryptLayer << 2) | (uRequestsCryptLayer << 1) | (uSupportsCryptLayer << 0); data.WriteUInt8(byCryptOptions); } if (nCount > 500) { break; } } } if (!nCount) { return 0; } data.Seek(bIsSX2Packet ? 17 : 16, wxFromStart); data.WriteUInt16(nCount); CPacket* result = new CPacket(data, OP_EMULEPROT, bIsSX2Packet ? OP_ANSWERSOURCES2 : OP_ANSWERSOURCES); if ( result->GetPacketSize() > 354 ) { result->PackPacket(); } return result; }
bool CKnownFile::LoadTagsFromFile(const CFileDataIO* file) { uint32 tagcount = file->ReadUInt32(); for (uint32 j = 0; j != tagcount; ++j) { CTag newtag(*file, true); switch(newtag.GetNameID()){ case FT_FILENAME: if (GetFileName().IsOk()) { // Unlike eMule, we actually prefer the second // filename tag, since we use it to specify the // 'universial' filename (see CPath::ToUniv). CPath path = CPath::FromUniv(newtag.GetStr()); // May be invalid, if from older versions where // unicoded filenames be saved as empty-strings. if (path.IsOk()) { SetFileName(path); } } else { SetFileName(CPath(newtag.GetStr())); } break; case FT_FILESIZE: SetFileSize(newtag.GetInt()); m_AvailPartFrequency.clear(); m_AvailPartFrequency.insert( m_AvailPartFrequency.begin(), GetPartCount(), 0); break; case FT_ATTRANSFERRED: statistic.alltimetransferred += newtag.GetInt(); break; case FT_ATTRANSFERREDHI: statistic.alltimetransferred = (((uint64)newtag.GetInt()) << 32) + ((uint64)statistic.alltimetransferred); break; case FT_ATREQUESTED: statistic.alltimerequested = newtag.GetInt(); break; case FT_ATACCEPTED: statistic.alltimeaccepted = newtag.GetInt(); break; case FT_ULPRIORITY: m_iUpPriority = newtag.GetInt(); if( m_iUpPriority == PR_AUTO ){ m_iUpPriority = PR_HIGH; m_bAutoUpPriority = true; } else { if ( m_iUpPriority != PR_VERYLOW && m_iUpPriority != PR_LOW && m_iUpPriority != PR_NORMAL && m_iUpPriority != PR_HIGH && m_iUpPriority != PR_VERYHIGH && m_iUpPriority != PR_POWERSHARE) { m_iUpPriority = PR_NORMAL; } m_bAutoUpPriority = false; } break; case FT_PERMISSIONS: // Ignore it, it's not used anymore. break; case FT_AICH_HASH: { CAICHHash hash; bool hashSizeOk = hash.DecodeBase32(newtag.GetStr()) == CAICHHash::GetHashSize(); wxASSERT(hashSizeOk); if (hashSizeOk) { m_pAICHHashSet->SetMasterHash(hash, AICH_HASHSETCOMPLETE); } break; } case FT_KADLASTPUBLISHSRC: SetLastPublishTimeKadSrc( newtag.GetInt(), 0 ); if(GetLastPublishTimeKadSrc() > (uint32)time(NULL)+KADEMLIAREPUBLISHTIMES) { //There may be a posibility of an older client that saved a random number here.. This will check for that.. SetLastPublishTimeKadSrc(0, 0); } break; case FT_KADLASTPUBLISHNOTES: SetLastPublishTimeKadNotes( newtag.GetInt() ); break; case FT_KADLASTPUBLISHKEY: // Just purge it wxASSERT( newtag.IsInt() ); break; default: // Store them here and write them back on saving. m_taglist.push_back(newtag); } } return true; }
void CKnownFile::UpdatePartsInfo() { // Cache part count uint16 partcount = GetPartCount(); bool flag = (time(NULL) - m_nCompleteSourcesTime > 0); // Ensure the frequency-list is ready if ( m_AvailPartFrequency.size() != GetPartCount() ) { m_AvailPartFrequency.clear(); m_AvailPartFrequency.insert(m_AvailPartFrequency.begin(), GetPartCount(), 0); } if (flag) { ArrayOfUInts16 count; count.reserve(m_ClientUploadList.size()); SourceSet::iterator it = m_ClientUploadList.begin(); for ( ; it != m_ClientUploadList.end(); it++ ) { if ( !(*it)->GetUpPartStatus().empty() && (*it)->GetUpPartCount() == partcount ) { count.push_back((*it)->GetUpCompleteSourcesCount()); } } m_nCompleteSourcesCount = m_nCompleteSourcesCountLo = m_nCompleteSourcesCountHi = 0; if( partcount > 0) { m_nCompleteSourcesCount = m_AvailPartFrequency[0]; } for (uint16 i = 1; i < partcount; ++i) { if( m_nCompleteSourcesCount > m_AvailPartFrequency[i]) { m_nCompleteSourcesCount = m_AvailPartFrequency[i]; } } count.push_back(m_nCompleteSourcesCount); int32 n = count.size(); if (n > 0) { std::sort(count.begin(), count.end(), std::less<uint16>()); // calculate range int i = n >> 1; // (n / 2) int j = (n * 3) >> 2; // (n * 3) / 4 int k = (n * 7) >> 3; // (n * 7) / 8 // For complete files, trust the people your uploading to more... // For low guess and normal guess count // - If we see more sources then the guessed low and // normal, use what we see. // - If we see less sources then the guessed low, // adjust network accounts for 100%, we account for // 0% with what we see and make sure we are still // above the normal. // For high guess // Adjust 100% network and 0% what we see. if (n < 20) { if ( count[i] < m_nCompleteSourcesCount ) { m_nCompleteSourcesCountLo = m_nCompleteSourcesCount; } else { m_nCompleteSourcesCountLo = count[i]; } m_nCompleteSourcesCount= m_nCompleteSourcesCountLo; m_nCompleteSourcesCountHi = count[j]; if( m_nCompleteSourcesCountHi < m_nCompleteSourcesCount ) { m_nCompleteSourcesCountHi = m_nCompleteSourcesCount; } } else { // Many sources.. // For low guess // Use what we see. // For normal guess // Adjust network accounts for 100%, we account for // 0% with what we see and make sure we are still above the low. // For high guess // Adjust network accounts for 100%, we account for 0% // with what we see and make sure we are still above the normal. m_nCompleteSourcesCountLo = m_nCompleteSourcesCount; m_nCompleteSourcesCount = count[j]; if( m_nCompleteSourcesCount < m_nCompleteSourcesCountLo ) { m_nCompleteSourcesCount = m_nCompleteSourcesCountLo; } m_nCompleteSourcesCountHi= count[k]; if( m_nCompleteSourcesCountHi < m_nCompleteSourcesCount ) { m_nCompleteSourcesCountHi = m_nCompleteSourcesCount; } } } m_nCompleteSourcesTime = time(NULL) + (60); }