1/* 2 * Copyright 1998-1999 Be, Inc. All Rights Reserved. 3 * Copyright 2003-2019 Haiku, Inc. All rights reserved. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8#include "SftpClient.h" 9 10#include <unistd.h> 11 12#include <String.h> 13 14 15SftpClient::SftpClient() 16 : 17 SpawningUploadClient() 18{ 19} 20 21 22SftpClient::~SftpClient() 23{ 24 if (OutputPipe() >= 0) 25 SendCommand("quit\n"); 26} 27 28 29bool 30SftpClient::ChangeDir(const string& dir) 31{ 32 int len; 33 BString cmd("cd"); 34 BString reply; 35 36 cmd << " " << dir.c_str() << "\n"; 37 SendCommand(cmd.String()); 38 39 len = ReadReply(&reply); 40 if (len < 0) { 41 fprintf(stderr, _GetReadText(), len); 42 return false; 43 } 44 45 fprintf(stderr, _GetReplyText(), reply.String()); 46 if (reply.FindFirst("sftp>") < 0) 47 return false; 48 49 return true; 50} 51 52 53bool 54SftpClient::ListDirContents(string& listing) 55{ 56 int len; 57 BString reply; 58 59 SendCommand("ls\n"); 60 do { 61 len = ReadReply(&reply); 62 if (len < 0) { 63 fprintf(stderr, _GetReadText(), len); 64 return false; 65 } 66 fprintf(stderr, _GetReplyText(), reply.String()); 67 printf("%s", reply.String()); 68 if (reply.FindFirst("sftp>") == 0) 69 return true; 70 } while (true); 71 72 return false; 73} 74 75 76bool 77SftpClient::PrintWorkingDir(string& dir) 78{ 79 SendCommand("pwd\n"); 80 return false; 81} 82 83 84bool 85SftpClient::Connect(const string& server, const string& login, 86 const string& passwd) 87{ 88 BString cmd("sftp "); 89 BString host(server.c_str()); 90 BString port; 91 92 if (host.FindFirst(':')) 93 host.MoveInto(port, host.FindFirst(':'), host.Length()); 94 port.RemoveAll(":"); 95 96 if (port.Length()) 97 cmd << "-oPort=" << port << " "; 98 99 cmd << login.c_str(); 100 cmd << "@" << host.String(); 101 printf("COMMAND: '%s'\n", cmd.String()); 102 SetCommandLine(cmd.String()); 103 104 if (!SpawningUploadClient::Connect(server, login, passwd)) 105 return false; 106 107 BString reply; 108 ssize_t len; 109 110 len = ReadReply(&reply); 111 if (len < 0) { 112 fprintf(stderr, _GetLongReadText(), len); 113 return false; 114 } 115 fprintf(stderr, _GetReplyText(), reply.String()); 116 if (reply.FindFirst("Connecting to ") != 0) 117 return false; 118 119 len = ReadReply(&reply); 120 if (len < 0) { 121 fprintf(stderr, _GetLongReadText(), len); 122 return false; 123 } 124 125 fprintf(stderr, _GetReplyText(), reply.String()); 126 if (reply.FindFirst(/*[pP]*/"assword:") < 0) 127 return false; 128 129 write(OutputPipe(), passwd.c_str(), strlen(passwd.c_str())); 130 write(OutputPipe(), "\n", 1); 131 132 len = ReadReply(&reply); 133 if (len < 0) { 134 fprintf(stderr, _GetLongReadText(), len); 135 return false; 136 } 137 138 fprintf(stderr, _GetReplyText(), reply.String()); 139 if (reply != "\n") 140 return false; 141 142 len = ReadReply(&reply); 143 if (len < 0) { 144 fprintf(stderr, _GetLongReadText(), len); 145 return false; 146 } 147 148 fprintf(stderr, _GetReplyText(), reply.String()); 149 if (reply.FindFirst("sftp>") < 0) 150 return false; 151 152 return true; 153} 154 155 156bool 157SftpClient::PutFile(const string& local, const string& remote, ftp_mode mode) 158{ 159 int len; 160 //XXX: handle mode ? 161 BString cmd("put"); 162 cmd << " " << local.c_str() << " " << remote.c_str() << "\n"; 163 SendCommand(cmd.String()); 164 165 BString reply; 166 167 len = ReadReply(&reply); 168 if (len < 0) { 169 fprintf(stderr, _GetReadText(), len); 170 return false; 171 } 172 173 fprintf(stderr, _GetReplyText(), reply.String()); 174 if (reply.FindFirst("Uploading") < 0) 175 return false; 176 177 len = ReadReply(&reply); 178 if (len < 0) { 179 fprintf(stderr, _GetReadText(), len); 180 return false; 181 } 182 183 fprintf(stderr, _GetReplyText(), reply.String()); 184 if (reply.FindFirst("sftp>") < 0) 185 return false; 186 187 return true; 188} 189 190 191bool 192SftpClient::GetFile(const string& remote, const string& local, ftp_mode mode) 193{ 194 //XXX 195 return false; 196} 197 198 199// Note: this only works for local remote moves, cross filesystem moves 200// will not work 201bool 202SftpClient::MoveFile(const string& oldPath, const string& newPath) 203{ 204 int len; 205 206 // sftpd can't rename to an existing file... 207 BString cmd("rm"); 208 cmd << " " << newPath.c_str() << "\n"; 209 fprintf(stderr, "CMD: '%s'\n", cmd.String()); 210 SendCommand(cmd.String()); 211 BString reply; 212 213 len = ReadReply(&reply); 214 if (len < 0) { 215 fprintf(stderr, _GetReadText(), len); 216 return false; 217 } 218 219 fprintf(stderr, _GetReplyText(), reply.String()); 220 // we don't care if it worked or not. 221 //if (reply.FindFirst("Removing") != 0 && reply.FindFirst("Couldn't") ) 222 // return false; 223 224 len = ReadReply(&reply); 225 if (len < 0) { 226 fprintf(stderr, _GetReadText(), len); 227 return false; 228 } 229 230 fprintf(stderr, _GetReplyText(), reply.String()); 231 if (reply.FindFirst("sftp>") < 0) 232 return false; 233 234 cmd = "rename"; 235 cmd << " " << oldPath.c_str() << " " << newPath.c_str() << "\n"; 236 SendCommand(cmd.String()); 237 238 len = ReadReply(&reply); 239 if (len < 0) { 240 fprintf(stderr, _GetReadText(), len); 241 return false; 242 } 243 244 fprintf(stderr, _GetReplyText(), reply.String()); 245 if (reply.FindFirst("sftp>") < 0) 246 return false; 247 248 return true; 249} 250 251 252bool 253SftpClient::Chmod(const string& path, const string& mod) 254{ 255 int len; 256 //XXX: handle mode ? 257 BString cmd("chmod"); 258 cmd << " " << mod.c_str() << " " << path.c_str() << "\n"; 259 SendCommand(cmd.String()); 260 261 BString reply; 262 263 len = ReadReply(&reply); 264 if (len < 0) { 265 fprintf(stderr, _GetReadText(), len); 266 return false; 267 } 268 269 fprintf(stderr, _GetReplyText(), reply.String()); 270 if (reply.FindFirst("Changing") < 0) 271 return false; 272 273 len = ReadReply(&reply); 274 if (len < 0) { 275 fprintf(stderr, _GetReadText(), len); 276 return false; 277 } 278 279 fprintf(stderr, _GetReplyText(), reply.String()); 280 if (reply.FindFirst("sftp>") < 0) 281 return false; 282 283 return true; 284} 285 286 287void 288SftpClient::SetPassive(bool on) 289{ 290} 291 292 293const char* 294SftpClient::_GetLongReadText() const 295{ 296 return B_TRANSLATE("read: %ld\n"); 297} 298 299 300const char* 301SftpClient::_GetReadText() const 302{ 303 return B_TRANSLATE("read: %d\n"); 304} 305 306 307const char* 308SftpClient::_GetReplyText() const 309{ 310 return B_TRANSLATE("reply: '%s'\n"); 311} 312