void TransportSSH::send(const std::string& source) { std::vector<std::string> sourcelist; std::vector<std::string>::const_iterator source_iter; if (_uri._host == "") throw std::string (STRING_TRANSPORT_SSH_URI); // cmd line is: scp [-p port] [user@]host:path if (_uri._port != "") { _arguments.push_back ("-P"); _arguments.push_back (_uri._port); } if (is_filelist (source)) { expand_braces (source, _uri._data, sourcelist); // Is there more than one source? // Then path has to end with a '/' if (sourcelist.size () > 1 && !_uri.is_directory ()) throw format (STRING_TRANSPORT_URI_NODIR, _uri); for (source_iter = sourcelist.begin (); source_iter != sourcelist.end (); ++source_iter) { _arguments.push_back (*source_iter); } } else { _arguments.push_back (source); } if (_uri._user != "") { _arguments.push_back (_uri._user + "@" + _uri._host + ":" + escape (_uri._path, ' ')); } else { _arguments.push_back (_uri._host + ":" + escape (_uri._path, ' ')); } if (execute ()) throw std::string (STRING_TRANSPORT_SSH_FAIL); }
/// Perform brace expansion. static expand_error_t expand_braces(const wcstring &instr, expand_flags_t flags, std::vector<completion_t> *out, parse_error_list_t *errors) { bool syntax_error = false; int brace_count = 0; const wchar_t *brace_begin = NULL, *brace_end = NULL; const wchar_t *last_sep = NULL; const wchar_t *item_begin; size_t length_preceding_braces, length_following_braces, tot_len; const wchar_t *const in = instr.c_str(); // Locate the first non-nested brace pair. for (const wchar_t *pos = in; (*pos) && !syntax_error; pos++) { switch (*pos) { case BRACE_BEGIN: { if (brace_count == 0) brace_begin = pos; brace_count++; break; } case BRACE_END: { brace_count--; if (brace_count < 0) { syntax_error = true; } else if (brace_count == 0) { brace_end = pos; } break; } case BRACE_SEP: { if (brace_count == 1) last_sep = pos; break; } default: { break; // we ignore all other characters here } } } if (brace_count > 0) { if (!(flags & EXPAND_FOR_COMPLETIONS)) { syntax_error = true; } else { // The user hasn't typed an end brace yet; make one up and append it, then expand // that. wcstring mod; if (last_sep) { mod.append(in, brace_begin - in + 1); mod.append(last_sep + 1); mod.push_back(BRACE_END); } else { mod.append(in); mod.push_back(BRACE_END); } // Note: this code looks very fishy, apparently it has never worked. return expand_braces(mod, 1, out, errors); } } // Expand a literal "{}" to itself because it is useless otherwise, // and this eases e.g. `find -exec {}`. See #1109. if (brace_begin + 1 == brace_end) { wcstring newstr = instr; newstr.at(brace_begin - in) = L'{'; newstr.at(brace_end - in) = L'}'; return expand_braces(newstr, flags, out, errors); } if (syntax_error) { append_syntax_error(errors, SOURCE_LOCATION_UNKNOWN, _(L"Mismatched braces")); return EXPAND_ERROR; } if (brace_begin == NULL) { append_completion(out, instr); return EXPAND_OK; } length_preceding_braces = (brace_begin - in); length_following_braces = wcslen(brace_end) - 1; tot_len = length_preceding_braces + length_following_braces; item_begin = brace_begin + 1; for (const wchar_t *pos = (brace_begin + 1); true; pos++) { if (brace_count == 0 && ((*pos == BRACE_SEP) || (pos == brace_end))) { assert(pos >= item_begin); size_t item_len = pos - item_begin; wcstring item = wcstring(item_begin, item_len); item = trim(item, (const wchar_t[]) { BRACE_SPACE, L'\0' }); for (auto &c : item) { if (c == BRACE_SPACE) { c = ' '; } } wcstring whole_item; whole_item.reserve(tot_len + item_len + 2); whole_item.append(in, length_preceding_braces); whole_item.append(item.begin(), item.end()); whole_item.append(brace_end + 1); expand_braces(whole_item, flags, out, errors); item_begin = pos + 1; if (pos == brace_end) break; }