[Pkg-owncloud-commits] [owncloud-client] 74/211: Windows Shell Integration: Use the QLocalSocket on windo and do the request assynchroniously

Sandro Knauß hefee-guest at moszumanska.debian.org
Sat Oct 25 09:10:28 UTC 2014


This is an automated email from the git hooks/post-receive script.

hefee-guest pushed a commit to branch master
in repository owncloud-client.

commit 4b001a77b36c3e2815a5f36d17b388cd0420bce0
Author: Olivier Goffart <ogoffart at woboq.com>
Date:   Tue Oct 14 16:05:48 2014 +0200

    Windows Shell Integration: Use the QLocalSocket on windo and do the request assynchroniously
    
    Squashed commit of the following:
    
    commit 4d9b072f560fa171a1390b7c74425614aa20e955
    Author: Olivier Goffart <ogoffart at woboq.com>
    Date:   Tue Oct 14 16:04:02 2014 +0200
    
        Remove useless variable
    
    commit 8e85de0307ec5f31bf3f92a7de793fed7d41c2ea
    Author: Daniel Molkentin <danimo at owncloud.com>
    Date:   Tue Oct 14 16:01:52 2014 +0200
    
        Make Windows Explorer Extension build
    
    commit 8e2942cd9fd32e3af72d60cba0d06bd9d6222a45
    Author: Daniel Molkentin <danimo at owncloud.com>
    Date:   Tue Oct 14 11:39:37 2014 +0200
    
        Fix compilation
    
    commit 0fc0c0e0e0c7e58ad97f62700256c7d1f8c0670b
    Author: Olivier Goffart <ogoffart at woboq.com>
    Date:   Tue Oct 14 11:48:32 2014 +0200
    
        Windows Shell Integration: Try to let the thread notify about changes when there are changes
    
    commit 4a1712b7c03269ca3007f167b8f313ea47655967
    Author: Olivier Goffart <ogoffart at woboq.com>
    Date:   Tue Oct 14 11:35:20 2014 +0200
    
        Windows Shell Integration: Share the RemotePathChecker amongst all the OCOverlay instances
    
    commit 2d87408e9af5a4d7ab71c460ce606ba1f367c09f
    Author: Olivier Goffart <ogoffart at woboq.com>
    Date:   Mon Oct 13 18:55:15 2014 +0200
    
        Windows Shell Integration: Attempts to wait on multiple objects (WIP)
    
    commit e448e427b6d1561ad7a40d08fc6632f4d2b4ef44
    Author: Daniel Molkentin <danimo at owncloud.com>
    Date:   Mon Oct 13 17:58:02 2014 +0200
    
        Introduce a worker thread
    
    commit 2344407ec0bc1ce173ebbacadcf3992d62d94078
    Author: Olivier Goffart <ogoffart at woboq.com>
    Date:   Mon Oct 13 17:03:47 2014 +0200
    
        Windows Shell Integration:  try to keep the socket open using a thread (WIP)
    
    commit ea6d5273ed60d8bc3f1c5d5c6936364d783a1c0f
    Author: Daniel Molkentin <danimo at owncloud.com>
    Date:   Mon Oct 13 15:27:46 2014 +0200
    
        Make Explorer plugin work again with named pipes
    
        This is a temporary hack, which needs more refactoring.
    
    commit 44a3437a44082379efa0078c9afd7b8bbde930de
    Author: Daniel Molkentin <danimo at owncloud.com>
    Date:   Sat Oct 11 07:31:24 2014 +0200
    
        Fix code
    
    commit 123390a0f3516c0078309d7048c6d2acb9293676
    Author: Olivier Goffart <ogoffart at woboq.com>
    Date:   Fri Oct 10 16:29:35 2014 +0200
    
        Windows shell integration: Use named pipe  (WIP)
    
    commit 9eea7e2321abeac6b8db0bd85bfce612dbf6bb20
    Author: Olivier Goffart <ogoffart at woboq.com>
    Date:   Wed Oct 1 12:04:13 2014 +0200
    
        Windows Shell Integration: Simplify StringUtil
    
        This fixes a memory leak in CommunicationSocket::ReadLine
---
 .../OCShellExtensions/OCOverlays/OCOverlay.cpp     |  26 +---
 .../OCShellExtensions/OCOverlays/OCOverlay.h       |   3 +-
 .../OCUtil/CommunicationSocket.cpp                 | 116 +++++++--------
 .../OCShellExtensions/OCUtil/CommunicationSocket.h |   9 +-
 .../OCShellExtensions/OCUtil/RemotePathChecker.cpp | 162 ++++++++++++---------
 .../OCShellExtensions/OCUtil/RemotePathChecker.h   |  30 +++-
 .../OCShellExtensions/OCUtil/StringUtil.cpp        |  26 ++--
 .../windows/OCShellExtensions/OCUtil/StringUtil.h  |   7 +-
 8 files changed, 210 insertions(+), 169 deletions(-)

diff --git a/shell_integration/windows/OCShellExtensions/OCOverlays/OCOverlay.cpp b/shell_integration/windows/OCShellExtensions/OCOverlays/OCOverlay.cpp
index 8e0265d..967231d 100644
--- a/shell_integration/windows/OCShellExtensions/OCOverlays/OCOverlay.cpp
+++ b/shell_integration/windows/OCShellExtensions/OCOverlays/OCOverlay.cpp
@@ -36,17 +36,13 @@ extern HINSTANCE instanceHandle;
 #define IDM_DISPLAY 0  
 #define IDB_OK 101
 
-namespace {
-	static std::vector<std::wstring> s_watchedDirectories;
-}
-
 OCOverlay::OCOverlay(int state) 
-	: _communicationSocket(0)
-	, _referenceCount(1)
-	, _checker(new RemotePathChecker(PORT))
+	: _referenceCount(1)
 	, _state(state)
 
 {
+    static RemotePathChecker s_remotePathChecker;
+    _checker = &s_remotePathChecker;
 }
 
 OCOverlay::~OCOverlay(void)
@@ -121,23 +117,13 @@ IFACEMETHODIMP OCOverlay::GetPriority(int *pPriority)
 
  IFACEMETHODIMP OCOverlay::IsMemberOf(PCWSTR pwszPath, DWORD dwAttrib)
 {
-	
-	//if(!_IsOverlaysEnabled())
-	//{
-	//	return MAKE_HRESULT(S_FALSE, 0, 0);
-	//}
-
-	// FIXME: Use Registry instead, this will only trigger once
-	// and now follow any user changes in the client
-	if (s_watchedDirectories.empty()) {
-		s_watchedDirectories = _checker->WatchedDirectories();
-	}
+    auto watchedDirectories = _checker->WatchedDirectories();
 
 	wstring wpath(pwszPath);
-	wpath.append(L"\\");
+	//wpath.append(L"\\");
 	vector<wstring>::iterator it;
 	bool watched = false;
-	for (it = s_watchedDirectories.begin(); it != s_watchedDirectories.end(); ++it) {
+	for (it = watchedDirectories.begin(); it != watchedDirectories.end(); ++it) {
 		if (StringUtil::begins_with(wpath, *it)) {
 			watched = true;
 		}
diff --git a/shell_integration/windows/OCShellExtensions/OCOverlays/OCOverlay.h b/shell_integration/windows/OCShellExtensions/OCOverlays/OCOverlay.h
index a84bc45..2e82114 100644
--- a/shell_integration/windows/OCShellExtensions/OCOverlays/OCOverlay.h
+++ b/shell_integration/windows/OCShellExtensions/OCOverlays/OCOverlay.h
@@ -35,14 +35,13 @@ public:
     IFACEMETHODIMP_(ULONG) Release();
 
 protected:
-    ~OCOverlay(void);
+    ~OCOverlay();
 
 private:
 	//bool _GenerateMessage(const wchar_t*, std::wstring*);
 
 	bool _IsOverlaysEnabled();
     long _referenceCount;
-	CommunicationSocket* _communicationSocket;
 	RemotePathChecker* _checker;
 	int _state;
 };
diff --git a/shell_integration/windows/OCShellExtensions/OCUtil/CommunicationSocket.cpp b/shell_integration/windows/OCShellExtensions/OCUtil/CommunicationSocket.cpp
index a2f4a94..13494d9 100644
--- a/shell_integration/windows/OCShellExtensions/OCUtil/CommunicationSocket.cpp
+++ b/shell_integration/windows/OCShellExtensions/OCUtil/CommunicationSocket.cpp
@@ -21,6 +21,7 @@
 #include <windows.h>
 #include <iostream>
 #include <vector>
+#include <array>
 
 #include <fstream> 
 
@@ -30,8 +31,8 @@ using namespace std;
 
 #define DEFAULT_BUFLEN 4096
 
-CommunicationSocket::CommunicationSocket(int port)
-	: _port(port), _clientSocket(INVALID_SOCKET)
+CommunicationSocket::CommunicationSocket()
+    : _pipe(INVALID_HANDLE_VALUE)
 {
 }
 
@@ -43,64 +44,42 @@ CommunicationSocket::~CommunicationSocket()
 bool CommunicationSocket::Close()
 {
 	WSACleanup();
-	bool closed = (closesocket(_clientSocket) == 0);
-	shutdown(_clientSocket, SD_BOTH);
-	_clientSocket = INVALID_SOCKET;
-	return closed;
+	if (_pipe == INVALID_HANDLE_VALUE) {
+		return false;
+	}
+	CloseHandle(_pipe);
+	_pipe = INVALID_HANDLE_VALUE;
+	return true;
 }
 
 
 bool CommunicationSocket::Connect()
 {
-	WSADATA wsaData;
-
-	HRESULT iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
-
-	if (iResult != NO_ERROR) {
-		int error = WSAGetLastError();
-	}
-
-
-	_clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-
-	if (_clientSocket == INVALID_SOCKET) {
-		//int error = WSAGetLastError();
-		Close();
-		return false;
-	}
-
-	struct sockaddr_in clientService;
-
-	clientService.sin_family = AF_INET;
-	clientService.sin_addr.s_addr = inet_addr(PLUG_IN_SOCKET_ADDRESS);
-	clientService.sin_port = htons(_port);
+    auto pipename = std::wstring(L"\\\\.\\pipe\\");
+    pipename += L"ownCloud";
 
-	iResult = connect(_clientSocket, (SOCKADDR*)&clientService, sizeof(clientService));
-	DWORD timeout = 500; // ms
-	setsockopt(_clientSocket, SOL_SOCKET, SO_RCVTIMEO, (const char*) &timeout, sizeof(DWORD));
+	_pipe = CreateFile(pipename.data(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
 
-	if (iResult == SOCKET_ERROR) {
-		//int error = WSAGetLastError();
-		Close();
-		return false;
-	}
-	return true;
+    if (_pipe == INVALID_HANDLE_VALUE) {
+        return false;
+    }
+    return true;
 }
 
 bool CommunicationSocket::SendMsg(const wchar_t* message)
 {
-	const char* utf8_msg = StringUtil::toUtf8(message);
-	size_t result = send(_clientSocket, utf8_msg, (int)strlen(utf8_msg), 0);
-	delete[] utf8_msg;
-
-	if (result == SOCKET_ERROR) {
-		//int error = WSAGetLastError();
-		closesocket(_clientSocket);
-		return false;
-	}
-
-	return true;
-
+	auto utf8_msg = StringUtil::toUtf8(message);
+
+    DWORD numBytesWritten = 0;
+    auto result = WriteFile( _pipe, utf8_msg.c_str(), DWORD(utf8_msg.size()), &numBytesWritten, NULL);
+
+    if (result) {
+        return true;
+    } else {
+//        qWarning() << "Failed to send data." <<;
+        // look up error code here using GetLastError()
+        return false;
+    }
 }
 
 bool CommunicationSocket::ReadLine(wstring* response)
@@ -109,21 +88,36 @@ bool CommunicationSocket::ReadLine(wstring* response)
 		return false;
 	}
 
-	vector<char> resp_utf8;
-	char buffer;
+    response->clear();
+
+	Sleep(50);
+
 	while (true) {
-		int bytesRead = recv(_clientSocket, &buffer, 1, 0);
-		if (bytesRead <= 0) {
-			response = 0;
+        int lbPos = 0;
+        auto it = std::find(_buffer.begin() + lbPos, _buffer.end(), '\n');
+        if (it != _buffer.end()) {
+            *response = StringUtil::toUtf16(_buffer.data(), DWORD(it - _buffer.begin()));
+            _buffer.erase(_buffer.begin(), it + 1);
+            return true;
+        }
+
+        std::array<char, 128> resp_utf8;
+        DWORD numBytesRead = 0;
+		DWORD totalBytesAvailable = 0;
+		PeekNamedPipe(_pipe, NULL, 0, 0, &totalBytesAvailable, 0);
+		if (totalBytesAvailable == 0) {
 			return false;
 		}
 
-		if (buffer == '\n')	{
-			resp_utf8.push_back(0);
-			*response = StringUtil::toUtf16(&resp_utf8[0], resp_utf8.size());
-			return true;
-		} else {
-			resp_utf8.push_back(buffer);
-		}
+        auto result = ReadFile(_pipe, resp_utf8.data(), DWORD(resp_utf8.size()), &numBytesRead, NULL);
+        if (!result) {
+//            qWarning() << "Failed to read data from the pipe";
+            return false;
+        }
+        if (numBytesRead <= 0) {
+            return false;
+        }
+		_buffer.insert(_buffer.end(), resp_utf8.begin(), resp_utf8.begin()+numBytesRead);
+        continue;
 	}
 }
diff --git a/shell_integration/windows/OCShellExtensions/OCUtil/CommunicationSocket.h b/shell_integration/windows/OCShellExtensions/OCUtil/CommunicationSocket.h
index 7bbf1bf..7e9cd11 100644
--- a/shell_integration/windows/OCShellExtensions/OCUtil/CommunicationSocket.h
+++ b/shell_integration/windows/OCShellExtensions/OCUtil/CommunicationSocket.h
@@ -20,12 +20,13 @@
 #pragma warning (disable : 4251)
 
 #include <string>
+#include <vector>
 #include <WinSock2.h>
 
 class __declspec(dllexport) CommunicationSocket
 {
 public:
-	CommunicationSocket(int port);
+	CommunicationSocket();
 	~CommunicationSocket();
 
 	bool Connect();
@@ -34,9 +35,11 @@ public:
 	bool SendMsg(const wchar_t*);
 	bool ReadLine(std::wstring*);
 
+    HANDLE Event() { return _pipe; }
+
 private:	
-	int _port;
-	SOCKET _clientSocket;
+	HANDLE _pipe;
+	std::vector<char> _buffer;
 };
 
 #endif
\ No newline at end of file
diff --git a/shell_integration/windows/OCShellExtensions/OCUtil/RemotePathChecker.cpp b/shell_integration/windows/OCShellExtensions/OCUtil/RemotePathChecker.cpp
index a6d9cce..5967245 100644
--- a/shell_integration/windows/OCShellExtensions/OCUtil/RemotePathChecker.cpp
+++ b/shell_integration/windows/OCShellExtensions/OCUtil/RemotePathChecker.cpp
@@ -20,88 +20,120 @@
 #include <iostream>
 #include <sstream>
 #include <iterator>
+#include <unordered_set>
+#include <cassert>
+
+#include <shlobj.h>
 
 using namespace std;
 
-RemotePathChecker::RemotePathChecker(int port)
-	: _port(port)
+
+// This code is run in a thread
+void RemotePathChecker::workerThreadLoop()
 {
+    CommunicationSocket socket;
+    std::unordered_set<std::wstring> asked;
+    if (!socket.Connect()) {
+        return;
+        //FIXME! what if this fails!  what if we are disconnected later?
+    }
+
+    while(!_stop) {
+        {
+            std::unique_lock<std::mutex> lock(_mutex);
+            while (!_pending.empty() && !_stop) {
+                auto filePath = _pending.front();
+                _pending.pop();
+
+                lock.unlock();
+                if (!asked.count(filePath)) {
+                    asked.insert(filePath);
+                    socket.SendMsg(wstring(L"RETRIEVE_FILE_STATUS:" + filePath + L'\n').data());
+                }
+                lock.lock();
+            }
+        }
+
+        std::wstring response;
+        while (!_stop && socket.ReadLine(&response)) {
+            if (StringUtil::begins_with(response, wstring(L"REGISTER_PATH:"))) {
+                wstring responsePath = response.substr(14); // length of REGISTER_PATH:
+
+                std::unique_lock<std::mutex> lock(_mutex);
+                _watchedDirectories.push_back(responsePath);
+            } else if (StringUtil::begins_with(response, wstring(L"STATUS:")) ||
+                    StringUtil::begins_with(response, wstring(L"BROADCAST:"))) {
+
+                auto statusBegin = response.find(L':', 0);
+                assert(statusBegin != std::wstring::npos);
+
+                auto statusEnd = response.find(L':', statusBegin + 1);
+                if (statusEnd == std::wstring::npos) {
+                    // the command do not contains two colon?
+                    continue;
+                }
+
+                auto responseStatus = response.substr(statusBegin+1, statusEnd - statusBegin-1);
+                auto responsePath = response.substr(statusEnd+1);
+                auto state = _StrToFileState(responseStatus);
+                auto erased = asked.erase(responsePath);
+
+                {   std::unique_lock<std::mutex> lock(_mutex);
+                    _cache[responsePath] = state;
+                }
+                SHChangeNotify(SHCNE_MKDIR, SHCNF_PATH, responsePath.data(), NULL);
+            }
+        }
+
+        if (_stop)
+            return;
+    }
 }
 
-vector<wstring> RemotePathChecker::WatchedDirectories()
+
+
+RemotePathChecker::RemotePathChecker()
+    : _thread([this]{ this->workerThreadLoop(); } )
+    , _newQueries(CreateEvent(NULL, true, true, NULL))
 {
-	vector<wstring> watchedDirectories;
-	wstring response;
-	bool needed = false;
-
-	CommunicationSocket socket(_port);
-	socket.Connect();
-
-	while (socket.ReadLine(&response)) {
-		if (StringUtil::begins_with(response, wstring(L"REGISTER_PATH:"))) {
-			size_t pathBegin = response.find(L':', 0);
-			if (pathBegin == -1) {
-				continue;
-			}
-
-			// chop trailing '\n'
-			wstring responsePath = response.substr(pathBegin + 1, response.length()-1);
-			watchedDirectories.push_back(responsePath);
-		}
-	}
+}
 
-	return watchedDirectories;
+RemotePathChecker::~RemotePathChecker()
+{
+    _stop = true;
+    //_newQueries.notify_all();
+    SetEvent(_newQueries);
+    _thread.join();
+    CloseHandle(_newQueries);
+}
+
+vector<wstring> RemotePathChecker::WatchedDirectories()
+{
+    std::unique_lock<std::mutex> lock(_mutex);
+    return _watchedDirectories;
 }
 
 bool RemotePathChecker::IsMonitoredPath(const wchar_t* filePath, int* state)
 {
-	wstring request;
-	wstring response;
-	bool needed = false;
-
-	CommunicationSocket socket(_port);
-	socket.Connect();
-	request = L"RETRIEVE_FILE_STATUS:";
-	request += filePath;
-	request += L'\n';
-
-	if (!socket.SendMsg(request.c_str())) {
-		return false;
-	}
+    assert(state); assert(filePath);
 
-	while (socket.ReadLine(&response)) {
-		// discard broadcast messages
-		if (StringUtil::begins_with(response, wstring(L"STATUS:"))) {
-			break;
-		}
-	}
+    std::unique_lock<std::mutex> lock(_mutex);
 
-	size_t statusBegin = response.find(L':', 0);
-	if (statusBegin == -1)
-		return false;
-
-	size_t statusEnd = response.find(L':', statusBegin + 1);
-	if (statusEnd == -1)
-		return false;
-
-
-	wstring responseStatus = response.substr(statusBegin+1, statusEnd - statusBegin-1);
-	wstring responsePath = response.substr(statusEnd+1);
-	if (responsePath == filePath) {
-		if (!state) {
-			return false;
-		}
-		*state = _StrToFileState(responseStatus);
-		if (*state == StateNone) {
-			return false;
-		}
-		needed = true;
-	}
+    auto path = std::wstring(filePath);
+
+    auto it = _cache.find(path);
+    if (it != _cache.end()) {
+        *state = it->second;
+        return true;
+    }
+
+    _pending.push(filePath);
+    SetEvent(_newQueries);
+    return false;
 
-	return needed;
 }
 
-int RemotePathChecker::_StrToFileState(const std::wstring &str)
+RemotePathChecker::FileState RemotePathChecker::_StrToFileState(const std::wstring &str)
 {
 	if (str == L"NOP" || str == L"NONE") {
 		return StateNone;
diff --git a/shell_integration/windows/OCShellExtensions/OCUtil/RemotePathChecker.h b/shell_integration/windows/OCShellExtensions/OCUtil/RemotePathChecker.h
index 1fb1ef9..5c4c43f 100644
--- a/shell_integration/windows/OCShellExtensions/OCUtil/RemotePathChecker.h
+++ b/shell_integration/windows/OCShellExtensions/OCUtil/RemotePathChecker.h
@@ -16,6 +16,12 @@
 
 #include <string>
 #include <vector>
+#include <unordered_map>
+#include <queue>
+#include <thread>
+#include <mutex>
+#include <atomic>
+#include <condition_variable>
 
 #pragma once    
 
@@ -29,14 +35,32 @@ public:
 		StateWarning, StateWarningSWM,
 		StateNone
 	};
-	RemotePathChecker(int port);
+	RemotePathChecker();
+    ~RemotePathChecker();
 	std::vector<std::wstring> WatchedDirectories();
 	bool IsMonitoredPath(const wchar_t* filePath, int* state);
 
 private:
-	int _StrToFileState(const std::wstring &str);
-	int _port;
+	FileState _StrToFileState(const std::wstring &str);
+    std::mutex _mutex;
+    std::thread _thread;
+    std::atomic<bool> _stop;
 
+    // Everything here is protected by the _mutex
+
+    /** The list of paths we need to query. The main thread fill this, and the worker thread
+     * send that to the socket. */
+    std::queue<std::wstring> _pending;
+
+    std::unordered_map<std::wstring, FileState> _cache;
+    std::vector<std::wstring> _watchedDirectories;
+
+
+    // The main thread notifies when there are new items in _pending
+    //std::condition_variable _newQueries;
+    HANDLE _newQueries;
+
+    void workerThreadLoop();
 };
 
 #endif
\ No newline at end of file
diff --git a/shell_integration/windows/OCShellExtensions/OCUtil/StringUtil.cpp b/shell_integration/windows/OCShellExtensions/OCUtil/StringUtil.cpp
index 0c7af0b..aa7ad55 100644
--- a/shell_integration/windows/OCShellExtensions/OCUtil/StringUtil.cpp
+++ b/shell_integration/windows/OCShellExtensions/OCUtil/StringUtil.cpp
@@ -11,22 +11,26 @@
 * details.
 */
 
-#include <Windows.h>
+#include <locale>
+#include <string>
+#include <codecvt>
 
 #include "StringUtil.h"
 
-char* StringUtil::toUtf8(const wchar_t *utf16, int len)
+std::string StringUtil::toUtf8(const wchar_t *utf16, int len)
 {
-	int newlen = WideCharToMultiByte(CP_UTF8, 0, utf16, len, NULL, 0, NULL, NULL);
-	char* str = new char[newlen];
-	WideCharToMultiByte(CP_UTF8, 0, utf16, -1, str, newlen, NULL, NULL);
-	return str;
+	if (len < 0) {
+		len = wcslen(utf16);
+	}
+    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t> > converter;
+    return converter.to_bytes(utf16, utf16+len);
 }
 
-wchar_t* StringUtil::toUtf16(const char *utf8, int len)
+std::wstring StringUtil::toUtf16(const char *utf8, int len)
 {
-	int newlen = MultiByteToWideChar(CP_UTF8, 0, utf8, len, NULL, 0);
-	wchar_t* wstr = new wchar_t[newlen];
-	MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wstr, newlen);
-	return wstr;
+	if (len < 0) {
+		len = strlen(utf8);
+	}
+	std::wstring_convert<std::codecvt_utf8_utf16<wchar_t> > converter;
+    return converter.from_bytes(utf8, utf8+len);
 }
diff --git a/shell_integration/windows/OCShellExtensions/OCUtil/StringUtil.h b/shell_integration/windows/OCShellExtensions/OCUtil/StringUtil.h
index cf6ec86..d64eda7 100644
--- a/shell_integration/windows/OCShellExtensions/OCUtil/StringUtil.h
+++ b/shell_integration/windows/OCShellExtensions/OCUtil/StringUtil.h
@@ -20,15 +20,14 @@
 
 class __declspec(dllexport) StringUtil {
 public:
-	static char*    toUtf8(const wchar_t* utf16, int len = -1);
-	static wchar_t* toUtf16(const char* utf8, int len = -1);
-
+	static std::string  toUtf8(const wchar_t* utf16, int len = -1);
+	static std::wstring toUtf16(const char* utf8, int len = -1);
 
 	template<class T>
 	static bool begins_with(const T& input, const T& match)
 	{
 		return input.size() >= match.size()
-			&& equal(match.begin(), match.end(), input.begin());
+			&& std::equal(match.begin(), match.end(), input.begin());
 	}
 };
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-owncloud/owncloud-client.git



More information about the Pkg-owncloud-commits mailing list