2014-05-30 12:53:19 +04:00
/*
This file is part of Telegram Desktop ,
2014-12-01 13:47:38 +03:00
the official desktop version of Telegram messaging app , see https : //telegram.org
2014-05-30 12:53:19 +04:00
Telegram Desktop is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
It is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
2015-10-03 16:16:42 +03:00
In addition , as a special exception , the copyright holders give permission
to link the code of portions of this program with the OpenSSL library .
2014-05-30 12:53:19 +04:00
Full license : https : //github.com/telegramdesktop/tdesktop/blob/master/LICENSE
2016-02-08 13:56:18 +03:00
Copyright ( c ) 2014 - 2016 John Preston , https : //desktop.telegram.org
2014-05-30 12:53:19 +04:00
*/
# include "stdafx.h"
2016-03-23 21:43:12 +03:00
# include "mtproto/file_download.h"
2014-05-30 12:53:19 +04:00
# include "mainwidget.h"
# include "window.h"
2014-10-30 19:23:44 +03:00
# include "application.h"
2014-11-22 12:45:04 +03:00
# include "localstorage.h"
2014-10-30 19:23:44 +03:00
2014-05-30 12:53:19 +04:00
namespace {
2015-12-24 22:26:28 +03:00
int32 GlobalPriority = 1 ;
2014-10-30 19:23:44 +03:00
struct DataRequested {
DataRequested ( ) {
memset ( v , 0 , sizeof ( v ) ) ;
}
int64 v [ MTPDownloadSessionsCount ] ;
} ;
2015-12-24 22:26:28 +03:00
QMap < int32 , DataRequested > DataRequestedMap ;
2014-05-30 12:53:19 +04:00
}
2015-12-31 03:09:20 +08:00
struct FileLoaderQueue {
FileLoaderQueue ( int32 limit ) : queries ( 0 ) , limit ( limit ) , start ( 0 ) , end ( 0 ) {
2014-05-30 12:53:19 +04:00
}
2015-12-31 03:09:20 +08:00
int32 queries , limit ;
FileLoader * start , * end ;
2014-05-30 12:53:19 +04:00
} ;
namespace {
2015-12-31 03:09:20 +08:00
typedef QMap < int32 , FileLoaderQueue > LoaderQueues ;
2014-05-30 12:53:19 +04:00
LoaderQueues queues ;
2015-12-31 03:09:20 +08:00
FileLoaderQueue _webQueue ( MaxWebFileQueries ) ;
QThread * _webLoadThread = 0 ;
WebLoadManager * _webLoadManager = 0 ;
WebLoadManager * webLoadManager ( ) {
return ( _webLoadManager & & _webLoadManager ! = FinishedWebLoadManager ) ? _webLoadManager : 0 ;
2014-05-30 12:53:19 +04:00
}
2015-12-31 03:09:20 +08:00
WebLoadMainManager * _webLoadMainManager = 0 ;
2014-05-30 12:53:19 +04:00
}
2015-12-31 13:34:43 +08:00
FileLoader : : FileLoader ( const QString & toFile , int32 size , LocationType locationType , LoadToCacheSetting toCache , LoadFromCloudSetting fromCloud , bool autoLoading )
2015-12-31 03:09:20 +08:00
: _prev ( 0 )
, _next ( 0 )
, _priority ( 0 )
2015-12-23 22:23:14 +03:00
, _paused ( false )
2015-12-24 22:26:28 +03:00
, _autoLoading ( autoLoading )
, _inQueue ( false )
, _complete ( false )
2015-12-23 22:23:14 +03:00
, _localStatus ( LocalNotTried )
2015-12-31 23:28:54 +08:00
, _file ( toFile )
, _fname ( toFile )
2015-12-24 22:26:28 +03:00
, _fileIsOpen ( false )
2015-12-31 13:34:43 +08:00
, _toCache ( toCache )
2015-12-24 22:26:28 +03:00
, _fromCloud ( fromCloud )
, _size ( size )
, _type ( mtpc_storage_fileUnknown )
2015-12-31 03:09:20 +08:00
, _locationType ( locationType )
2015-12-23 22:23:14 +03:00
, _localTaskId ( 0 ) {
2014-05-30 12:53:19 +04:00
}
2015-12-31 03:09:20 +08:00
QByteArray FileLoader : : imageFormat ( ) const {
2015-09-29 21:44:31 +03:00
if ( _imageFormat . isEmpty ( ) & & _locationType = = UnknownFileLocation ) {
readImage ( ) ;
}
return _imageFormat ;
2014-05-30 12:53:19 +04:00
}
2015-12-31 03:09:20 +08:00
QPixmap FileLoader : : imagePixmap ( ) const {
2015-09-29 21:44:31 +03:00
if ( _imagePixmap . isNull ( ) & & _locationType = = UnknownFileLocation ) {
readImage ( ) ;
}
return _imagePixmap ;
2014-05-30 12:53:19 +04:00
}
2015-12-31 03:09:20 +08:00
void FileLoader : : readImage ( ) const {
2015-09-29 21:44:31 +03:00
QByteArray format ;
2015-12-24 22:26:28 +03:00
switch ( _type ) {
2015-09-29 21:44:31 +03:00
case mtpc_storage_fileGif : format = " GIF " ; break ;
case mtpc_storage_fileJpeg : format = " JPG " ; break ;
case mtpc_storage_filePng : format = " PNG " ; break ;
default : format = QByteArray ( ) ; break ;
}
2015-12-24 22:26:28 +03:00
_imagePixmap = QPixmap : : fromImage ( App : : readImage ( _data , & format , false ) , Qt : : ColorOnly ) ;
2015-09-29 21:44:31 +03:00
if ( ! _imagePixmap . isNull ( ) ) {
_imageFormat = format ;
}
2014-05-30 12:53:19 +04:00
}
2015-12-31 03:09:20 +08:00
float64 FileLoader : : currentProgress ( ) const {
2015-12-24 22:26:28 +03:00
if ( _complete ) return 1 ;
2014-05-30 12:53:19 +04:00
if ( ! fullSize ( ) ) return 0 ;
return float64 ( currentOffset ( ) ) / fullSize ( ) ;
}
2015-12-31 03:09:20 +08:00
int32 FileLoader : : fullSize ( ) const {
2015-12-24 22:26:28 +03:00
return _size ;
2014-05-30 12:53:19 +04:00
}
2015-12-31 03:09:20 +08:00
bool FileLoader : : setFileName ( const QString & fileName ) {
2015-12-24 22:26:28 +03:00
if ( _toCache ! = LoadToCacheAsWell | | ! _fname . isEmpty ( ) ) return fileName . isEmpty ( ) ;
_fname = fileName ;
_file . setFileName ( _fname ) ;
return true ;
}
2015-12-31 03:09:20 +08:00
void FileLoader : : permitLoadFromCloud ( ) {
2015-12-24 22:26:28 +03:00
_fromCloud = LoadFromCloudOrLocal ;
2014-09-04 11:33:44 +04:00
}
2015-12-31 03:09:20 +08:00
void FileLoader : : loadNext ( ) {
if ( _queue - > queries > = _queue - > limit ) return ;
for ( FileLoader * i = _queue - > start ; i ; ) {
if ( i - > loadPart ( ) ) {
if ( _queue - > queries > = _queue - > limit ) return ;
} else {
i = i - > _next ;
}
}
2014-05-30 12:53:19 +04:00
}
2015-12-31 03:09:20 +08:00
void FileLoader : : removeFromQueue ( ) {
if ( ! _inQueue ) return ;
if ( _next ) {
_next - > _prev = _prev ;
}
if ( _prev ) {
_prev - > _next = _next ;
}
if ( _queue - > end = = this ) {
_queue - > end = _prev ;
}
if ( _queue - > start = = this ) {
_queue - > start = _next ;
}
_next = _prev = 0 ;
_inQueue = false ;
}
void FileLoader : : pause ( ) {
removeFromQueue ( ) ;
_paused = true ;
}
FileLoader : : ~ FileLoader ( ) {
if ( _localTaskId ) {
Local : : cancelTask ( _localTaskId ) ;
}
removeFromQueue ( ) ;
}
void FileLoader : : localLoaded ( const StorageImageSaved & result , const QByteArray & imageFormat , const QPixmap & imagePixmap ) {
_localTaskId = 0 ;
if ( result . type = = StorageFileUnknown ) {
_localStatus = LocalFailed ;
start ( true ) ;
return ;
}
_data = result . data ;
_type = mtpFromStorageType ( result . type ) ;
if ( ! imagePixmap . isNull ( ) ) {
_imageFormat = imageFormat ;
_imagePixmap = imagePixmap ;
}
_localStatus = LocalLoaded ;
if ( ! _fname . isEmpty ( ) & & _toCache = = LoadToCacheAsWell ) {
if ( ! _fileIsOpen ) _fileIsOpen = _file . open ( QIODevice : : WriteOnly ) ;
if ( ! _fileIsOpen ) {
cancel ( true ) ;
return ;
}
if ( _file . write ( _data ) ! = qint64 ( _data . size ( ) ) ) {
cancel ( true ) ;
return ;
}
}
_complete = true ;
if ( _fileIsOpen ) {
_file . close ( ) ;
_fileIsOpen = false ;
psPostprocessFile ( QFileInfo ( _file ) . absoluteFilePath ( ) ) ;
}
emit App : : wnd ( ) - > imageLoaded ( ) ;
emit progress ( this ) ;
loadNext ( ) ;
}
void FileLoader : : start ( bool loadFirst , bool prior ) {
if ( _paused ) {
_paused = false ;
}
if ( _complete | | tryLoadLocal ( ) ) return ;
if ( _fromCloud = = LoadFromLocalOnly ) {
cancel ( ) ;
return ;
}
if ( ! _fname . isEmpty ( ) & & _toCache = = LoadToFileOnly & & ! _fileIsOpen ) {
_fileIsOpen = _file . open ( QIODevice : : WriteOnly ) ;
if ( ! _fileIsOpen ) {
return cancel ( true ) ;
}
}
FileLoader * before = 0 , * after = 0 ;
if ( prior ) {
if ( _inQueue & & _priority = = GlobalPriority ) {
if ( loadFirst ) {
if ( ! _prev ) return startLoading ( loadFirst , prior ) ;
before = _queue - > start ;
} else {
if ( ! _next | | _next - > _priority < GlobalPriority ) return startLoading ( loadFirst , prior ) ;
after = _next ;
while ( after - > _next & & after - > _next - > _priority = = GlobalPriority ) {
after = after - > _next ;
}
}
2014-10-30 19:23:44 +03:00
} else {
2015-12-31 03:09:20 +08:00
_priority = GlobalPriority ;
if ( loadFirst ) {
if ( _inQueue & & ! _prev ) return startLoading ( loadFirst , prior ) ;
before = _queue - > start ;
} else {
if ( _inQueue ) {
if ( _next & & _next - > _priority = = GlobalPriority ) {
after = _next ;
} else if ( _prev & & _prev - > _priority < GlobalPriority ) {
before = _prev ;
while ( before - > _prev & & before - > _prev - > _priority < GlobalPriority ) {
before = before - > _prev ;
}
} else {
return startLoading ( loadFirst , prior ) ;
}
} else {
if ( _queue - > start & & _queue - > start - > _priority = = GlobalPriority ) {
after = _queue - > start ;
} else {
before = _queue - > start ;
}
}
if ( after ) {
while ( after - > _next & & after - > _next - > _priority = = GlobalPriority ) {
after = after - > _next ;
}
}
}
}
} else {
if ( loadFirst ) {
if ( _inQueue & & ( ! _prev | | _prev - > _priority = = GlobalPriority ) ) return startLoading ( loadFirst , prior ) ;
before = _prev ;
while ( before - > _prev & & before - > _prev - > _priority ! = GlobalPriority ) {
before = before - > _prev ;
}
} else {
if ( _inQueue & & ! _next ) return startLoading ( loadFirst , prior ) ;
after = _queue - > end ;
}
}
removeFromQueue ( ) ;
_inQueue = true ;
if ( ! _queue - > start ) {
_queue - > start = _queue - > end = this ;
} else if ( before ) {
if ( before ! = _next ) {
_prev = before - > _prev ;
_next = before ;
_next - > _prev = this ;
if ( _prev ) {
_prev - > _next = this ;
}
if ( _queue - > start - > _prev ) _queue - > start = _queue - > start - > _prev ;
}
} else if ( after ) {
if ( after ! = _prev ) {
_next = after - > _next ;
_prev = after ;
after - > _next = this ;
if ( _next ) {
_next - > _prev = this ;
}
if ( _queue - > end - > _next ) _queue - > end = _queue - > end - > _next ;
2014-10-30 19:23:44 +03:00
}
2015-12-31 03:09:20 +08:00
} else {
LOG ( ( " Queue Error: _start && !before && !after " ) ) ;
}
return startLoading ( loadFirst , prior ) ;
}
void FileLoader : : cancel ( ) {
cancel ( false ) ;
}
void FileLoader : : cancel ( bool fail ) {
bool started = currentOffset ( true ) > 0 ;
cancelRequests ( ) ;
_type = mtpc_storage_fileUnknown ;
_complete = true ;
if ( _fileIsOpen ) {
_file . close ( ) ;
_fileIsOpen = false ;
_file . remove ( ) ;
}
_data = QByteArray ( ) ;
if ( fail ) {
emit failed ( this , started ) ;
} else {
emit progress ( this ) ;
}
_fname = QString ( ) ;
_file . setFileName ( _fname ) ;
loadNext ( ) ;
}
void FileLoader : : startLoading ( bool loadFirst , bool prior ) {
if ( ( _queue - > queries > = _queue - > limit & & ( ! loadFirst | | ! prior ) ) | | _complete ) return ;
loadPart ( ) ;
}
mtpFileLoader : : mtpFileLoader ( const StorageImageLocation * location , int32 size , LoadFromCloudSetting fromCloud , bool autoLoading )
2015-12-31 13:34:43 +08:00
: FileLoader ( QString ( ) , size , UnknownFileLocation , LoadToCacheAsWell , fromCloud , autoLoading )
2015-12-31 03:09:20 +08:00
, _lastComplete ( false )
, _skippedBytes ( 0 )
, _nextRequestOffset ( 0 )
, _dc ( location - > dc ( ) )
, _location ( location )
, _id ( 0 )
, _access ( 0 ) {
2016-03-24 11:57:11 +03:00
LoaderQueues : : iterator i = queues . find ( MTP : : dldDcId ( _dc , 0 ) ) ;
2015-12-31 03:09:20 +08:00
if ( i = = queues . cend ( ) ) {
2016-03-24 11:57:11 +03:00
i = queues . insert ( MTP : : dldDcId ( _dc , 0 ) , FileLoaderQueue ( MaxFileQueries ) ) ;
2015-12-31 03:09:20 +08:00
}
_queue = & i . value ( ) ;
}
mtpFileLoader : : mtpFileLoader ( int32 dc , const uint64 & id , const uint64 & access , LocationType type , const QString & to , int32 size , LoadToCacheSetting toCache , LoadFromCloudSetting fromCloud , bool autoLoading )
2015-12-31 13:34:43 +08:00
: FileLoader ( to , size , type , toCache , fromCloud , autoLoading )
2015-12-31 03:09:20 +08:00
, _lastComplete ( false )
, _skippedBytes ( 0 )
, _nextRequestOffset ( 0 )
, _dc ( dc )
, _location ( 0 )
, _id ( id )
, _access ( access ) {
2016-03-24 11:57:11 +03:00
LoaderQueues : : iterator i = queues . find ( MTP : : dldDcId ( _dc , 0 ) ) ;
2015-12-31 03:09:20 +08:00
if ( i = = queues . cend ( ) ) {
2016-03-24 11:57:11 +03:00
i = queues . insert ( MTP : : dldDcId ( _dc , 0 ) , FileLoaderQueue ( MaxFileQueries ) ) ;
2014-05-30 12:53:19 +04:00
}
2015-12-31 03:09:20 +08:00
_queue = & i . value ( ) ;
}
int32 mtpFileLoader : : currentOffset ( bool includeSkipped ) const {
return ( _fileIsOpen ? _file . size ( ) : _data . size ( ) ) - ( includeSkipped ? 0 : _skippedBytes ) ;
2014-05-30 12:53:19 +04:00
}
2016-03-17 21:03:08 +03:00
namespace {
QString serializereqs ( const QMap < mtpRequestId , int32 > & reqs ) { // serialize requests map in json-like format
QString result ;
result . reserve ( reqs . size ( ) * 16 + 4 ) ;
result . append ( qsl ( " { " ) ) ;
for ( auto i = reqs . cbegin ( ) , e = reqs . cend ( ) ; i ! = e ; ) {
result . append ( QString : : number ( i . key ( ) ) ) . append ( qsl ( " : " ) ) . append ( QString : : number ( i . value ( ) ) ) ;
if ( + + i = = e ) {
break ;
} else {
result . append ( qsl ( " , " ) ) ;
}
}
result . append ( qsl ( " } " ) ) ;
return result ;
}
}
2014-05-30 12:53:19 +04:00
bool mtpFileLoader : : loadPart ( ) {
2016-03-17 21:03:08 +03:00
if ( _complete | | _lastComplete | | ( ! _requests . isEmpty ( ) & & ! _size ) ) {
if ( DebugLogging : : FileLoader ( ) & & _id ) DEBUG_LOG ( ( " FileLoader(%1): loadPart() returned, _complete=%2, _lastComplete=%3, _requests.size()=%4, _size=%5 " ) . arg ( _id ) . arg ( Logs : : b ( _complete ) ) . arg ( Logs : : b ( _lastComplete ) ) . arg ( _requests . size ( ) ) . arg ( _size ) ) ;
return false ;
}
if ( _size & & _nextRequestOffset > = _size ) {
if ( DebugLogging : : FileLoader ( ) & & _id ) DEBUG_LOG ( ( " FileLoader(%1): loadPart() returned, _size=%2, _nextRequestOffset=%3, _requests=%4 " ) . arg ( _id ) . arg ( _size ) . arg ( _nextRequestOffset ) . arg ( serializereqs ( _requests ) ) ) ;
return false ;
}
2014-05-30 12:53:19 +04:00
int32 limit = DocumentDownloadPartSize ;
MTPInputFileLocation loc ;
2015-12-24 22:26:28 +03:00
if ( _location ) {
loc = MTP_inputFileLocation ( MTP_long ( _location - > volume ( ) ) , MTP_int ( _location - > local ( ) ) , MTP_long ( _location - > secret ( ) ) ) ;
2015-09-29 18:29:21 +03:00
limit = DownloadPartSize ;
2015-12-24 22:26:28 +03:00
} else {
switch ( _locationType ) {
2016-02-12 21:18:32 +03:00
case VideoFileLocation :
case AudioFileLocation :
2015-12-31 03:09:20 +08:00
case DocumentFileLocation : loc = MTP_inputDocumentFileLocation ( MTP_long ( _id ) , MTP_long ( _access ) ) ; break ;
default : cancel ( true ) ; return false ; break ;
2015-12-24 22:26:28 +03:00
}
2014-05-30 12:53:19 +04:00
}
2015-12-24 22:26:28 +03:00
int32 offset = _nextRequestOffset , dcIndex = 0 ;
DataRequested & dr ( DataRequestedMap [ _dc ] ) ;
if ( _size ) {
2014-10-30 19:23:44 +03:00
for ( int32 i = 1 ; i < MTPDownloadSessionsCount ; + + i ) {
if ( dr . v [ i ] < dr . v [ dcIndex ] ) {
dcIndex = i ;
}
}
}
2015-12-24 22:26:28 +03:00
App : : app ( ) - > killDownloadSessionsStop ( _dc ) ;
2014-10-30 19:23:44 +03:00
2016-03-24 11:57:11 +03:00
mtpRequestId reqId = MTP : : send ( MTPupload_GetFile ( MTPupload_getFile ( loc , MTP_int ( offset ) , MTP_int ( limit ) ) ) , rpcDone ( & mtpFileLoader : : partLoaded , offset ) , rpcFail ( & mtpFileLoader : : partFailed ) , MTP : : dldDcId ( _dc , dcIndex ) , 50 ) ;
2014-10-30 19:23:44 +03:00
2015-12-31 03:09:20 +08:00
+ + _queue - > queries ;
2014-10-30 19:23:44 +03:00
dr . v [ dcIndex ] + = limit ;
2015-12-24 22:26:28 +03:00
_requests . insert ( reqId , dcIndex ) ;
_nextRequestOffset + = limit ;
2014-10-30 19:23:44 +03:00
2016-03-17 21:03:08 +03:00
if ( DebugLogging : : FileLoader ( ) & & _id ) DEBUG_LOG ( ( " FileLoader(%1): requested part with offset=%2, _queue->queries=%3, _nextRequestOffset=%4, _requests=%5 " ) . arg ( _id ) . arg ( offset ) . arg ( _queue - > queries ) . arg ( _nextRequestOffset ) . arg ( serializereqs ( _requests ) ) ) ;
2014-05-30 12:53:19 +04:00
return true ;
}
2014-10-30 19:23:44 +03:00
void mtpFileLoader : : partLoaded ( int32 offset , const MTPupload_File & result , mtpRequestId req ) {
2015-12-24 22:26:28 +03:00
Requests : : iterator i = _requests . find ( req ) ;
2016-03-17 21:03:08 +03:00
if ( i = = _requests . cend ( ) ) {
if ( DebugLogging : : FileLoader ( ) & & _id ) DEBUG_LOG ( ( " FileLoader(%1): request req=%2 for offset=%3 not found in _requests=%4 " ) . arg ( _id ) . arg ( req ) . arg ( offset ) . arg ( serializereqs ( _requests ) ) ) ;
return loadNext ( ) ;
}
if ( result . type ( ) ! = mtpc_upload_file ) {
if ( DebugLogging : : FileLoader ( ) & & _id ) DEBUG_LOG ( ( " FileLoader(%1): bad cons received! %2 " ) . arg ( _id ) . arg ( result . type ( ) ) ) ;
return cancel ( true ) ;
}
2014-10-30 19:23:44 +03:00
2015-09-29 18:29:21 +03:00
int32 limit = ( _locationType = = UnknownFileLocation ) ? DownloadPartSize : DocumentDownloadPartSize ;
2014-10-30 19:23:44 +03:00
int32 dcIndex = i . value ( ) ;
2015-12-24 22:26:28 +03:00
DataRequestedMap [ _dc ] . v [ dcIndex ] - = limit ;
2014-10-30 19:23:44 +03:00
2015-12-31 03:09:20 +08:00
- - _queue - > queries ;
2015-12-24 22:26:28 +03:00
_requests . erase ( i ) ;
2014-10-30 19:23:44 +03:00
2016-04-08 14:44:35 +04:00
const auto & d ( result . c_upload_file ( ) ) ;
2014-10-30 19:23:44 +03:00
const string & bytes ( d . vbytes . c_string ( ) . v ) ;
2016-03-17 21:03:08 +03:00
if ( DebugLogging : : FileLoader ( ) & & _id ) DEBUG_LOG ( ( " FileLoader(%1): got part with offset=%2, bytes=%3, _queue->queries=%4, _nextRequestOffset=%5, _requests=%6 " ) . arg ( _id ) . arg ( offset ) . arg ( bytes . size ( ) ) . arg ( _queue - > queries ) . arg ( _nextRequestOffset ) . arg ( serializereqs ( _requests ) ) ) ;
2014-10-30 19:23:44 +03:00
if ( bytes . size ( ) ) {
2015-12-24 22:26:28 +03:00
if ( _fileIsOpen ) {
int64 fsize = _file . size ( ) ;
2014-10-30 19:23:44 +03:00
if ( offset < fsize ) {
2015-12-24 22:26:28 +03:00
_skippedBytes - = bytes . size ( ) ;
2014-10-30 19:23:44 +03:00
} else if ( offset > fsize ) {
2015-12-24 22:26:28 +03:00
_skippedBytes + = offset - fsize ;
2014-10-30 19:23:44 +03:00
}
2015-12-24 22:26:28 +03:00
_file . seek ( offset ) ;
if ( _file . write ( bytes . data ( ) , bytes . size ( ) ) ! = qint64 ( bytes . size ( ) ) ) {
return cancel ( true ) ;
2014-05-30 12:53:19 +04:00
}
} else {
2015-12-24 22:26:28 +03:00
_data . reserve ( offset + bytes . size ( ) ) ;
if ( offset > _data . size ( ) ) {
_skippedBytes + = offset - _data . size ( ) ;
_data . resize ( offset ) ;
2014-10-30 19:23:44 +03:00
}
2015-12-24 22:26:28 +03:00
if ( offset = = _data . size ( ) ) {
_data . append ( bytes . data ( ) , bytes . size ( ) ) ;
2014-10-30 19:23:44 +03:00
} else {
2015-12-24 22:26:28 +03:00
_skippedBytes - = bytes . size ( ) ;
if ( int64 ( offset + bytes . size ( ) ) > _data . size ( ) ) {
_data . resize ( offset + bytes . size ( ) ) ;
2014-09-04 11:33:44 +04:00
}
2015-12-24 22:26:28 +03:00
memcpy ( _data . data ( ) + offset , bytes . data ( ) , bytes . size ( ) ) ;
2014-09-04 11:33:44 +04:00
}
2014-10-30 19:23:44 +03:00
}
}
if ( ! bytes . size ( ) | | ( bytes . size ( ) % 1024 ) ) { // bad next offset
2015-12-24 22:26:28 +03:00
_lastComplete = true ;
2014-10-30 19:23:44 +03:00
}
2015-12-24 22:26:28 +03:00
if ( _requests . isEmpty ( ) & & ( _lastComplete | | ( _size & & _nextRequestOffset > = _size ) ) ) {
if ( ! _fname . isEmpty ( ) & & ( _toCache = = LoadToCacheAsWell ) ) {
if ( ! _fileIsOpen ) _fileIsOpen = _file . open ( QIODevice : : WriteOnly ) ;
if ( ! _fileIsOpen ) {
return cancel ( true ) ;
2014-05-30 12:53:19 +04:00
}
2015-12-24 22:26:28 +03:00
if ( _file . write ( _data ) ! = qint64 ( _data . size ( ) ) ) {
return cancel ( true ) ;
2014-10-30 19:23:44 +03:00
}
}
2015-12-24 22:26:28 +03:00
_type = d . vtype . type ( ) ;
_complete = true ;
if ( _fileIsOpen ) {
_file . close ( ) ;
_fileIsOpen = false ;
psPostprocessFile ( QFileInfo ( _file ) . absoluteFilePath ( ) ) ;
2014-10-30 19:23:44 +03:00
}
removeFromQueue ( ) ;
2015-05-19 18:46:45 +03:00
emit App : : wnd ( ) - > imageLoaded ( ) ;
2015-12-31 03:09:20 +08:00
if ( ! _queue - > queries ) {
2015-12-24 22:26:28 +03:00
App : : app ( ) - > killDownloadSessionsStart ( _dc ) ;
2014-05-30 12:53:19 +04:00
}
2014-11-22 12:45:04 +03:00
2015-09-29 18:29:21 +03:00
if ( _localStatus = = LocalNotFound | | _localStatus = = LocalFailed ) {
if ( _locationType ! = UnknownFileLocation ) { // audio, video, document
2015-12-24 22:26:28 +03:00
MediaKey mkey = mediaKey ( _locationType , _dc , _id ) ;
if ( ! _fname . isEmpty ( ) ) {
Local : : writeFileLocation ( mkey , FileLocation ( mtpToStorageType ( _type ) , _fname ) ) ;
2015-01-02 17:55:24 +03:00
}
2015-12-24 22:26:28 +03:00
if ( _toCache = = LoadToCacheAsWell ) {
2015-09-29 18:29:21 +03:00
if ( _locationType = = DocumentFileLocation ) {
2015-12-24 22:26:28 +03:00
Local : : writeStickerImage ( mkey , _data ) ;
2015-09-29 18:29:21 +03:00
} else if ( _locationType = = AudioFileLocation ) {
2015-12-24 22:26:28 +03:00
Local : : writeAudio ( mkey , _data ) ;
2015-09-29 18:29:21 +03:00
}
}
} else {
2015-12-24 22:26:28 +03:00
Local : : writeImage ( storageKey ( * _location ) , StorageImageSaved ( mtpToStorageType ( _type ) , _data ) ) ;
2015-01-02 17:55:24 +03:00
}
2014-11-22 12:45:04 +03:00
}
2016-03-17 21:03:08 +03:00
} else {
if ( DebugLogging : : FileLoader ( ) & & _id ) DEBUG_LOG ( ( " FileLoader(%1): not done yet, _lastComplete=%2, _size=%3, _nextRequestOffset=%4, _requests=%5 " ) . arg ( _id ) . arg ( Logs : : b ( _lastComplete ) ) . arg ( _size ) . arg ( _nextRequestOffset ) . arg ( serializereqs ( _requests ) ) ) ;
2014-05-30 12:53:19 +04:00
}
2014-10-30 19:23:44 +03:00
emit progress ( this ) ;
2014-05-30 12:53:19 +04:00
loadNext ( ) ;
}
bool mtpFileLoader : : partFailed ( const RPCError & error ) {
2016-04-08 14:44:35 +04:00
if ( MTP : : isDefaultHandledError ( error ) ) return false ;
2015-04-04 23:01:34 +03:00
2015-12-24 22:26:28 +03:00
cancel ( true ) ;
2014-05-30 12:53:19 +04:00
return true ;
}
2015-12-31 03:09:20 +08:00
void mtpFileLoader : : cancelRequests ( ) {
if ( _requests . isEmpty ( ) ) return ;
int32 limit = ( _locationType = = UnknownFileLocation ) ? DownloadPartSize : DocumentDownloadPartSize ;
DataRequested & dr ( DataRequestedMap [ _dc ] ) ;
for ( Requests : : const_iterator i = _requests . cbegin ( ) , e = _requests . cend ( ) ; i ! = e ; + + i ) {
MTP : : cancel ( i . key ( ) ) ;
int32 dcIndex = i . value ( ) ;
dr . v [ dcIndex ] - = limit ;
2014-05-30 12:53:19 +04:00
}
2015-12-31 03:09:20 +08:00
_queue - > queries - = _requests . size ( ) ;
_requests . clear ( ) ;
2014-05-30 12:53:19 +04:00
2016-03-01 21:41:06 +02:00
if ( ! _queue - > queries & & App : : app ( ) ) {
2015-12-31 03:09:20 +08:00
App : : app ( ) - > killDownloadSessionsStart ( _dc ) ;
}
2014-05-30 12:53:19 +04:00
}
2015-09-29 18:29:21 +03:00
bool mtpFileLoader : : tryLoadLocal ( ) {
if ( _localStatus = = LocalNotFound | | _localStatus = = LocalLoaded | | _localStatus = = LocalFailed ) {
return false ;
}
if ( _localStatus = = LocalLoading ) {
return true ;
}
2015-12-24 22:26:28 +03:00
if ( _location ) {
_localTaskId = Local : : startImageLoad ( storageKey ( * _location ) , this ) ;
2015-09-29 18:29:21 +03:00
} else {
2015-12-24 22:26:28 +03:00
if ( _toCache = = LoadToCacheAsWell ) {
MediaKey mkey = mediaKey ( _locationType , _dc , _id ) ;
2015-09-29 18:29:21 +03:00
if ( _locationType = = DocumentFileLocation ) {
2015-10-01 17:05:05 +03:00
_localTaskId = Local : : startStickerImageLoad ( mkey , this ) ;
2015-09-29 18:29:21 +03:00
} else if ( _locationType = = AudioFileLocation ) {
2015-10-01 17:05:05 +03:00
_localTaskId = Local : : startAudioLoad ( mkey , this ) ;
2015-01-02 17:55:24 +03:00
}
2014-11-22 12:45:04 +03:00
}
}
2014-05-30 12:53:19 +04:00
2015-12-24 22:26:28 +03:00
if ( _localStatus ! = LocalNotTried ) {
return _complete ;
} else if ( _localTaskId ) {
_localStatus = LocalLoading ;
return true ;
2015-09-29 18:29:21 +03:00
}
2015-12-24 22:26:28 +03:00
_localStatus = LocalNotFound ;
return false ;
2015-09-29 18:29:21 +03:00
}
2015-12-31 03:09:20 +08:00
mtpFileLoader : : ~ mtpFileLoader ( ) {
cancelRequests ( ) ;
}
webFileLoader : : webFileLoader ( const QString & url , const QString & to , LoadFromCloudSetting fromCloud , bool autoLoading )
2015-12-31 13:34:43 +08:00
: FileLoader ( QString ( ) , 0 , UnknownFileLocation , LoadToCacheAsWell , fromCloud , autoLoading )
2015-12-31 03:09:20 +08:00
, _url ( url )
, _requestSent ( false )
, _already ( 0 ) {
_queue = & _webQueue ;
}
bool webFileLoader : : loadPart ( ) {
if ( _complete | | _requestSent | | _webLoadManager = = FinishedWebLoadManager ) return false ;
if ( ! _webLoadManager ) {
_webLoadMainManager = new WebLoadMainManager ( ) ;
_webLoadThread = new QThread ( ) ;
_webLoadManager = new WebLoadManager ( _webLoadThread ) ;
_webLoadThread - > start ( ) ;
2015-09-29 21:44:31 +03:00
}
2015-12-31 03:09:20 +08:00
_requestSent = true ;
_webLoadManager - > append ( this , _url ) ;
return false ;
}
int32 webFileLoader : : currentOffset ( bool includeSkipped ) const {
return _already ;
}
void webFileLoader : : onProgress ( qint64 already , qint64 size ) {
_size = size ;
_already = already ;
emit progress ( this ) ;
}
void webFileLoader : : onFinished ( const QByteArray & data ) {
if ( _fileIsOpen ) {
if ( _file . write ( data . constData ( ) , data . size ( ) ) ! = qint64 ( data . size ( ) ) ) {
return cancel ( true ) ;
}
} else {
_data = data ;
2015-09-29 21:44:31 +03:00
}
2015-12-31 03:09:20 +08:00
if ( ! _fname . isEmpty ( ) & & ( _toCache = = LoadToCacheAsWell ) ) {
2015-12-24 22:26:28 +03:00
if ( ! _fileIsOpen ) _fileIsOpen = _file . open ( QIODevice : : WriteOnly ) ;
if ( ! _fileIsOpen ) {
2015-12-31 03:09:20 +08:00
return cancel ( true ) ;
2015-09-29 21:44:31 +03:00
}
2015-12-24 22:26:28 +03:00
if ( _file . write ( _data ) ! = qint64 ( _data . size ( ) ) ) {
2015-12-31 03:09:20 +08:00
return cancel ( true ) ;
2015-09-29 21:44:31 +03:00
}
}
2015-12-31 03:09:20 +08:00
_type = mtpc_storage_filePartial ;
2015-12-24 22:26:28 +03:00
_complete = true ;
if ( _fileIsOpen ) {
_file . close ( ) ;
_fileIsOpen = false ;
psPostprocessFile ( QFileInfo ( _file ) . absoluteFilePath ( ) ) ;
2015-09-29 21:44:31 +03:00
}
2015-12-31 03:09:20 +08:00
removeFromQueue ( ) ;
2015-09-29 21:44:31 +03:00
emit App : : wnd ( ) - > imageLoaded ( ) ;
2015-12-31 03:09:20 +08:00
if ( _localStatus = = LocalNotFound | | _localStatus = = LocalFailed ) {
2015-12-31 23:27:21 +08:00
Local : : writeWebFile ( _url , _data ) ;
2015-12-31 03:09:20 +08:00
}
2015-09-29 21:44:31 +03:00
emit progress ( this ) ;
loadNext ( ) ;
}
2015-12-31 03:09:20 +08:00
void webFileLoader : : onError ( ) {
cancel ( true ) ;
}
bool webFileLoader : : tryLoadLocal ( ) {
if ( _localStatus = = LocalNotFound | | _localStatus = = LocalLoaded | | _localStatus = = LocalFailed ) {
return false ;
}
if ( _localStatus = = LocalLoading ) {
return true ;
2015-12-23 19:48:44 +03:00
}
2015-12-24 22:26:28 +03:00
2015-12-31 23:27:21 +08:00
_localTaskId = Local : : startWebFileLoad ( _url , this ) ;
2015-12-31 03:09:20 +08:00
if ( _localStatus ! = LocalNotTried ) {
return _complete ;
} else if ( _localTaskId ) {
_localStatus = LocalLoading ;
return true ;
2015-12-24 22:26:28 +03:00
}
2015-12-31 03:09:20 +08:00
_localStatus = LocalNotFound ;
return false ;
}
2015-09-29 18:29:21 +03:00
2015-12-31 03:09:20 +08:00
void webFileLoader : : cancelRequests ( ) {
if ( ! webLoadManager ( ) ) return ;
webLoadManager ( ) - > stop ( this ) ;
}
webFileLoader : : ~ webFileLoader ( ) {
}
class webFileLoaderPrivate {
public :
webFileLoaderPrivate ( webFileLoader * loader , const QString & url )
: _interface ( loader )
, _url ( url )
, _already ( 0 )
, _size ( 0 )
, _reply ( 0 )
, _redirectsLeft ( MaxHttpRedirects ) {
}
QNetworkReply * reply ( ) {
return _reply ;
}
QNetworkReply * request ( QNetworkAccessManager & manager , const QString & redirect ) {
if ( ! redirect . isEmpty ( ) ) _url = redirect ;
QNetworkRequest req ( _url ) ;
QByteArray rangeHeaderValue = " bytes= " + QByteArray : : number ( _already ) + " - " ;
req . setRawHeader ( " Range " , rangeHeaderValue ) ;
_reply = manager . get ( req ) ;
return _reply ;
}
bool oneMoreRedirect ( ) {
if ( _redirectsLeft ) {
- - _redirectsLeft ;
return true ;
2014-05-30 12:53:19 +04:00
}
2015-12-31 03:09:20 +08:00
return false ;
2014-05-30 12:53:19 +04:00
}
2015-12-31 03:09:20 +08:00
void setData ( const QByteArray & data ) {
_data = data ;
}
void addData ( const QByteArray & data ) {
_data . append ( data ) ;
}
const QByteArray & data ( ) {
return _data ;
}
void setProgress ( qint64 already , qint64 size ) {
_already = already ;
_size = qMax ( size , 0LL ) ;
}
qint64 size ( ) const {
return _size ;
}
qint64 already ( ) const {
return _already ;
}
private :
webFileLoader * _interface ;
QUrl _url ;
qint64 _already , _size ;
QNetworkReply * _reply ;
int32 _redirectsLeft ;
QByteArray _data ;
friend class WebLoadManager ;
} ;
void reinitWebLoadManager ( ) {
2016-03-20 11:16:35 +03:00
# ifndef TDESKTOP_DISABLE_NETWORK_PROXY
2015-12-31 03:09:20 +08:00
if ( webLoadManager ( ) ) {
webLoadManager ( ) - > setProxySettings ( App : : getHttpProxySettings ( ) ) ;
}
2016-03-20 11:16:35 +03:00
# endif
2015-12-31 03:09:20 +08:00
}
void stopWebLoadManager ( ) {
if ( webLoadManager ( ) ) {
_webLoadThread - > quit ( ) ;
2016-03-01 05:36:23 +03:00
DEBUG_LOG ( ( " Waiting for webloadThread to finish " ) ) ;
2015-12-31 03:09:20 +08:00
_webLoadThread - > wait ( ) ;
delete _webLoadManager ;
delete _webLoadMainManager ;
delete _webLoadThread ;
_webLoadThread = 0 ;
_webLoadMainManager = 0 ;
_webLoadManager = FinishedWebLoadManager ;
}
}
2016-03-20 11:16:35 +03:00
# ifndef TDESKTOP_DISABLE_NETWORK_PROXY
2015-12-31 03:09:20 +08:00
void WebLoadManager : : setProxySettings ( const QNetworkProxy & proxy ) {
QMutexLocker lock ( & _loaderPointersMutex ) ;
_proxySettings = proxy ;
emit proxyApplyDelayed ( ) ;
}
2016-03-20 11:16:35 +03:00
# endif
2015-12-31 03:09:20 +08:00
WebLoadManager : : WebLoadManager ( QThread * thread ) {
moveToThread ( thread ) ;
_manager . moveToThread ( thread ) ;
connect ( thread , SIGNAL ( started ( ) ) , this , SLOT ( process ( ) ) ) ;
connect ( thread , SIGNAL ( finished ( ) ) , this , SLOT ( finish ( ) ) ) ;
connect ( this , SIGNAL ( processDelayed ( ) ) , this , SLOT ( process ( ) ) , Qt : : QueuedConnection ) ;
connect ( this , SIGNAL ( proxyApplyDelayed ( ) ) , this , SLOT ( proxyApply ( ) ) , Qt : : QueuedConnection ) ;
connect ( this , SIGNAL ( progress ( webFileLoader * , qint64 , qint64 ) ) , _webLoadMainManager , SLOT ( progress ( webFileLoader * , qint64 , qint64 ) ) ) ;
connect ( this , SIGNAL ( finished ( webFileLoader * , QByteArray ) ) , _webLoadMainManager , SLOT ( finished ( webFileLoader * , QByteArray ) ) ) ;
connect ( this , SIGNAL ( error ( webFileLoader * ) ) , _webLoadMainManager , SLOT ( error ( webFileLoader * ) ) ) ;
connect ( & _manager , SIGNAL ( authenticationRequired ( QNetworkReply * , QAuthenticator * ) ) , this , SLOT ( onFailed ( QNetworkReply * ) ) ) ;
connect ( & _manager , SIGNAL ( sslErrors ( QNetworkReply * , const QList < QSslError > & ) ) , this , SLOT ( onFailed ( QNetworkReply * ) ) ) ;
}
void WebLoadManager : : append ( webFileLoader * loader , const QString & url ) {
loader - > _private = new webFileLoaderPrivate ( loader , url ) ;
QMutexLocker lock ( & _loaderPointersMutex ) ;
_loaderPointers . insert ( loader , loader - > _private ) ;
emit processDelayed ( ) ;
}
void WebLoadManager : : stop ( webFileLoader * loader ) {
QMutexLocker lock ( & _loaderPointersMutex ) ;
_loaderPointers . remove ( loader ) ;
emit processDelayed ( ) ;
}
bool WebLoadManager : : carries ( webFileLoader * loader ) const {
QMutexLocker lock ( & _loaderPointersMutex ) ;
return _loaderPointers . contains ( loader ) ;
}
bool WebLoadManager : : handleReplyResult ( webFileLoaderPrivate * loader , WebReplyProcessResult result ) {
QMutexLocker lock ( & _loaderPointersMutex ) ;
LoaderPointers : : iterator it = _loaderPointers . find ( loader - > _interface ) ;
if ( it ! = _loaderPointers . cend ( ) & & it . key ( ) - > _private ! = loader ) {
it = _loaderPointers . end ( ) ; // it is a new loader which was realloced in the same address
}
if ( it = = _loaderPointers . cend ( ) ) {
return false ;
}
if ( result = = WebReplyProcessProgress ) {
if ( loader - > size ( ) > AnimationInMemory ) {
LOG ( ( " API Error: too large file is loaded to cache: %1 " ) . arg ( loader - > size ( ) ) ) ;
result = WebReplyProcessError ;
}
}
if ( result = = WebReplyProcessError ) {
if ( it ! = _loaderPointers . cend ( ) ) {
emit error ( it . key ( ) ) ;
}
return false ;
}
if ( loader - > already ( ) < loader - > size ( ) | | ! loader - > size ( ) ) {
emit progress ( it . key ( ) , loader - > already ( ) , loader - > size ( ) ) ;
return true ;
}
emit finished ( it . key ( ) , loader - > data ( ) ) ;
return false ;
}
void WebLoadManager : : onFailed ( QNetworkReply : : NetworkError error ) {
onFailed ( qobject_cast < QNetworkReply * > ( QObject : : sender ( ) ) ) ;
}
void WebLoadManager : : onFailed ( QNetworkReply * reply ) {
if ( ! reply ) return ;
reply - > deleteLater ( ) ;
Replies : : iterator j = _replies . find ( reply ) ;
if ( j = = _replies . cend ( ) ) { // handled already
return ;
}
webFileLoaderPrivate * loader = j . value ( ) ;
_replies . erase ( j ) ;
2015-12-31 13:34:43 +08:00
LOG ( ( " Network Error: Failed to request '%1', error %2 (%3) " ) . arg ( QString : : fromLatin1 ( loader - > _url . toEncoded ( ) ) ) . arg ( int ( reply - > error ( ) ) ) . arg ( reply - > errorString ( ) ) ) ;
2015-12-31 03:09:20 +08:00
if ( ! handleReplyResult ( loader , WebReplyProcessError ) ) {
_loaders . remove ( loader ) ;
delete loader ;
}
}
void WebLoadManager : : onProgress ( qint64 already , qint64 size ) {
QNetworkReply * reply = qobject_cast < QNetworkReply * > ( QObject : : sender ( ) ) ;
if ( ! reply ) return ;
Replies : : iterator j = _replies . find ( reply ) ;
if ( j = = _replies . cend ( ) ) { // handled already
return ;
}
webFileLoaderPrivate * loader = j . value ( ) ;
WebReplyProcessResult result = WebReplyProcessProgress ;
QVariant statusCode = reply - > attribute ( QNetworkRequest : : HttpStatusCodeAttribute ) ;
int32 status = statusCode . isValid ( ) ? statusCode . toInt ( ) : 200 ;
if ( status ! = 200 & & status ! = 206 & & status ! = 416 ) {
if ( status = = 301 | | status = = 302 ) {
QString loc = reply - > header ( QNetworkRequest : : LocationHeader ) . toString ( ) ;
if ( ! loc . isEmpty ( ) ) {
if ( loader - > oneMoreRedirect ( ) ) {
sendRequest ( loader , loc ) ;
return ;
2014-05-30 12:53:19 +04:00
} else {
2015-12-31 03:09:20 +08:00
LOG ( ( " Network Error: Too many HTTP redirects in onFinished() for web file loader: %1 " ) . arg ( loc ) ) ;
result = WebReplyProcessError ;
2014-05-30 12:53:19 +04:00
}
}
2015-12-31 03:09:20 +08:00
} else {
LOG ( ( " Network Error: Bad HTTP status received in WebLoadManager::onProgress(): %1 " ) . arg ( statusCode . toInt ( ) ) ) ;
result = WebReplyProcessError ;
2014-05-30 12:53:19 +04:00
}
} else {
2015-12-31 03:09:20 +08:00
loader - > setProgress ( already , size ) ;
QByteArray r = reply - > readAll ( ) ;
if ( ! r . isEmpty ( ) ) {
loader - > addData ( r ) ;
}
if ( size = = 0 ) {
LOG ( ( " Network Error: Zero size received for HTTP download progress in WebLoadManager::onProgress(): %1 / %2 " ) . arg ( already ) . arg ( size ) ) ;
result = WebReplyProcessError ;
2014-05-30 12:53:19 +04:00
}
}
2015-12-31 03:09:20 +08:00
if ( ! handleReplyResult ( loader , result ) ) {
_replies . erase ( j ) ;
_loaders . remove ( loader ) ;
delete loader ;
2014-05-30 12:53:19 +04:00
2015-12-31 03:09:20 +08:00
reply - > abort ( ) ;
reply - > deleteLater ( ) ;
}
}
2014-05-30 12:53:19 +04:00
2015-12-31 03:09:20 +08:00
void WebLoadManager : : onMeta ( ) {
QNetworkReply * reply = qobject_cast < QNetworkReply * > ( QObject : : sender ( ) ) ;
if ( ! reply ) return ;
Replies : : iterator j = _replies . find ( reply ) ;
if ( j = = _replies . cend ( ) ) { // handled already
return ;
}
webFileLoaderPrivate * loader = j . value ( ) ;
typedef QList < QNetworkReply : : RawHeaderPair > Pairs ;
Pairs pairs = reply - > rawHeaderPairs ( ) ;
for ( Pairs : : iterator i = pairs . begin ( ) , e = pairs . end ( ) ; i ! = e ; + + i ) {
if ( QString : : fromUtf8 ( i - > first ) . toLower ( ) = = " content-range " ) {
QRegularExpressionMatch m = QRegularExpression ( qsl ( " /( \\ d+)([^ \\ d]|$) " ) ) . match ( QString : : fromUtf8 ( i - > second ) ) ;
if ( m . hasMatch ( ) ) {
loader - > setProgress ( qMax ( qint64 ( loader - > data ( ) . size ( ) ) , loader - > already ( ) ) , m . captured ( 1 ) . toLongLong ( ) ) ;
if ( ! handleReplyResult ( loader , WebReplyProcessProgress ) ) {
_replies . erase ( j ) ;
_loaders . remove ( loader ) ;
delete loader ;
reply - > abort ( ) ;
reply - > deleteLater ( ) ;
}
2014-05-30 12:53:19 +04:00
}
}
2015-12-31 03:09:20 +08:00
}
}
void WebLoadManager : : process ( ) {
Loaders newLoaders ;
{
QMutexLocker lock ( & _loaderPointersMutex ) ;
for ( LoaderPointers : : iterator i = _loaderPointers . begin ( ) , e = _loaderPointers . end ( ) ; i ! = e ; + + i ) {
Loaders : : iterator it = _loaders . find ( i . value ( ) ) ;
if ( i . value ( ) ) {
if ( it = = _loaders . cend ( ) ) {
_loaders . insert ( i . value ( ) ) ;
newLoaders . insert ( i . value ( ) ) ;
}
i . value ( ) = 0 ;
}
}
2016-03-25 18:20:34 +03:00
for ( auto i = _loaders . begin ( ) , e = _loaders . end ( ) ; i ! = e ; ) {
LoaderPointers : : iterator it = _loaderPointers . find ( ( * i ) - > _interface ) ;
if ( it ! = _loaderPointers . cend ( ) & & it . key ( ) - > _private ! = ( * i ) ) {
2015-12-31 03:09:20 +08:00
it = _loaderPointers . end ( ) ;
}
if ( it = = _loaderPointers . cend ( ) ) {
2016-03-25 18:20:34 +03:00
if ( QNetworkReply * reply = ( * i ) - > reply ( ) ) {
2015-12-31 03:09:20 +08:00
_replies . remove ( reply ) ;
reply - > abort ( ) ;
reply - > deleteLater ( ) ;
}
2016-03-25 18:20:34 +03:00
delete ( * i ) ;
2015-12-31 03:09:20 +08:00
i = _loaders . erase ( i ) ;
} else {
+ + i ;
2014-05-30 12:53:19 +04:00
}
}
}
2016-03-25 18:20:34 +03:00
for_const ( webFileLoaderPrivate * loader , newLoaders ) {
if ( _loaders . contains ( loader ) ) {
sendRequest ( loader ) ;
2015-12-31 03:09:20 +08:00
}
}
2014-05-30 12:53:19 +04:00
}
2015-12-31 03:09:20 +08:00
void WebLoadManager : : sendRequest ( webFileLoaderPrivate * loader , const QString & redirect ) {
Replies : : iterator j = _replies . find ( loader - > reply ( ) ) ;
if ( j ! = _replies . cend ( ) ) {
QNetworkReply * r = j . key ( ) ;
_replies . erase ( j ) ;
2015-12-24 22:26:28 +03:00
2015-12-31 03:09:20 +08:00
r - > abort ( ) ;
r - > deleteLater ( ) ;
2015-12-24 22:26:28 +03:00
}
2015-12-31 03:09:20 +08:00
QNetworkReply * r = loader - > request ( _manager , redirect ) ;
connect ( r , SIGNAL ( downloadProgress ( qint64 , qint64 ) ) , this , SLOT ( onProgress ( qint64 , qint64 ) ) ) ;
connect ( r , SIGNAL ( error ( QNetworkReply : : NetworkError ) ) , this , SLOT ( onFailed ( QNetworkReply : : NetworkError ) ) ) ;
connect ( r , SIGNAL ( metaDataChanged ( ) ) , this , SLOT ( onMeta ( ) ) ) ;
_replies . insert ( r , loader ) ;
2014-05-30 12:53:19 +04:00
}
2015-12-31 03:09:20 +08:00
void WebLoadManager : : proxyApply ( ) {
2016-03-20 11:16:35 +03:00
# ifndef TDESKTOP_DISABLE_NETWORK_PROXY
2015-12-31 03:09:20 +08:00
QMutexLocker lock ( & _loaderPointersMutex ) ;
_manager . setProxy ( _proxySettings ) ;
2016-03-20 11:16:35 +03:00
# endif
2015-12-31 03:09:20 +08:00
}
2014-10-30 19:23:44 +03:00
2015-12-31 03:09:20 +08:00
void WebLoadManager : : finish ( ) {
clear ( ) ;
}
void WebLoadManager : : clear ( ) {
QMutexLocker lock ( & _loaderPointersMutex ) ;
for ( LoaderPointers : : iterator i = _loaderPointers . begin ( ) , e = _loaderPointers . end ( ) ; i ! = e ; + + i ) {
if ( i . value ( ) ) {
i . key ( ) - > _private = 0 ;
}
2014-10-30 19:23:44 +03:00
}
2015-12-31 03:09:20 +08:00
_loaderPointers . clear ( ) ;
2014-10-30 19:23:44 +03:00
2016-03-25 18:20:34 +03:00
for_const ( webFileLoaderPrivate * loader , _loaders ) {
delete loader ;
2014-10-30 19:23:44 +03:00
}
2015-12-31 03:09:20 +08:00
_loaders . clear ( ) ;
for ( Replies : : iterator i = _replies . begin ( ) , e = _replies . end ( ) ; i ! = e ; + + i ) {
delete i . key ( ) ;
}
_replies . clear ( ) ;
2014-10-30 19:23:44 +03:00
}
2015-12-31 03:09:20 +08:00
WebLoadManager : : ~ WebLoadManager ( ) {
clear ( ) ;
2014-05-30 12:53:19 +04:00
}
2015-12-31 03:09:20 +08:00
void WebLoadMainManager : : progress ( webFileLoader * loader , qint64 already , qint64 size ) {
if ( webLoadManager ( ) & & webLoadManager ( ) - > carries ( loader ) ) {
loader - > onProgress ( already , size ) ;
}
}
void WebLoadMainManager : : finished ( webFileLoader * loader , QByteArray data ) {
if ( webLoadManager ( ) & & webLoadManager ( ) - > carries ( loader ) ) {
loader - > onFinished ( data ) ;
}
}
void WebLoadMainManager : : error ( webFileLoader * loader ) {
if ( webLoadManager ( ) & & webLoadManager ( ) - > carries ( loader ) ) {
loader - > onError ( ) ;
2015-09-29 21:44:31 +03:00
}
2014-05-30 12:53:19 +04:00
}
namespace MTP {
void clearLoaderPriorities ( ) {
2015-12-24 22:26:28 +03:00
+ + GlobalPriority ;
2014-05-30 12:53:19 +04:00
}
}