Subversion Repositories Programming Utils

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
86 rm5248 1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one
3
 * or more contributor license agreements.  See the NOTICE file
4
 * distributed with this work for additional information
5
 * regarding copyright ownership.  The ASF licenses this file
6
 * to you under the Apache License, Version 2.0 (the
7
 * "License"); you may not use this file except in compliance
8
 * with the License.  You may obtain a copy of the License at
9
 *
10
 *   http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing,
13
 * software distributed under the License is distributed on an
14
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
 * KIND, either express or implied.  See the License for the
16
 * specific language governing permissions and limitations
17
 * under the License.
18
 */
19
package org.apache.sshd.server.command;
20
 
21
import java.io.IOException;
22
import java.io.InputStream;
23
import java.io.OutputStream;
24
import java.util.ArrayList;
25
import java.util.Arrays;
26
import java.util.Collections;
27
import java.util.List;
28
 
29
import org.apache.sshd.common.file.FileSystemAware;
30
import org.apache.sshd.common.file.FileSystemView;
31
import org.apache.sshd.common.scp.ScpHelper;
32
import org.apache.sshd.server.Command;
33
import org.apache.sshd.server.Environment;
34
import org.apache.sshd.server.ExitCallback;
35
import org.slf4j.Logger;
36
import org.slf4j.LoggerFactory;
37
 
38
/**
39
 * This commands provide SCP support on both server and client side.
40
 * Permissions and preservation of access / modification times on files
41
 * are not supported.
42
 *
43
 * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
44
 */
45
public class ScpCommand implements Command, Runnable, FileSystemAware {
46
 
47
    protected static final Logger log = LoggerFactory.getLogger(ScpCommand.class);
48
 
49
    protected String name;
50
    protected boolean optR;
51
    protected boolean optT;
52
    protected boolean optF;
53
    protected boolean optD;
54
    protected boolean optP; // TODO: handle modification times
55
    protected FileSystemView root;
56
    protected String path;
57
    protected InputStream in;
58
    protected OutputStream out;
59
    protected OutputStream err;
60
    protected ExitCallback callback;
61
    protected IOException error;
62
 
63
    public ScpCommand(String command) {
64
        this.name = command;
65
        log.debug("Executing command {}", command);
66
        String[] args = command.split(" ");
67
        for (int i = 1; i < args.length; i++) {
68
            if (args[i].charAt(0) == '-') {
69
                for (int j = 1; j < args[i].length(); j++) {
70
                    switch (args[i].charAt(j)) {
71
                        case 'f':
72
                            optF = true;
73
                            break;
74
                        case 'p':
75
                            optP = true;
76
                            break;
77
                        case 'r':
78
                            optR = true;
79
                            break;
80
                        case 't':
81
                            optT = true;
82
                            break;
83
                        case 'd':
84
                            optD = true;
85
                            break;
86
//                          default:
87
//                            error = new IOException("Unsupported option: " + args[i].charAt(j));
88
//                            return;
89
                    }
90
                }
91
            } else {
92
                path = command.substring(command.indexOf(args[i-1]) + args[i-1].length() + 1);
93
                if (path.startsWith("\"") && path.endsWith("\"") || path.startsWith("'") && path.endsWith("'")) {
94
                    path = path.substring(1, path.length() - 1);
95
                }
96
                break;
97
            }
98
        }
99
        if (!optF && !optT) {
100
            error = new IOException("Either -f or -t option should be set");
101
        }
102
    }
103
 
104
    public void setInputStream(InputStream in) {
105
        this.in = in;
106
    }
107
 
108
    public void setOutputStream(OutputStream out) {
109
        this.out = out;
110
    }
111
 
112
    public void setErrorStream(OutputStream err) {
113
        this.err = err;
114
    }
115
 
116
    public void setExitCallback(ExitCallback callback) {
117
        this.callback = callback;
118
    }
119
 
120
    public void setFileSystemView(FileSystemView view) {
121
        this.root = view;
122
    }
123
 
124
    public void start(Environment env) throws IOException {
125
        if (error != null) {
126
            throw error;
127
        }
128
        new Thread(this, "ScpCommand: " + name).start();
129
    }
130
 
131
    public void destroy() {
132
    }
133
 
134
    public void run() {
135
        int exitValue = ScpHelper.OK;
136
        String exitMessage = null;
137
        ScpHelper helper = new ScpHelper(in, out, root);
138
        try {
139
            if (optT) {
140
                helper.receive(root.getFile(path), optR, optD, optP);
141
            } else if (optF) {
142
                helper.send(Collections.singletonList(path), optR, optP);
143
            } else {
144
                throw new IOException("Unsupported mode");
145
            }
146
        } catch (IOException e) {
147
            try {
148
                exitValue = ScpHelper.ERROR;
149
                exitMessage = e.getMessage() == null ? "" : e.getMessage();
150
                out.write(exitValue);
151
                out.write(exitMessage.getBytes());
152
                out.write('\n');
153
                out.flush();
154
            } catch (IOException e2) {
155
                // Ignore
156
            }
157
            log.info("Error in scp command", e);
158
        } finally {
159
            if (callback != null) {
160
                callback.onExit(exitValue, exitMessage);
161
            }
162
        }
163
    }
164
 
165
 
166
}