1 module libssh.scp;
2 
3 import libssh.c_bindings.libssh;
4 import libssh.errors;
5 import libssh.utils;
6 import libssh.session;
7 
8 enum SCPMode : int {
9     Write = SSH_SCP_WRITE,
10     Read = SSH_SCP_READ,
11     Recursive = SSH_SCP_RECURSIVE,
12 }
13 
14 enum SCPRequest : int {
15     NewDir = ssh_scp_request_types.SSH_SCP_REQUEST_NEWDIR,
16     NewFile = ssh_scp_request_types.SSH_SCP_REQUEST_NEWFILE,
17     EOF = ssh_scp_request_types.SSH_SCP_REQUEST_EOF,
18     EndDir = ssh_scp_request_types.SSH_SCP_REQUEST_ENDDIR,
19     Warning = ssh_scp_request_types.SSH_SCP_REQUEST_WARNING,
20 }
21 
22 class SSHSCP : Disposable {
23 
24     @property string requestFilename() {
25         auto result = ssh_scp_request_get_filename(this._scp);
26         checkForNullError(result, "Error while getting request file name");
27         return copyFromStrZ(result);
28     }
29 
30     @property uint requestPermissions() {
31         auto result = ssh_scp_request_get_permissions(this._scp);
32         if (result < 0) {
33             throw new SSHException(result);
34         }
35         return cast(uint) result;
36     }
37 
38     @property size_t requestSize() {
39         return ssh_scp_request_get_size(this._scp);
40     }
41 
42     @property ulong requestSize64() {
43         return ssh_scp_request_get_size64(this._scp);
44     }
45 
46     @property string requestWarning() {
47         auto result = ssh_scp_request_get_warning(this._scp);
48         checkForNullError(result, "Error while getting request warning");
49         return copyFromStrZ(result);
50     }
51 
52     void acceptRequest() {
53         auto rc = ssh_scp_accept_request(this._scp);
54         checkForRCError(rc, rc, "Error while accept request");
55     }
56     
57     void denyRequest(string reason) {
58         auto rc = ssh_scp_deny_request(this._scp, toStrZ(reason));
59         checkForRCError(rc, rc, "Error while deny request");
60     }
61 
62     void leaveDirectory() {
63         auto rc = ssh_scp_leave_directory(this._scp);
64         checkForRCError(rc, rc, "Error while leave directory");
65     }
66 
67     SCPRequest pullRequest() {
68         auto rc = ssh_scp_pull_request(this._scp);
69         if (rc < 0) {
70             throw new SSHException(rc, "Error while pull request");
71         }
72         return cast(SCPRequest) rc;
73     }
74 
75     void pushDirectory(string dirName, int mode) {
76         auto rc = ssh_scp_push_directory(this._scp, toStrZ(dirName), mode);
77         checkForRCError(rc, rc, "Error while pushing directory");
78     }
79 
80     void pushFile(string fileName, size_t size, uint mode) {
81         auto rc = ssh_scp_push_file(this._scp, toStrZ(fileName), size, cast(uint) mode);
82         checkForRCError(rc, rc, "Error while pushing file");
83     }
84 
85     void pushFile64(string fileName, ulong size, uint mode) {
86         auto rc = ssh_scp_push_file64(this._scp, toStrZ(fileName), size, cast(uint) mode);
87         checkForRCError(rc, rc, "Error while pushing file");
88     }
89 
90     int read(void[] buffer) {
91         auto rc = ssh_scp_read(this._scp, buffer.ptr, buffer.length);
92         if (rc < 0) {
93             throw new SSHException(rc, "Error while reading");
94         }
95         return rc;
96     }
97 
98     void write(const void[] buffer) {
99         auto rc = ssh_scp_write(this._scp, buffer.ptr, buffer.length);
100         checkForRCError(rc, rc, "Error while writing");
101     }
102 
103     void init() {
104         auto rc = ssh_scp_init(this._scp);
105         checkForRCError(rc, rc, "Error while initializing scp");
106     }
107 
108     void close() {
109         auto rc = ssh_scp_close(this._scp);
110         checkForRCError(rc, rc, "Error while closing");
111     }
112     
113     ~this() {
114         this._dispose(true);
115     }
116     
117     override void dispose() {
118         this._dispose(false);
119     }
120 
121     package {
122         this(SSHSession parent, ssh_scp scp) {
123             this._session = parent;
124             this._scp = scp;
125         }
126     }
127     
128     private {
129         void _dispose(bool fromDtor) {
130             if (this._scp !is null) {
131                 ssh_scp_free(this._scp);
132                 this._session = null;
133                 this._scp = null;
134             }
135         }
136 
137         SSHSession _session;
138         ssh_scp _scp;
139     }
140 }