File indexing completed on 2024-04-28 05:42:11

0001 /***************************************************************************
0002  *   Copyright (C) 2006-2009 by Rajko Albrecht                             *
0003  *   ral@alwins-world.de                                                   *
0004  *                                                                         *
0005  * This program is free software; you can redistribute it and/or           *
0006  * modify it under the terms of the GNU Lesser General Public              *
0007  * License as published by the Free Software Foundation; either            *
0008  * version 2.1 of the License, or (at your option) any later version.      *
0009  *                                                                         *
0010  * This program is distributed in the hope that it will be useful,         *
0011  * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
0012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU       *
0013  * Lesser General Public License for more details.                         *
0014  *                                                                         *
0015  * You should have received a copy of the GNU Lesser General Public        *
0016  * License along with this program (in the file LGPL.txt); if not,         *
0017  * write to the Free Software Foundation, Inc., 51 Franklin St,            *
0018  * Fifth Floor, Boston, MA  02110-1301  USA                                *
0019  *                                                                         *
0020  * This software consists of voluntary contributions made by many          *
0021  * individuals.  For exact contribution history, see the revision          *
0022  * history and logs, available at https://commits.kde.org/kdesvn.          *
0023  ***************************************************************************/
0024 #include "svnstream.h"
0025 
0026 #include "apr.h"
0027 #include "pool.h"
0028 
0029 // Subversion api
0030 #include <svn_client.h>
0031 
0032 #include <QBuffer>
0033 #include <QElapsedTimer>
0034 
0035 namespace svn
0036 {
0037 
0038 namespace stream
0039 {
0040 class SVNQT_NOEXPORT SvnStream_private
0041 {
0042 public:
0043     SvnStream_private()
0044     {
0045         m_Stream = nullptr;
0046         _context = nullptr; /*cancel_timeout.start();*/
0047     }
0048     ~SvnStream_private()
0049     {
0050         /*qDebug("Time elapsed: %i ",cancel_timeout.elapsed());*/
0051     }
0052 
0053     static svn_error_t *stream_write(void *baton, const char *data, apr_size_t *len);
0054     static svn_error_t *stream_read(void *baton, char *data, apr_size_t *len);
0055 
0056     Pool m_Pool;
0057     svn_stream_t *m_Stream;
0058     QString m_LastError;
0059 
0060     svn_client_ctx_t *_context;
0061     QElapsedTimer cancel_timeout;
0062 };
0063 
0064 svn_error_t *SvnStream_private::stream_read(void *baton, char *data, apr_size_t *len)
0065 {
0066     SvnStream *b = (SvnStream *)baton;
0067     svn_client_ctx_t *ctx = b->context();
0068 
0069     if (ctx && ctx->cancel_func) {
0070         SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
0071     }
0072 
0073     long res = b->isOk() ? b->read(data, *len) : -1;
0074 
0075     if (res < 0) {
0076         *len = 0;
0077         return svn_error_create(SVN_ERR_MALFORMED_FILE, nullptr, b->lastError().toUtf8());
0078     }
0079     *len = res;
0080     return SVN_NO_ERROR;
0081 }
0082 
0083 svn_error_t *SvnStream_private::stream_write(void *baton, const char *data, apr_size_t *len)
0084 {
0085     SvnStream *b = (SvnStream *)baton;
0086     svn_client_ctx_t *ctx = b->context();
0087 
0088     if (ctx && ctx->cancel_func && b->cancelElapsed() > 50) {
0089         // qDebug("Check cancel");
0090         SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
0091         b->cancelTimeReset();
0092     }
0093 
0094     long res = b->isOk() ? b->write(data, *len) : -1;
0095     if (res < 0) {
0096         *len = 0;
0097         return svn_error_create(SVN_ERR_MALFORMED_FILE, nullptr, b->lastError().toUtf8());
0098     }
0099     *len = res;
0100     return SVN_NO_ERROR;
0101 }
0102 
0103 SvnStream::SvnStream(bool read, bool write, svn_client_ctx_t *ctx)
0104 {
0105     m_Data = new SvnStream_private;
0106     m_Data->m_Stream = svn_stream_create(this, m_Data->m_Pool);
0107     m_Data->_context = ctx;
0108     if (read) {
0109         svn_stream_set_read(m_Data->m_Stream, SvnStream_private::stream_read);
0110     }
0111     if (write) {
0112         svn_stream_set_write(m_Data->m_Stream, SvnStream_private::stream_write);
0113     }
0114 }
0115 
0116 SvnStream::~SvnStream()
0117 {
0118     delete m_Data;
0119 }
0120 
0121 int SvnStream::cancelElapsed() const
0122 {
0123     return m_Data->cancel_timeout.elapsed();
0124 }
0125 
0126 void SvnStream::cancelTimeReset()
0127 {
0128     m_Data->cancel_timeout.restart();
0129 }
0130 
0131 SvnStream::operator svn_stream_t *() const
0132 {
0133     return m_Data->m_Stream;
0134 }
0135 
0136 svn_client_ctx_t *SvnStream::context()
0137 {
0138     return m_Data->_context;
0139 }
0140 
0141 long SvnStream::write(const char *, const unsigned long)
0142 {
0143     m_Data->m_LastError = QLatin1String("Write not supported with that stream");
0144     return -1;
0145 }
0146 
0147 long SvnStream::read(char *, const unsigned long)
0148 {
0149     m_Data->m_LastError = QLatin1String("Read not supported with that stream");
0150     return -1;
0151 }
0152 
0153 const QString &SvnStream::lastError() const
0154 {
0155     return m_Data->m_LastError;
0156 }
0157 
0158 void SvnStream::setError(const QString &aError) const
0159 {
0160     m_Data->m_LastError = aError;
0161 }
0162 
0163 /* ByteStream implementation start */
0164 SvnByteStream::SvnByteStream(svn_client_ctx_t *ctx)
0165     : SvnStream(false, true, ctx)
0166     , m_ByteData(new QBuffer)
0167 {
0168     m_ByteData->open(QIODevice::ReadWrite);
0169     if (!m_ByteData->isOpen()) {
0170         setError(m_ByteData->errorString());
0171     }
0172 }
0173 
0174 SvnByteStream::~SvnByteStream()
0175 {
0176     delete m_ByteData;
0177 }
0178 
0179 long SvnByteStream::write(const char *aData, const unsigned long max)
0180 {
0181     qint64 i = m_ByteData->write(aData, max);
0182     if (i < 0) {
0183         setError(m_ByteData->errorString());
0184     }
0185     return i;
0186 }
0187 
0188 QByteArray SvnByteStream::content() const
0189 {
0190     return m_ByteData->buffer();
0191 }
0192 
0193 bool SvnByteStream::isOk() const
0194 {
0195     return m_ByteData->isOpen();
0196 }
0197 
0198 /* ByteStream implementation end */
0199 
0200 } // namespace stream
0201 
0202 } // namespace svn