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 15 SftpClient::SftpClient() 16 : 17 SpawningUploadClient() 18 { 19 } 20 21 22 SftpClient::~SftpClient() 23 { 24 if (OutputPipe() >= 0) 25 SendCommand("quit\n"); 26 } 27 28 29 bool 30 SftpClient::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 53 bool 54 SftpClient::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 76 bool 77 SftpClient::PrintWorkingDir(string& dir) 78 { 79 SendCommand("pwd\n"); 80 return false; 81 } 82 83 84 bool 85 SftpClient::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 156 bool 157 SftpClient::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 191 bool 192 SftpClient::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 201 bool 202 SftpClient::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 252 bool 253 SftpClient::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 287 void 288 SftpClient::SetPassive(bool on) 289 { 290 } 291 292 293 const char* 294 SftpClient::_GetLongReadText() const 295 { 296 return B_TRANSLATE("read: %ld\n"); 297 } 298 299 300 const char* 301 SftpClient::_GetReadText() const 302 { 303 return B_TRANSLATE("read: %d\n"); 304 } 305 306 307 const char* 308 SftpClient::_GetReplyText() const 309 { 310 return B_TRANSLATE("reply: '%s'\n"); 311 } 312