PageRenderTime 27ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/downloadFTP/main.c

https://github.com/ciberwizz/RCOM
C | 441 lines | 303 code | 98 blank | 40 comment | 46 complexity | 47b120b28ee7842eca08c05e89cc2cc4 MD5 | raw file
  1. #include <stdio.h>
  2. #include <sys/types.h>
  3. #include <sys/socket.h>
  4. #include <netinet/in.h>
  5. #include <arpa/inet.h>
  6. #include <stdlib.h>
  7. #include <unistd.h>
  8. #include <signal.h>
  9. #include <netdb.h>
  10. #include <errno.h>
  11. #include <regex.h>
  12. #include <string.h>
  13. struct {
  14. char* ip;
  15. char* username;
  16. char* password;
  17. int porta; //porta default 21
  18. int lport; //porta para fazer listen
  19. char* path; //path para o ficheiro
  20. }Con;
  21. int new_con(char* host, int port);
  22. char* getIP(char* host);
  23. int getArgs(char* arg);
  24. int getLPort(char* buff);
  25. int main(int argc, char *argv[] ){
  26. int sock,lsock, bytes=-1, bytesTotal = 0, size,i, tamanhoFicheiro,j;
  27. char buff[256], temp[256];
  28. char *data, *dataBuff, **tosend;
  29. if( argc >= 2){
  30. if(getArgs(argv[1])<0){
  31. printf("usage: %s ftp://[<user>:<password>@]<host>/<url-path>\n", argv[0]);
  32. return 0;
  33. }
  34. }
  35. else {
  36. printf("usage: %s ftp://[<user>:<password>@]<host>/<url-path>\n", argv[0]);
  37. return 0;
  38. }
  39. tosend = (char**)calloc(100, sizeof(char*));
  40. //init default Con vars
  41. Con.porta = 21;
  42. Con.lport = 0;
  43. printf("struct {\n");
  44. printf(" char* ip=%s\n",Con.ip);
  45. printf(" char* username=%s\n",Con.username);
  46. printf(" char* password=%s\n",Con.password);
  47. printf(" int porta=%d\n",Con.porta);
  48. printf(" int lport=%d\n",Con.lport);
  49. printf(" char* path=%s\n",Con.path);
  50. printf(")}Con;\n");
  51. sock = new_con(Con.ip,21);
  52. bytes = -1;
  53. while(bytes == -1)
  54. bytes = recv(sock,buff,255,0);
  55. buff[bytes] = '\0';
  56. printf("A receber -> %s\n", buff);
  57. //<-- 220 FTP for Alf/Tom/Crazy/Pinguim
  58. if(strncmp("220",buff,3)!=0){
  59. printf("ERRO: expected:%s got: %s\n","220",buff);
  60. return -1;
  61. }
  62. tosend[0] = calloc(256, sizeof(char));
  63. tosend[1] = calloc(256, sizeof(char));
  64. if(Con.username != NULL){
  65. strcpy(tosend[0], "user ");
  66. strcat(tosend[0], Con.username);
  67. strcat(tosend[0], "\n");
  68. printf("A enviar -> %s\n", tosend[0]);
  69. send(sock, tosend[0], strlen(tosend[0]),0);
  70. bytes = -1;
  71. while(bytes == -1){printf("bytes = %d\n",bytes);
  72. bytes = recv(sock,buff,255,0);
  73. }
  74. buff[bytes] = '\0';
  75. printf("A receber -> %s\n", buff);
  76. //← 331 Please specify the password.
  77. if(strncmp("331",buff,3)!=0){
  78. printf("ERRO: expected:%s got: %s\n","331",buff);
  79. return -1;
  80. }
  81. strcpy(tosend[1], "pass ");
  82. strcat(tosend[1], Con.password);
  83. strcat(tosend[1], "\n");
  84. printf("A enviar -> %s\nCon.password = %s\n", tosend[1],Con.password);
  85. send(sock, tosend[1], strlen(tosend[1]), 0);
  86. bytes = -1;
  87. while(bytes == -1)
  88. bytes = recv(sock,buff,255,0);
  89. buff[bytes] = '\0';
  90. printf("A receber -> %s\n", buff);
  91. //<-- 230 Login successfull.
  92. if(strncmp("230",buff,3)!=0){
  93. printf("ERRO: expected:%s got: %s\n","230",buff);
  94. return -1;
  95. }
  96. }
  97. //TAMANHO DO FICHEIRO
  98. tosend[3] = calloc(256, sizeof(char));
  99. strcpy(tosend[3], "size ");
  100. strcat(tosend[3], Con.path);
  101. strcat(tosend[3], "\n");
  102. printf("A enviar -> %s\n", tosend[3]);
  103. send(sock, tosend[3], strlen(tosend[3]), 0);
  104. bytes = -1;
  105. while(bytes == -1)
  106. bytes = recv(sock,buff,255,0);
  107. buff[bytes] = '\0';
  108. printf("A receber -> %s\n", buff);
  109. //<-- 213 successfull.
  110. if(strncmp("213",buff,3)!=0){
  111. printf("ERRO: expected:%s got: %s\n","213",buff);
  112. return -1;
  113. }
  114. i=4;
  115. strcpy(temp, buff + i++);
  116. tamanhoFicheiro = atoi(temp);
  117. printf("TAMANHO (SIZE): %d\n", tamanhoFicheiro);
  118. //PASV
  119. printf("A enviar -> %s\n", "pasv");
  120. send(sock, "pasv\n",5, 0);
  121. bytes = -1;
  122. while(bytes == -1)
  123. bytes = recv(sock,buff,255,0);
  124. buff[bytes] = '\0';
  125. printf("A receber -> %s\n", buff);
  126. //<-- 227 Entering Passive Mode (192,168,50,138,179,4).
  127. if(strncmp("227",buff,3)!=0){
  128. printf("ERRO: expected:%s got: %s\n","227",buff);
  129. return -1;
  130. }
  131. printf("entrou\n");
  132. Con.lport = getLPort(buff);
  133. printf("PORT: %d\n", Con.lport);
  134. lsock = new_con(Con.ip,Con.lport);
  135. tosend[2] = calloc(256, sizeof(char));
  136. strcpy(tosend[2], "retr ");
  137. strcat(tosend[2], Con.path);
  138. strcat(tosend[2], "\n");
  139. send(sock, tosend[2], strlen(tosend[2]),0);
  140. bytes = -1;
  141. while(bytes == -1){printf("bytes = %d\n",bytes);
  142. bytes = recv(sock,buff,255,0);
  143. }
  144. buff[bytes] = '\0';
  145. printf("A receber -> %s\n", buff);
  146. // //← 150 Opening BINARY mode data connection for PATH (XXXX bytes).
  147. if(strncmp("150",buff,3)!=0){
  148. printf("ERRO: expected:%s got: %s\n","150",buff);
  149. return -1;
  150. }
  151. i = strlen(Con.path);
  152. while(i--)
  153. if(Con.path[i] == '/')
  154. Con.path += i+1;
  155. FILE *file = fopen(Con.path, "w");
  156. //buffer com tamanho do ficheiro
  157. dataBuff = calloc(tamanhoFicheiro, sizeof(char));
  158. if(data == 0)
  159. return -1;
  160. i=0;
  161. do{
  162. j = 0;
  163. bytes = -1;
  164. while(bytes == -1){
  165. bytes = recv(lsock, dataBuff, tamanhoFicheiro, 0);
  166. size = bytes;
  167. printf("Bytes: %d\n", bytes);
  168. if(bytes != -1){
  169. bytesTotal += bytes;
  170. while(j<bytes)
  171. fprintf(file,"%c", dataBuff[j++]);
  172. }
  173. i++;
  174. }
  175. }while(bytesTotal != tamanhoFicheiro);
  176. i=0;
  177. send(sock, "quit\n",5, 0);
  178. close(sock);
  179. close(lsock);
  180. //Con.path
  181. fclose(file);
  182. return 0;
  183. }
  184. int new_con(char* host_ip, int port){
  185. int sockfd;
  186. struct sockaddr_in server_addr;
  187. /*server address handling*/
  188. bzero((char*)&server_addr,sizeof(server_addr));
  189. server_addr.sin_family = AF_INET;
  190. server_addr.sin_addr.s_addr = inet_addr(host_ip); /*32 bit Internet address network byte ordered*/
  191. server_addr.sin_port = htons(port); /*server TCP port must be network byte ordered */
  192. /*open an TCP socket*/
  193. if ((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0) {
  194. perror("socket()");
  195. return -1;
  196. }
  197. /*connect to the server*/
  198. if(connect(sockfd,(struct sockaddr *)&server_addr, sizeof(server_addr)) < 0){
  199. perror("connect()");
  200. return -1;
  201. }
  202. /*send a string to the server*/
  203. return sockfd;
  204. }
  205. char* getIP(char* host){
  206. struct hostent *h;
  207. /*
  208. struct hostent {
  209. char *h_name; Official name of the host.
  210. char **h_aliases; A NULL-terminated array of alternate names for the host.
  211. int h_addrtype; The type of address being returned; usually AF_INET.
  212. int h_length; The length of the address in bytes.
  213. char **h_addr_list; A zero-terminated array of network addresses for the host.
  214. Host addresses are in Network Byte Order.
  215. };
  216. #define h_addr h_addr_list[0] The first address in h_addr_list.
  217. */
  218. if ((h=gethostbyname(host)) == NULL) {
  219. herror("gethostbyname");
  220. return NULL;
  221. }
  222. return inet_ntoa(*((struct in_addr *)h->h_addr));
  223. }
  224. int getArgs(char* arg){
  225. //arg = ftp://[<user>:<password>@]<host>/<url-path>
  226. //0 - regex para fazer match a ftp://
  227. //1 - regex para fazer match a /username:
  228. //2 - regex para fazer match a :username@
  229. //3 - regex para fazer match a host_name/
  230. //4 - regex para fazer match an ip
  231. //5 - regex para fazer match a path
  232. char **regex;
  233. char **match;
  234. char *temp=0;
  235. int i = 6;
  236. int offset;
  237. regex_t re;
  238. char buf[256];
  239. regmatch_t pmatch[100];
  240. int status;
  241. char *ps;
  242. int eflag;
  243. regex = (char**)calloc(6, sizeof(char*));
  244. regex[0] = (char*)calloc(8, sizeof(char));
  245. regex[1] = (char*)calloc(20, sizeof(char));
  246. regex[2] = (char*)calloc(20, sizeof(char));
  247. regex[3] = (char*)calloc(95, sizeof(char));
  248. regex[4] = (char*)calloc(104, sizeof(char));
  249. regex[5] = (char*)calloc(34, sizeof(char));
  250. strcpy(regex[0],"^ftp://");
  251. strcpy(regex[1],"/[a-zA-Z0-9]{1,12}:");
  252. strcpy(regex[2],":[a-zA-Z0-9]{1,12}@");
  253. strcpy(regex[3],"(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\\-]*[a-zA-Z0-9])\\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\\-]*[A-Za-z0-9])/");
  254. strcpy(regex[4],"(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])");
  255. strcpy(regex[5],"(/[a-zA-Z0-9_\\-]+)+\\.[a-zA-Z0-9]+$");
  256. match = (char**)calloc(6,sizeof(char*));
  257. // printf("\nmatch = %d\n",match);
  258. // printf("\n\n\n");
  259. while(i--){
  260. if((status = regcomp( &re, regex[5-i], REG_EXTENDED))!= 0){
  261. regerror(status, &re, buf, 120);
  262. return -1;
  263. }
  264. ps = arg;
  265. eflag = 0;
  266. if( status = regexec( &re, ps, 1, pmatch, eflag)== 0){
  267. offset = pmatch[0].rm_eo-pmatch[0].rm_so;
  268. match[5-i] = (char*)calloc(offset,sizeof(char));
  269. strncpy(match[5-i],ps+pmatch[0].rm_so,offset);
  270. }
  271. regfree( &re);
  272. }
  273. if(match[0] != 0) //começa com ftp://?
  274. if(match[5]!=0){ //tem path?
  275. Con.path = (char*)calloc( strlen(match[5])-1, sizeof(char));
  276. strncpy(Con.path, match[5]+1, strlen(match[5])-1);
  277. } else return -1; //não tem! logo não se pode fazer download
  278. else return -1; //o arg não está na forma necessaria
  279. if((match[1]!=0) && (match[2]!=0)){ //tem username e password?
  280. Con.username = (char*)calloc( strlen(match[1])-2, sizeof(char));
  281. Con.password = (char*)calloc( strlen(match[2])-1, sizeof(char));
  282. strncpy(Con.username, match[1]+1, strlen(match[1])-2);
  283. strncpy(Con.password, match[2]+1, strlen(match[2])-2);
  284. } else {
  285. Con.username = 0;
  286. Con.password = 0;
  287. }
  288. if((match[3]!=0) && (match[4]==0)){//tem hostname mas ip não?
  289. Con.ip = (char*)calloc(4*3+3, sizeof(char));
  290. temp = (char*)calloc( strlen(match[3]), sizeof(char));
  291. strncpy( temp, match[3], strlen(match[3])-1 );
  292. //match[4]-> null => uso-o como uma var temp para obter o ip do hostname
  293. match[4] = getIP(temp);
  294. strncpy(Con.ip, match[4], strlen(match[4]));
  295. match[4] = 0;
  296. } else{
  297. Con.ip = (char*)calloc(4*3+3, sizeof(char));
  298. strncpy(Con.ip, match[4], strlen(match[4]));
  299. }
  300. i=6;
  301. //limpar apontadores
  302. while(--i){
  303. free(regex[i]);
  304. if(match[i]!=0)
  305. free(match[i]);
  306. }
  307. free(regex);
  308. free(match);
  309. if(temp!=0)
  310. free(temp);
  311. return 1; //é correcto
  312. }
  313. int getLPort(char* buff){
  314. char regex[] = "([0-9]{1,3})";
  315. char** res;
  316. int status,i=0, port, offset;
  317. char* ps;
  318. regex_t re;
  319. char buf[256];
  320. regmatch_t pmatch[100];
  321. if((status = regcomp( &re, regex, REG_EXTENDED))!= 0){
  322. regerror(status, &re, buf, 120);
  323. return -1;
  324. }
  325. ps = buff;
  326. res = (char**) calloc(9,sizeof(char*));
  327. status=1;
  328. printf("ps : %s", ps);
  329. while(status!=0){
  330. if( status = regexec( &re, ps, 1, pmatch, 0) == 0){
  331. //pmatch[0].rm_eo indice de start
  332. //pmatch[0].rm_eo indice de end
  333. offset = pmatch[0].rm_eo - pmatch[0].rm_so;
  334. res[i] = (char*) calloc(offset,sizeof(char));
  335. strncpy(res[i], ps+pmatch[0].rm_so, offset);
  336. ps += pmatch[0].rm_eo;
  337. i++;
  338. }
  339. }
  340. port = atoi(res[i-2])*256 + atoi(res[i-1]);
  341. return port;
  342. }