Bugzilla – Attachment 148695 Details for
Bug 112689
Replace chained O(U)StringBuffer::append() with operator+
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
I Replace chained O(U)StringBuffer::append() with operator+
patch1 (text/plain), 21.71 KB, created by
Yusuf Sönmez
on 2019-01-27 21:34:25 UTC
(
hide
)
Description:
I Replace chained O(U)StringBuffer::append() with operator+
Filename:
MIME Type:
Creator:
Yusuf Sönmez
Created:
2019-01-27 21:34:25 UTC
Size:
21.71 KB
patch
obsolete
>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >/* > * This file is part of the LibreOffice project. > * > * This Source Code Form is subject to the terms of the Mozilla Public > * License, v. 2.0. If a copy of the MPL was not distributed with this > * file, You can obtain one at http://mozilla.org/MPL/2.0/. > * > * This file incorporates work covered by the following license notice: > * > * Licensed to the Apache Software Foundation (ASF) under one or more > * contributor license agreements. See the NOTICE file distributed > * with this work for additional information regarding copyright > * ownership. The ASF licenses this file to you under the Apache > * License, Version 2.0 (the "License"); you may not use this file > * except in compliance with the License. You may obtain a copy of > * the License at http://www.apache.org/licenses/LICENSE-2.0 . > */ > >/************************************************************************** > TODO > ************************************************************************** > > *************************************************************************/ > >#include <sal/config.h> >#include <sal/log.hxx> > >#include <cstring> >#include <vector> > >#include <rtl/ustrbuf.hxx> >#include <com/sun/star/ucb/OpenMode.hpp> >#include <string.h> >#include <rtl/uri.hxx> >#include <rtl/strbuf.hxx> > >#include "ftpurl.hxx" >#include "ftpcontentprovider.hxx" >#include "ftpcfunc.hxx" >#include "ftpcontainer.hxx" >#include <memory> > >using namespace ftp; >using namespace com::sun::star::ucb; >using namespace com::sun::star::uno; >using namespace com::sun::star::io; > >namespace { > >OUString encodePathSegment(OUString const & decoded) { > return rtl::Uri::encode( > decoded, rtl_UriCharClassPchar, rtl_UriEncodeIgnoreEscapes, > RTL_TEXTENCODING_UTF8); >} > >OUString decodePathSegment(OUString const & encoded) { > return rtl::Uri::decode( > encoded, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8); >} > >} > >MemoryContainer::MemoryContainer() > : m_nLen(0), > m_nWritePos(0), > m_pBuffer(nullptr) >{ >} > >MemoryContainer::~MemoryContainer() >{ > std::free(m_pBuffer); >} > > >int MemoryContainer::append( > const void* pBuffer, > size_t size, > size_t nmemb >) throw() >{ > sal_uInt32 nLen = size*nmemb; > sal_uInt32 tmp(nLen + m_nWritePos); > > if(m_nLen < tmp) { // enlarge in steps of multiples of 1K > do { > m_nLen+=1024; > } while(m_nLen < tmp); > > if (auto p = std::realloc(m_pBuffer, m_nLen)) > m_pBuffer = p; > else > return 0; > } > > memcpy(static_cast<sal_Int8*>(m_pBuffer)+m_nWritePos, > pBuffer,nLen); > m_nWritePos = tmp; > return nLen; >} > > >extern "C" { > > int memory_write(void *buffer,size_t size,size_t nmemb,void *stream) > { > MemoryContainer *_stream = > static_cast<MemoryContainer*>(stream); > > if(!_stream) > return 0; > > return _stream->append(buffer,size,nmemb); > } > >} > > >FTPURL::FTPURL(const FTPURL& r) > : m_pFCP(r.m_pFCP), > m_aUsername(r.m_aUsername), > m_bShowPassword(r.m_bShowPassword), > m_aHost(r.m_aHost), > m_aPort(r.m_aPort), > m_aPathSegmentVec(r.m_aPathSegmentVec) > >{ >} > > >FTPURL::FTPURL(const OUString& url, > FTPContentProvider* pFCP) > : m_pFCP(pFCP), > m_aUsername("anonymous"), > m_bShowPassword(false), > m_aPort("21") >{ > parse(url); // can reset m_bShowPassword >} > > >FTPURL::~FTPURL() >{ >} > > >void FTPURL::parse(const OUString& url) >{ > OUString aPassword, urlRest; > > if(url.getLength() < 6 || !url.startsWithIgnoreAsciiCase("ftp://", &urlRest)) > throw malformed_exception(); > > // determine "username:password@host:port" > OUString aExpr; > sal_Int32 nIdx = urlRest.indexOf('/'); > if (nIdx == -1) > { > aExpr = urlRest; > urlRest = ""; > } > else > { > aExpr = urlRest.copy(0, nIdx); > urlRest = urlRest.copy(nIdx + 1); > } > > sal_Int32 l = aExpr.indexOf('@'); > m_aHost = aExpr.copy(1+l); > > if(l != -1) { > // Now username and password. > aExpr = aExpr.copy(0,l); > l = aExpr.indexOf(':'); > if(l != -1) { > aPassword = aExpr.copy(1+l); > if(!aPassword.isEmpty()) > m_bShowPassword = true; > } > if(l > 0) > // Overwritten only if the username is not empty. > m_aUsername = aExpr.copy(0,l); > else if(!aExpr.isEmpty()) > m_aUsername = aExpr; > } > > l = m_aHost.lastIndexOf(':'); > sal_Int32 ipv6Back = m_aHost.lastIndexOf(']'); > if((ipv6Back == -1 && l != -1) // not ipv6, but a port > || > (ipv6Back != -1 && 1+ipv6Back == l) // ipv6, and a port > ) > { > if(1+l<m_aHost.getLength()) > m_aPort = m_aHost.copy(1+l); > m_aHost = m_aHost.copy(0,l); > } > > // now determine the pathsegments ... > while(!urlRest.isEmpty()) > { > nIdx = urlRest.indexOf('/'); > OUString segment; > if(nIdx == -1) > { > segment = urlRest; > urlRest = ""; > } > else > { > segment = urlRest.copy(0, nIdx); > urlRest = urlRest.copy(nIdx + 1); > } > if( segment == ".." && !m_aPathSegmentVec.empty() && m_aPathSegmentVec.back() != ".." ) > m_aPathSegmentVec.pop_back(); > else if( segment == "." ) > ; // Ignore > else > // This is a legal name. > m_aPathSegmentVec.push_back( segment ); > } > > if(m_bShowPassword) > m_pFCP->setHost(m_aHost, > m_aPort, > m_aUsername, > aPassword, > ""/*aAccount*/); > > // now check for something like ";type=i" at end of url > if(!m_aPathSegmentVec.empty() && > (l = m_aPathSegmentVec.back().indexOf(';')) != -1) { > m_aType = m_aPathSegmentVec.back().copy(l); > m_aPathSegmentVec.back() = m_aPathSegmentVec.back().copy(0,l); > } >} > > >OUString FTPURL::ident(bool withslash,bool internal) const > >{ >// rebuild the url as one without ellipses, > // and more important, as one without username and > // password. ( These are set together with the command. ) > >OUString bff = "ftp://"; > if( m_aUsername != "anonymous" ) { > bff = m_aUserName ; > > OUString aPassword,aAccount; > m_pFCP->forHost(m_aHost, > m_aPort, > m_aUsername, > aPassword, > aAccount); > > if((internal || m_bShowPassword) && !aPassword.isEmpty()) > bff = ":" + aPassword ; > bff = "@"; > } > > bff = m_aHost; > > if( m_aPort != "21" ) > bff = ":" + m_aPort + "/" ; > else > bff = "/"; > > for(size_t i = 0; i < m_aPathSegmentVec.size(); ++i) > if(i == 0) > bff = m_aPathSegmentVec[i]; > else > bff = "/" + m_aPathSegmentVec[i]; > if(withslash) > if(!bff.isEmpty() && bff[bff.getLength()-1] != '/') > bff = "/"; > bff = m_aType; > return bff; > > >OUString FTPURL::parent(bool internal) const >{ > OUString bff = "ftp://"; > if( m_aUsername != "anonymous" ) { > bff = m_aUsername; > > OUString aPassword,aAccount; > m_pFCP->forHost(m_aHost, > m_aPort, > m_aUsername, > aPassword, > aAccount); > if((internal || m_bShowPassword) && !aPassword.isEmpty()) > bff = ":" + aPassword ; > bff = "@"; > } > bff = m_aHost; > if( m_aPort != "21" ) > bff = ":" + m_aPort + "/"; > else bff = "/"; > > > OUString last; > > > for(size_t i = 0; i < m_aPathSegmentVec.size(); ++i) > if(1+i == m_aPathSegmentVec.size()) > last = m_aPathSegmentVec[i]; > else if(i == 0) > OUString bff = m_aPathSegmentVec[i]; > else > OUString bff="/" + m_aPathSegmentVec[i]; > > if(last.isEmpty()) > OUString bff = ".." ; > else if ( last == ".." ) > OUString bff = last + "/.."; > > OUString bff = m_aType; > return bff; >} > >void FTPURL::child(const OUString& title) >{ > m_aPathSegmentVec.push_back(encodePathSegment(title)); >} > > >OUString FTPURL::child() const >{ > return > !m_aPathSegmentVec.empty() ? > decodePathSegment(m_aPathSegmentVec.back()) : OUString(); >} > > >/** Listing of a directory. > */ > >namespace ftp { > > enum OS { > FTP_DOS,FTP_UNIX,FTP_VMS,FTP_UNKNOWN > }; > >} > > >#define SET_CONTROL_CONTAINER \ > MemoryContainer control; \ > curl_easy_setopt(curl, \ > CURLOPT_HEADERFUNCTION, \ > memory_write); \ > curl_easy_setopt(curl, \ > CURLOPT_WRITEHEADER, \ > &control) > > >static void setCurlUrl(CURL* curl, OUString const & url) >{ > OString urlParAscii(url.getStr(), > url.getLength(), > RTL_TEXTENCODING_UTF8); > curl_easy_setopt(curl, > CURLOPT_URL, > urlParAscii.getStr()); >}; > >oslFileHandle FTPURL::open() >{ > if(m_aPathSegmentVec.empty()) > throw curl_exception(CURLE_FTP_COULDNT_RETR_FILE); > > CURL *curl = m_pFCP->handle(); > > SET_CONTROL_CONTAINER; > OUString url(ident(false,true)); > setCurlUrl(curl, url); > > oslFileHandle res( nullptr ); > if ( osl_createTempFile( nullptr, &res, nullptr ) == osl_File_E_None ) > { > curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,file_write); > curl_easy_setopt(curl,CURLOPT_WRITEDATA,res); > > curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0); > CURLcode err = curl_easy_perform(curl); > > if(err == CURLE_OK) > { > oslFileError rc = osl_setFilePos( res, osl_Pos_Absolut, 0 ); > SAL_WARN_IF(rc != osl_File_E_None, "ucb.ucp.ftp", > "osl_setFilePos failed"); > } > else { > osl_closeFile(res); > res = nullptr; > throw curl_exception(err); > } > } > > return res; >} > > >std::vector<FTPDirentry> FTPURL::list( > sal_Int16 nMode >) const >{ > CURL *curl = m_pFCP->handle(); > > SET_CONTROL_CONTAINER; > curl_easy_setopt(curl,CURLOPT_NOBODY,false); > MemoryContainer data; > curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,memory_write); > curl_easy_setopt(curl,CURLOPT_WRITEDATA,&data); > > OUString url(ident(true,true)); > setCurlUrl(curl, url); > curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0); > > CURLcode err = curl_easy_perform(curl); > if(err != CURLE_OK) > throw curl_exception(err); > > // now evaluate the error messages > > sal_uInt32 len = data.m_nWritePos; > char* fwd = static_cast<char*>(data.m_pBuffer); > char *p1, *p2; > p1 = p2 = fwd; > > OS osKind(FTP_UNKNOWN); > std::vector<FTPDirentry> resvec; > FTPDirentry aDirEntry; > // ensure slash at the end > OUString viewurl(ident(true,false)); > > while(true) { > while(p2-fwd < int(len) && *p2 != '\n') ++p2; > if(p2-fwd == int(len)) break; > > *p2 = 0; > switch(osKind) { > // While FTP knows the 'system'-command, > // which returns the operating system type, > // this is not usable here: There are Windows-server > // formatting the output like UNIX-ls command. > case FTP_DOS: > FTPDirectoryParser::parseDOS(aDirEntry,p1); > break; > case FTP_UNIX: > FTPDirectoryParser::parseUNIX(aDirEntry,p1); > break; > case FTP_VMS: > FTPDirectoryParser::parseVMS(aDirEntry,p1); > break; > default: > if(FTPDirectoryParser::parseUNIX(aDirEntry,p1)) > osKind = FTP_UNIX; > else if(FTPDirectoryParser::parseDOS(aDirEntry,p1)) > osKind = FTP_DOS; > else if(FTPDirectoryParser::parseVMS(aDirEntry,p1)) > osKind = FTP_VMS; > } > aDirEntry.m_aName = aDirEntry.m_aName.trim(); > if( osKind != int(FTP_UNKNOWN) && aDirEntry.m_aName != ".." && aDirEntry.m_aName != "." ) { > aDirEntry.m_aURL = viewurl + encodePathSegment(aDirEntry.m_aName); > > bool isDir = (aDirEntry.m_nMode & INETCOREFTP_FILEMODE_ISDIR) == INETCOREFTP_FILEMODE_ISDIR; > switch(nMode) { > case OpenMode::DOCUMENTS: > if(!isDir) > resvec.push_back(aDirEntry); > break; > case OpenMode::FOLDERS: > if(isDir) > resvec.push_back(aDirEntry); > break; > default: > resvec.push_back(aDirEntry); > }; > } > aDirEntry.clear(); > p1 = p2 + 1; > } > > return resvec; >} > > >OUString FTPURL::net_title() const >{ > CURL *curl = m_pFCP->handle(); > > SET_CONTROL_CONTAINER; > curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer > struct curl_slist *slist = nullptr; > // post request > slist = curl_slist_append(slist,"PWD"); > curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist); > > bool try_more(true); > CURLcode err; > OUString aNetTitle; > > while(true) { > OUString url(ident(false,true)); > > if(try_more && !url.endsWith("/")) > url += "/"; // add end-slash > else if(!try_more && url.endsWith("/")) > url = url.copy(0,url.getLength()-1); // remove end-slash > > setCurlUrl(curl, url); > err = curl_easy_perform(curl); > > if(err == CURLE_OK) { // get the title from the server > char* fwd = static_cast<char*>(control.m_pBuffer); > sal_uInt32 len = control.m_nWritePos; > > aNetTitle = OUString(fwd,len,RTL_TEXTENCODING_UTF8); > // the buffer now contains the name of the file; > // analyze the output: > // Format of current working directory: > // 257 "/bla/bla" is current directory > sal_Int32 index1 = aNetTitle.lastIndexOf("257"); > index1 = aNetTitle.indexOf('"', index1 + std::strlen("257")) + 1; > sal_Int32 index2 = aNetTitle.indexOf('"', index1); > aNetTitle = index2 > index1 > ? aNetTitle.copy(index1, index2 - index1) : OUString(); > if( aNetTitle != "/" ) { > index1 = aNetTitle.lastIndexOf('/'); > aNetTitle = aNetTitle.copy(1+index1); > } > try_more = false; > } else if(err == CURLE_BAD_PASSWORD_ENTERED) > // the client should retry after getting the correct > // username + password > throw curl_exception(err); >#if LIBCURL_VERSION_NUM>=0x070d01 /* 7.13.1 */ > else if(err == CURLE_LOGIN_DENIED) > // the client should retry after getting the correct > // username + password > throw curl_exception(err); >#endif > else if(try_more && err == CURLE_FTP_ACCESS_DENIED) { > // We were either denied access when trying to login to > // an FTP server or when trying to change working directory > // to the one given in the URL. > if(!m_aPathSegmentVec.empty()) > // determine title form url > aNetTitle = decodePathSegment(m_aPathSegmentVec.back()); > else > // must be root > aNetTitle = "/"; > try_more = false; > } > > if(try_more) > try_more = false; > else > break; > } > > curl_slist_free_all(slist); > return aNetTitle; >} > > >FTPDirentry FTPURL::direntry() const >{ > OUString nettitle = net_title(); > FTPDirentry aDirentry; > > aDirentry.m_aName = nettitle; // init aDirentry > if( nettitle == "/" || nettitle == ".." ) > aDirentry.m_nMode = INETCOREFTP_FILEMODE_ISDIR; > else > aDirentry.m_nMode = INETCOREFTP_FILEMODE_UNKNOWN; > > aDirentry.m_nSize = 0; > > if( nettitle != "/" ) { > // try to open the parent directory > FTPURL aURL(parent(),m_pFCP); > > std::vector<FTPDirentry> aList = aURL.list(OpenMode::ALL); > > for(FTPDirentry & d : aList) { > if(d.m_aName == nettitle) { // the relevant file is found > aDirentry = d; > break; > } > } > } > return aDirentry; >} > > >extern "C" { > > static size_t memory_read(void *ptr,size_t size,size_t nmemb,void *stream) > { > sal_Int32 nRequested = sal_Int32(size*nmemb); > CurlInput *curlInput = static_cast<CurlInput*>(stream); > if(curlInput) > return size_t(curlInput->read(static_cast<sal_Int8*>(ptr),nRequested)); > else > return 0; > } > >} > > >void FTPURL::insert(bool replaceExisting,void* stream) const >{ > if(!replaceExisting) { >// FTPDirentry aDirentry(direntry()); >// if(aDirentry.m_nMode == INETCOREFTP_FILEMODE_UNKNOWN) > // throw curl_exception(FILE_EXIST_DURING_INSERT); > throw curl_exception(FILE_MIGHT_EXIST_DURING_INSERT); > } // else > // overwrite is default in libcurl > > CURL *curl = m_pFCP->handle(); > > SET_CONTROL_CONTAINER; > curl_easy_setopt(curl,CURLOPT_NOBODY,false); // no data => no transfer > curl_easy_setopt(curl,CURLOPT_POSTQUOTE,0); > curl_easy_setopt(curl,CURLOPT_QUOTE,0); > curl_easy_setopt(curl,CURLOPT_READFUNCTION,memory_read); > curl_easy_setopt(curl,CURLOPT_READDATA,stream); > curl_easy_setopt(curl, CURLOPT_UPLOAD,1); > > OUString url(ident(false,true)); > setCurlUrl(curl, url); > > CURLcode err = curl_easy_perform(curl); > curl_easy_setopt(curl, CURLOPT_UPLOAD,false); > > if(err != CURLE_OK) > throw curl_exception(err); >} > > >void FTPURL::mkdir(bool ReplaceExisting) const >{ > OString title; > if(!m_aPathSegmentVec.empty()) { > OUString titleOU = m_aPathSegmentVec.back(); > titleOU = decodePathSegment(titleOU); > title = OString(titleOU.getStr(), > titleOU.getLength(), > RTL_TEXTENCODING_UTF8); > } > else > // will give an error > title = OString("/"); > > OString aDel("del "); aDel += title; > OString mkd("mkd "); mkd += title; > > struct curl_slist *slist = nullptr; > > FTPDirentry aDirentry(direntry()); > if(!ReplaceExisting) { >// if(aDirentry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN) >// throw curl_exception(FOLDER_EXIST_DURING_INSERT); > throw curl_exception(FOLDER_MIGHT_EXIST_DURING_INSERT); > } else if(aDirentry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN) > slist = curl_slist_append(slist,aDel.getStr()); > > slist = curl_slist_append(slist,mkd.getStr()); > > CURL *curl = m_pFCP->handle(); > SET_CONTROL_CONTAINER; > curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer > curl_easy_setopt(curl,CURLOPT_QUOTE,0); > > // post request > curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist); > > OUString url(parent(true)); > if(!url.endsWith("/")) > url += "/"; > setCurlUrl(curl, url); > > CURLcode err = curl_easy_perform(curl); > curl_slist_free_all(slist); > if(err != CURLE_OK) > throw curl_exception(err); >} > > >OUString FTPURL::ren(const OUString& NewTitle) >{ > CURL *curl = m_pFCP->handle(); > > // post request > OString renamefrom("RNFR "); > OUString OldTitle = net_title(); > renamefrom += > OString(OldTitle.getStr(), > OldTitle.getLength(), > RTL_TEXTENCODING_UTF8); > > OString renameto("RNTO "); > renameto += > OString(NewTitle.getStr(), > NewTitle.getLength(), > RTL_TEXTENCODING_UTF8); > > struct curl_slist *slist = nullptr; > slist = curl_slist_append(slist,renamefrom.getStr()); > slist = curl_slist_append(slist,renameto.getStr()); > curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist); > > SET_CONTROL_CONTAINER; > curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer > curl_easy_setopt(curl,CURLOPT_QUOTE,0); > > OUString url(parent(true)); > if(!url.endsWith("/")) > url += "/"; > setCurlUrl(curl, url); > > CURLcode err = curl_easy_perform(curl); > curl_slist_free_all(slist); > if(err != CURLE_OK) > throw curl_exception(err); > else if( !m_aPathSegmentVec.empty() && m_aPathSegmentVec.back() != ".." ) > m_aPathSegmentVec.back() = encodePathSegment(NewTitle); > return OldTitle; >} > > >void FTPURL::del() const >{ > FTPDirentry aDirentry(direntry()); > > OString dele(aDirentry.m_aName.getStr(), > aDirentry.m_aName.getLength(), > RTL_TEXTENCODING_UTF8); > > if(aDirentry.m_nMode & INETCOREFTP_FILEMODE_ISDIR) { > std::vector<FTPDirentry> vec = list(sal_Int16(OpenMode::ALL)); > for(const FTPDirentry & i : vec) > { > try { > FTPURL url(i.m_aURL,m_pFCP); > url.del(); > } catch(const curl_exception&) { > } > } > dele = OString("RMD ") + dele; > } > else if(aDirentry.m_nMode != INETCOREFTP_FILEMODE_UNKNOWN) > dele = OString("DELE ") + dele; > else > return; > > // post request > CURL *curl = m_pFCP->handle(); > struct curl_slist *slist = nullptr; > slist = curl_slist_append(slist,dele.getStr()); > curl_easy_setopt(curl,CURLOPT_POSTQUOTE,slist); > > SET_CONTROL_CONTAINER; > curl_easy_setopt(curl,CURLOPT_NOBODY,true); // no data => no transfer > curl_easy_setopt(curl,CURLOPT_QUOTE,0); > > OUString url(parent(true)); > if(!url.endsWith("/")) > url += "/"; > setCurlUrl(curl, url); > > CURLcode err = curl_easy_perform(curl); > curl_slist_free_all(slist); > if(err != CURLE_OK) > throw curl_exception(err); >} > >/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 112689
: 148695 |
148718