Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Very very basic FTP by Basshunter
- #if defined ftp_included
- #endinput
- #endif
- #define ftp_included
- #pragma library ftp
- #include <a_samp>
- #include <socket>
- #tryinclude <sscanf2>
- #undef INVALID_SOCKET
- #define INVALID_SOCKET Socket:(-1) // warning miatt
- #define INVALID_FTP_ID -1
- #define MAX_FTP 255
- #define MAX_PATH_LEN 255
- #define MAX_USER_LEN 32
- #define MAX_PASS_LEN 32
- #define MAX_IPV4_LEN 15 // 4*3 szám + 3 pont
- #define NO_REASON 0
- #define NEED_ACCOUNT_FOR_LOGIN 1
- #define USERNAME_OK_NEED_PASSWORD 2
- #define INVALID_USERNAME_OR_PASSWORD 3
- #define CONNECTION_TIMED_OUT 4
- #define NOT_LOGGED_IN 5
- forward OnFTPConnected(ftpId);
- forward OnFTPDisconnected(ftpId, reason);
- forward OnFTPReceiveCode(ftpId, code);
- forward OnFTPFileNotFound(ftpId, file[]);
- forward OnFileDownloaded(ftpId, file[], savedAs[]);
- enum ftpEnum {
- bool:Active,
- bool:Connected,
- bool:Downloading,
- bool:PasswordGived,
- Socket:SocketId,
- Socket:DataSocketId,
- File[MAX_PATH_LEN],
- SaveAs[MAX_PATH_LEN]
- }
- new ftpData[MAX_FTP][ftpEnum];
- stock CreateFTP(host[], port, user[] = "", pass[] = "") {
- new ftpId = 0;
- for (; ftpId < MAX_FTP; ftpId++) if (!ftpData[ftpId][Active]) break;
- if (ftpId == MAX_FTP) return INVALID_FTP_ID;
- ftpData[ftpId][SocketId] = socket_create(TCP);
- ftpData[ftpId][DataSocketId] = socket_create(TCP);
- if (is_socket_valid(ftpData[ftpId][SocketId]) && is_socket_valid(ftpData[ftpId][DataSocketId])) {
- socket_connect(ftpData[ftpId][SocketId], host, port);
- new formatstring[256] = "";
- if (strlen(user) > 0) {
- format(formatstring, sizeof(formatstring), "USER %s\r\n", user);
- }
- if (strlen(pass) > 0) {
- format(formatstring, sizeof(formatstring), "%sPASS %s\r\n", formatstring, pass);
- ftpData[ftpId][PasswordGived] = true;
- }
- else ftpData[ftpId][PasswordGived] = false;
- format(formatstring, sizeof(formatstring), "%sCWD /\r\nPWD\r\n", formatstring);
- socket_send(ftpData[ftpId][SocketId], formatstring, strlen(formatstring));
- ftpData[ftpId][Active] = true;
- ftpData[ftpId][Connected] = false;
- ftpData[ftpId][Downloading] = false;
- ftpData[ftpId][File][0] = '\0';
- ftpData[ftpId][SaveAs][0] = '\0';
- return ftpId;
- }
- return INVALID_FTP_ID;
- }
- stock DestroyFTP(ftpId, reason = NO_REASON) {
- if (!ftpData[ftpId][Active]) return 1;
- if (is_socket_valid(ftpData[ftpId][SocketId])) {
- socket_send(ftpData[ftpId][SocketId], "QUIT\r\n", strlen("QUIT\r\n"));
- socket_destroy(ftpData[ftpId][SocketId]);
- }
- if (is_socket_valid(ftpData[ftpId][DataSocketId])) {
- socket_send(ftpData[ftpId][DataSocketId], "QUIT\r\n", strlen("QUIT\r\n"));
- socket_destroy(ftpData[ftpId][DataSocketId]);
- }
- ftpData[ftpId][Connected] = false;
- ftpData[ftpId][File][0] = '\0';
- ftpData[ftpId][SaveAs][0] = '\0';
- ftpData[ftpId][Active] = false;
- CallRemoteFunction("OnFTPDisconnected", "ii", ftpId, reason);
- return 0;
- }
- stock DownloadFTP(ftpId, file[], saveAs[], bool:binary = false) {
- // Mondanám, hogy a letöltés még szebb lenne pl egy queue-val de m1 :D
- if (!ftpData[ftpId][Active] || ftpData[ftpId][Downloading]) return 0;
- memcpy(ftpData[ftpId][File], file, 0, MAX_PATH_LEN * 4, MAX_PATH_LEN);
- memcpy(ftpData[ftpId][SaveAs], saveAs, 0, MAX_PATH_LEN * 4, MAX_PATH_LEN);
- new formatstring[128];
- format(formatstring, sizeof(formatstring), "TYPE %c\r\nPASV\r\n", binary ? 'I' : 'A');
- socket_send(ftpData[ftpId][SocketId], formatstring, strlen(formatstring));
- ftpData[ftpId][Downloading] = true;
- return 1;
- }
- public onSocketAnswer(Socket:id, data[], data_len) {
- // FTP id behatárolása
- new
- bool:dataSocket = false,
- ftpId = 0;
- for (; ftpId < MAX_FTP; ftpId++) {
- if (ftpData[ftpId][SocketId] == id) break;
- if (ftpData[ftpId][DataSocketId] == id) {
- dataSocket = true;
- break;
- }
- }
- if (ftpId == INVALID_FTP_ID) return 1;
- if (!ftpData[ftpId][Connected] && !ftpData[ftpId][PasswordGived]) {
- CallRemoteFunction("OnFTPConnected", "i", ftpId);
- ftpData[ftpId][Connected] = true;
- }
- if (dataSocket) {
- if (ftpData[ftpId][File][0] != '\0') {
- //printf("[FTP #%i DATA] %s", ftpId, data);
- new File:downloaded = fopen(ftpData[ftpId][SaveAs], io_write);
- //fwrite(downloaded, data);
- //for (new i = 0; i < data_len; i++) printf("%i", getarg(1,i));
- for (new i = 0; i < data_len; i++) {
- fputchar(downloaded, data[i] & 255, false);
- //printf("%i", data[i] & 255);
- }
- fclose(downloaded);
- new tmpFile[MAX_PATH_LEN], tmpSaveAs[MAX_PATH_LEN];
- format(tmpFile, MAX_PATH_LEN, ftpData[ftpId][File]);
- format(tmpSaveAs, MAX_PATH_LEN, ftpData[ftpId][SaveAs]);
- ftpData[ftpId][File][0] = '\0';
- ftpData[ftpId][SaveAs][0] = '\0';
- ftpData[ftpId][Downloading] = false;
- CallRemoteFunction("OnFileDownloaded", "iss", ftpId, tmpFile, tmpSaveAs);
- }
- }
- else {
- new File:temp = ftemp();
- fwrite(temp, data);
- fseek(temp, 0, seek_start); // fájl elejére ugrás
- new line[256];
- // Soronként olvasás...
- while (fread(temp, line, sizeof(line)) && ftpData[ftpId][Active]) {
- new code = GetFTPCode(line);
- switch (code) {
- // https://en.wikipedia.org/wiki/List_of_FTP_server_return_codes
- // Alkalmazva a teljesség igénye nélkül... :D
- case 227: {
- new host[MAX_IPV4_LEN], port;
- GetIPAndPort(line, host, MAX_IPV4_LEN, port);
- if (port) {
- printf("[FTP #%i] Szerver altal felkinalt port: %s:%i", ftpId, host, port);
- ftpData[ftpId][DataSocketId] = socket_create(TCP);
- if (is_socket_valid(ftpData[ftpId][DataSocketId])) {
- socket_connect(ftpData[ftpId][DataSocketId], host, port);
- if (strlen(ftpData[ftpId][File])) {
- format(line, sizeof(line), "RETR %s\r\n", ftpData[ftpId][File]);
- socket_send(ftpData[ftpId][SocketId], line, strlen(line));
- }
- }
- }
- }
- // 230 User logged in
- case 230: {
- if (!ftpData[ftpId][Connected] && ftpData[ftpId][PasswordGived]) {
- CallRemoteFunction("OnFTPConnected", "i", ftpId);
- ftpData[ftpId][Connected] = true;
- }
- }
- // 331 User name okay, need password.
- case 331: if (!ftpData[ftpId][PasswordGived]) DestroyFTP(ftpId, USERNAME_OK_NEED_PASSWORD);
- // 332 Need account for login.
- case 332: DestroyFTP(ftpId, NEED_ACCOUNT_FOR_LOGIN);
- // 421 Connection timed out
- case 421: DestroyFTP(ftpId, CONNECTION_TIMED_OUT);
- // 430 Invalid username or password
- case 430: DestroyFTP(ftpId, INVALID_USERNAME_OR_PASSWORD);
- // 530 Not logged in
- case 530: DestroyFTP(ftpId, NOT_LOGGED_IN);
- // 550 File not found
- case 550: {
- CallRemoteFunction("OnFTPFileNotFound", "is", ftpId, ftpData[ftpId][File]);
- //printf("[FTP #%i] Fájl nem található: %s", ftpId, ftpData[ftpId][File]);
- ftpData[ftpId][File][0] = '\0';
- ftpData[ftpId][SaveAs][0] = '\0';
- ftpData[ftpId][Downloading] = false;
- }
- default: CallRemoteFunction("OnFTPReceiveCode", "ii", ftpId, code);
- }
- }
- fclose(temp);
- }
- return 1;
- }
- // Segédfüggvények...
- // Megmondja, milyen szám van a sztring elején
- stock GetFTPCode(string[]) {
- new code;
- for (new i = 0; '0' <= string[i] <= '9'; i++) code = code * 10 + string[i] - '0';
- return code;
- }
- // A PASV által adott válaszból megmondja a hostot és a portot
- stock GetIPAndPort(PASVResponse[], host[], len, &port) {
- // www.serv-u.com/respcode.asp?resp=227
- new h[4], p[2];
- // Az sscanf2 pluginban van ilyen alias így biztos nem lesz összekeverve a régebbi pawn verzióval
- #if defined unformat
- // Van egy újranyitott topikja a nemzetközi fórumon, ott néztem utána hogy kell használni
- // P<elválasztó karakterek>, {kihagyás}, a<típus>[méret] tömb
- unformat(PASVResponse, "P<(),>{s[255]}a<i>[4]a<i>[2]", h, p);
- #else
- // Nagyon nagyon alap, nagyon nagyon feltéve, hogy jó a bemenet! :D
- new bool:openBracket = false, delims = 0, ch, i = 0;
- while ((ch = PASVResponse[i++])) {
- switch(ch) {
- case '(': openBracket = true;
- case ',': delims++;
- case ')': if (openBracket) break;
- case '0'..'9': {
- if (!openBracket) continue;
- if (delims < 4) h[delims] = h[delims] * 10 + ch - '0';
- else p[delims-4] = p[delims-4] * 10 + ch - '0';
- }
- }
- }
- #endif
- format(host, len, "%i.%i.%i.%i", h[0], h[1], h[2], h[3]);
- port = (p[0] * 256) + p[1];
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement