1//
2// FTPSStreamFactory.cpp
3//
4// Library: Net
5// Package: FTP
6// Module: FTPSStreamFactory
7//
8// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
9// and Contributors.
10//
11// SPDX-License-Identifier: BSL-1.0
12//
13
14
15#include "Poco/Net/FTPSStreamFactory.h"
16#include "Poco/Net/FTPSClientSession.h"
17#include "Poco/Net/NetException.h"
18#include "Poco/URI.h"
19#include "Poco/URIStreamOpener.h"
20#include "Poco/UnbufferedStreamBuf.h"
21#include "Poco/Path.h"
22
23
24using Poco::URIStreamFactory;
25using Poco::URI;
26using Poco::URIStreamOpener;
27using Poco::UnbufferedStreamBuf;
28using Poco::Path;
29
30
31namespace Poco {
32namespace Net {
33
34
35class FTPStreamBuf: public UnbufferedStreamBuf
36{
37public:
38 FTPStreamBuf(std::istream& istr):
39 _istr(istr)
40 {
41 // make sure exceptions from underlying string propagate
42 _istr.exceptions(std::ios::badbit);
43 }
44
45 ~FTPStreamBuf()
46 {
47 }
48
49private:
50 int readFromDevice()
51 {
52 return _istr.get();
53 }
54
55 std::istream& _istr;
56};
57
58
59class FTPSIOS: public virtual std::ios
60{
61public:
62 FTPSIOS(std::istream& istr):
63 _buf(istr)
64 {
65 poco_ios_init(&_buf);
66 }
67
68 ~FTPSIOS()
69 {
70 }
71
72 FTPStreamBuf* rdbuf()
73 {
74 return &_buf;
75 }
76
77protected:
78 FTPStreamBuf _buf;
79};
80
81
82class FTPSStream: public FTPSIOS, public std::istream
83{
84public:
85 FTPSStream(std::istream& istr, FTPSClientSession* pSession):
86 FTPSIOS(istr),
87 std::istream(&_buf),
88 _pSession(pSession)
89 {
90 }
91
92 ~FTPSStream()
93 {
94 delete _pSession;
95 }
96
97private:
98 FTPSClientSession* _pSession;
99};
100
101
102std::string FTPSStreamFactory::_anonymousPassword("poco@localhost");
103FTPPasswordProvider* FTPSStreamFactory::_pPasswordProvider(0);
104
105
106FTPSStreamFactory::FTPSStreamFactory()
107{
108}
109
110
111FTPSStreamFactory::~FTPSStreamFactory()
112{
113}
114
115
116std::istream* FTPSStreamFactory::open(const URI& uri)
117{
118 poco_assert (uri.getScheme() == "ftps");
119
120 FTPSClientSession* pSession = new FTPSClientSession(uri.getHost(), uri.getPort());
121 try
122 {
123 std::string username;
124 std::string password;
125 getUserInfo(uri, username, password);
126
127 std::string path;
128 char type;
129 getPathAndType(uri, path, type);
130
131 pSession->login(username, password);
132 if (type == 'a')
133 pSession->setFileType(FTPClientSession::TYPE_TEXT);
134
135 Path p(path, Path::PATH_UNIX);
136 p.makeFile();
137 for (int i = 0; i < p.depth(); ++i)
138 pSession->setWorkingDirectory(p[i]);
139 std::string file(p.getFileName());
140 std::istream& istr = (type == 'd' ? pSession->beginList(file) : pSession->beginDownload(file));
141 return new FTPSStream(istr, pSession);
142 }
143 catch (...)
144 {
145 delete pSession;
146 throw;
147 }
148}
149
150
151void FTPSStreamFactory::setAnonymousPassword(const std::string& password)
152{
153 _anonymousPassword = password;
154}
155
156
157const std::string& FTPSStreamFactory::getAnonymousPassword()
158{
159 return _anonymousPassword;
160}
161
162
163void FTPSStreamFactory::setPasswordProvider(FTPPasswordProvider* pProvider)
164{
165 _pPasswordProvider = pProvider;
166}
167
168
169FTPPasswordProvider* FTPSStreamFactory::getPasswordProvider()
170{
171 return _pPasswordProvider;
172}
173
174
175void FTPSStreamFactory::splitUserInfo(const std::string& userInfo, std::string& username, std::string& password)
176{
177 std::string::size_type pos = userInfo.find(':');
178 if (pos != std::string::npos)
179 {
180 username.assign(userInfo, 0, pos++);
181 password.assign(userInfo, pos, userInfo.size() - pos);
182 }
183 else username = userInfo;
184}
185
186
187void FTPSStreamFactory::getUserInfo(const URI& uri, std::string& username, std::string& password)
188{
189 splitUserInfo(uri.getUserInfo(), username, password);
190 if (username.empty())
191 {
192 username = "anonymous";
193 password = _anonymousPassword;
194 }
195 else if (password.empty())
196 {
197 if (_pPasswordProvider)
198 password = _pPasswordProvider->password(username, uri.getHost());
199 else
200 throw FTPException(std::string("Password required for ") + username + "@" + uri.getHost());
201 }
202}
203
204
205void FTPSStreamFactory::getPathAndType(const Poco::URI& uri, std::string& path, char& type)
206{
207 path = uri.getPath();
208 type = 'i';
209 std::string::size_type pos = path.rfind(';');
210 if (pos != std::string::npos)
211 {
212 if (path.length() == pos + 7 && path.compare(pos + 1, 5, "type=") == 0)
213 {
214 type = path[pos + 6];
215 path.resize(pos);
216 }
217 }
218}
219
220
221void FTPSStreamFactory::registerFactory()
222{
223 URIStreamOpener::defaultOpener().registerStreamFactory("ftps", new FTPSStreamFactory);
224}
225
226
227void FTPSStreamFactory::unregisterFactory()
228{
229 URIStreamOpener::defaultOpener().unregisterStreamFactory("ftps");
230}
231
232
233} } // namespace Poco::Net
234