Ir al contenido


Foto

Presentación Android (~ashot)


  • Por favor identifícate para responder
23 respuestas en este tema

#1 cHackAll

cHackAll

    Advanced Member

  • Administrador
  • 599 mensajes

Escrito 13 febrero 2012 - 08:09

Hice un programa el cual debía presentar al gerente de la empresa donde trabajo, presentación que tuve que posponer porque la cámara Web que planeaba usar para poder mostrar la aplicación con un proyector, obtenía malas imágenes por la ausencia de luz.

Tras varios intentos encontré éste interesante utilitario que desgraciadamente tampoco pude hacer funcionar. Revisando su forma de instalación leí que si el utilitario “android-sdks\tools\ddms” funciona también ashot, entonces decidí revisar a “ddmlib” (clase con la cual ddms funciona).

Preocupado por el hecho de tener que instalar Java y Android SDK en cualquier equipo en el que haga la presentación y con la soga al cuello decidí hacer yo mismo un programa sencillo para realizar la presentación de mi software.


Es básico; permite mover la ventana, cerrarla con Alt+F4,

Imagen Enviada

Y rotar la imagen con Click derecho:

Imagen Enviada

Adjunto programa y fuente, espero les sea util

Archivos adjuntos


  • 0

#2 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 13 febrero 2012 - 08:21

Excelente amigo, que bueno verte de nuevo por estos lares, cuando tenga un tiempecito lo reviso, gracias de nuevo !!.

Saludos.
  • 0

#3 fredycc

fredycc

    Advanced Member

  • Moderadores
  • PipPipPip
  • 874 mensajes
  • LocationOaxaca, México

Escrito 13 febrero 2012 - 08:27

Hola cHackAll, a mi el Avira me mando esto:

A virus or unwanted program was found in the HTTP data of the requested page.


Seguro me quieres hackear  :D

Saludos
  • 0

#4 cHackAll

cHackAll

    Advanced Member

  • Administrador
  • 599 mensajes

Escrito 13 febrero 2012 - 08:34

...Seguro me quieres hackear  :D...


Si quisiera no lo haría de una forma que desprestigie mis aportes a la comunidad.

Algunos antivirus solo aparentan hacer un buen trabajo, descarga el comprimido, recontra desinfecta con alcohol recontra-hiper-etílico la fuente... jaja y compilalo por ti mismo. Espero sea util e ilustrativo, Saludos!
  • 0

#5 Caral

Caral

    Advanced Member

  • Moderador
  • PipPipPip
  • 4.266 mensajes
  • LocationCosta Rica

Escrito 13 febrero 2012 - 09:34

Hola
Vamos amigo, recetando alcohol el lunes en la mañana.....  (b)
Gracias por el aporte, no lo bajare por que seguro no lo entenderé pero estoy seguro que a mas de uno le servirá. (y)
Saludos
PD: Es un gusto leerte, aunque sea de vez en cuando, no te pierdas tanto, recuerda que aquí tienes familia. (y)
  • 0

#6 felipe

felipe

    Advanced Member

  • Administrador
  • 3.283 mensajes
  • LocationColombia

Escrito 13 febrero 2012 - 10:07

Si quisiera no lo haría de una forma que desprestigie mis aportes a la comunidad.


Jaja :D no lo dudo (y)

buen aporte para complementar al estudio del androide.


Saludos!
  • 0

#7 seoane

seoane

    Advanced Member

  • Administrador
  • 1.259 mensajes
  • LocationEspaña

Escrito 13 febrero 2012 - 10:40

Muy Bueno  (y) .

Aunque no estaría mal que explicaras un poco como funciona, o donde encontrar información.

Entiendo que lanzas el servidor adb y te comunicas con el por sockets, pero me quedo ahí  :(

Gracias
  • 0

#8 fredycc

fredycc

    Advanced Member

  • Moderadores
  • PipPipPip
  • 874 mensajes
  • LocationOaxaca, México

Escrito 13 febrero 2012 - 10:43

...Seguro me quieres hackear  :D...


Si quisiera no lo haría de una forma que desprestigie mis aportes a la comunidad.

Algunos antivirus solo aparentan hacer un buen trabajo, descarga el comprimido, recontra desinfecta con alcohol recontra-hiper-etílico la fuente... jaja y compilalo por ti mismo. Espero sea util e ilustrativo, Saludos!


Jajajaa era broma  :D, esta interesante el tema, además que me empiezo a interesar por Android.


PD. mmm pero pudieste usurpar el nombre de cHackAll para pasar desapercibido e iniciar el ataque, jajajaja broma

saludos
  • 0

#9 cHackAll

cHackAll

    Advanced Member

  • Administrador
  • 599 mensajes

Escrito 13 febrero 2012 - 01:09

Muy Bueno  (y) .

Aunque no estaría mal que explicaras un poco como funciona, o donde encontrar información.

Entiendo que lanzas el servidor adb y te comunicas con el por sockets, pero me quedo ahí  :(

Gracias


El Driver se comunica con el Dispositvo.
ADB se comunica con el Driver (ADB es un puente de comunicación con fines de depuración).
ADB escucha en el puerto por defecto 5037.
El protocolo de comunicación con ADB no es binario, es mas bien una secuencia de comandos con respuestas como "OKAY" ó "FAIL" (STAT,RECV,DATA,DONE,SEND,...)

Cuando ADB recibe "host:track-devices" retorna un listado de los Dispositivos a los cuales se puede acceder, retorna una lista ID[tab]TYPE[cr].
Cuando ADB recibe "host:transport:" + ID, establece una conexión con el Dispositivo identificado por ID.
Cuando ADB recibe "framebuffer:" envía un pantallazo del Dispositivo.
El pantallazo que ADB envía al cliente está compuesto por un cabezal y el vector de pixeles.
Existen dos versiones de cabezales conocidos, el 16 (modo compatibilidad) y el 1.
El modo compatibilidad consta del tamaño de buffer y el ancho por el alto del mismo, obviando que la resolución es un estándar de 16 Bits 565.
Ver también

Salud!!
  • 0

#10 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.448 mensajes
  • LocationMéxico

Escrito 13 febrero 2012 - 01:15

:( baje el archivo y no puedo descompactarlo

!  F:\ashot.zip: The archive is either in unknown format or damaged



:(

Saludos
  • 0

#11 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.448 mensajes
  • LocationMéxico

Escrito 13 febrero 2012 - 01:18

El mensaje anterior fue con Winrar con el descompactador de Windows me dice

---------------------------
Carpetas comprimidas (en zip)
---------------------------
Introduzca el último disco del conjunto multivolumen

y haga clic en Aceptar.
---------------------------
Aceptar  Cancelar 
---------------------------


Saludos

  • 0

#12 cHackAll

cHackAll

    Advanced Member

  • Administrador
  • 599 mensajes

Escrito 13 febrero 2012 - 01:28



delphi
  1. program ashot; // by cHackAll
  2.  
  3. uses Windows, WinSock, Messages;
  4.  
  5. function _itoa(Value: Integer; lpBuffer: PChar; Radix: Integer): PChar; cdecl external 'ntdll';
  6. function strstr(str, strSearch: PChar): PChar; cdecl external 'ntdll';
  7.  
  8. type
  9. argb = packed record
  10.   b, g, r, a: Byte;
  11. end;
  12.  
  13. var
  14. Value, Index, hWnd, Version, hScreen, hCanvas, hdibCanvas, w, h, y, x, Pixel: Integer;
  15. lpBuffer, lpType, lpDevice: PChar;
  16. Buffer, Device: ShortString;
  17. WndClass: TWndClass;
  18. WSData: TWSAData;
  19. Msg: TMsg;
  20.  
  21. Header: packed record
  22.   bpp, size, width, height, red_offset, red_length, blue_offset, blue_length, green_offset, green_length, alpha_offset, alpha_length: Integer;
  23. end;
  24.  
  25. name: TSockAddrIn;
  26. hSocket: Integer;
  27. lpCanvas: PIntegerArray;
  28. lpPixel: Pointer;
  29.  
  30. PaintStruct: TPaintStruct;
  31. isDown, isSwap: LongBool;
  32. BitmapInfo: TBitmapInfo;
  33. Pos, Cursor: TPoint;
  34.  
  35. function read(const lpBuffer: PChar; const uBytes: Integer): Integer;
  36. var Count: Integer;
  37. begin
  38. Result := 0;
  39. while Result < uBytes do
  40.   begin
  41.   Count := recv(hSocket, lpBuffer[Result], uBytes - Result, 0);
  42.   if Count > 0 then Inc(Result, Count) else Break;
  43.   end;
  44. end;
  45.  
  46. function write(const lpBuffer: PChar): LongBool;
  47. var len: Integer;
  48. begin
  49. len := lstrlen(lpBuffer);
  50. if len = 0 then Inc(len);
  51. Result := (send(hSocket, lstrcat(_itoa(len or $10000, @Buffer, 16), lpBuffer)[1], len + 4, 0) = len + 4) and
  52.           (read(@Result, SizeOf(Result)) = SizeOf(Result)) and
  53.           (Integer(Result) = PInteger(PChar('OKAY'))^);
  54. end;
  55.  
  56. begin
  57. CreateMutex(nil, False, 'nil');
  58. if GetLastError <> 0 then Exit;
  59. WinExec('adb start-server', SW_HIDE);
  60.  
  61. WndClass.lpszClassName := 'nil';
  62. WndClass.lpfnWndProc := @DefWindowProc;
  63. WndClass.hCursor := CreateCursor(HInstance, 5, 5, 9, 9, PChar(#255#255#255#255#255#255#255#255#247#255#255#255#255#255#255#255#255#255), PChar(#8#8#8#8#8#8#28#28#247#128#28#8#8#8#8#8#8#8));
  64. hWnd := CreateWindowEx(WS_EX_TOOLWINDOW or WS_EX_TOPMOST or WS_EX_LAYERED, Ptr(RegisterClass(WndClass)), nil, WS_POPUP, 0, 0, 0, 0, 0, 0, HInstance, nil);
  65. SetLayeredWindowAttributes(hWnd, 0, 232, LWA_ALPHA);
  66. isDown := False;
  67. isSwap := False;
  68.  
  69. WSAStartup($0101, WSData);
  70. name.sin_family := AF_INET;
  71. name.sin_port := htons(5037);
  72. name.sin_addr.S_addr := inet_addr('127.0.0.1');
  73.  
  74. with BitmapInfo.bmiHeader do
  75.   begin
  76.   biSize := SizeOf(BitmapInfo.bmiHeader);
  77.   biPlanes := 1;
  78.   biBitCount := 32;
  79.   biCompression := BI_RGB;
  80.   end;
  81.  
  82. lstrcpy(@Device, 'host:transport:');
  83. repeat
  84.   Sleep($7F);
  85.   lpDevice := nil;
  86.   hSocket := socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
  87.   while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do
  88.   DispatchMessage(Msg);
  89.   if connect(hSocket, name, SizeOf(name)) = 0 then
  90.   if write('host:track-devices') then
  91.     while not Assigned(lpDevice) and (read(@Buffer, 4) = 4) do
  92.     if PInteger(@Buffer)^ <> PInteger(PChar('0000'))^ then
  93.       begin
  94.       Value := 0;
  95.       for Index := 0 to 3 do
  96.         begin
  97.         if Buffer[Index] > '9' then
  98.           Buffer[Index] := Chr((Ord(Buffer[Index]) or 32) - 39);
  99.         Value := (Value shl 4) or (Ord(Buffer[Index]) - Ord('0'));
  100.         end;
  101.       lpBuffer := @Buffer;
  102.       if read(lpBuffer, Value) = Value then
  103.         begin lpBuffer[Value] := #0;
  104.         while lpBuffer[0] <> #0 do
  105.           begin
  106.           Value := Length('host:transport:');
  107.           lpType := @Device;
  108.           repeat
  109.             if lpBuffer[0] > #10 then
  110.             Device[Value] := lpBuffer[0]
  111.             else
  112.             Device[Value] := #0;
  113.             Inc(Value);
  114.             if lpBuffer[0] = #9 then
  115.             lpType := @Device[Value]
  116.             else
  117.             if (lpBuffer[0] = #10) and (lstrcmpi(lpType, 'device') = 0) then
  118.               lpDevice := @Device;
  119.             Inc(lpBuffer);
  120.           until (lpBuffer[-1] = #10) or Assigned(lpDevice);
  121.           end;
  122.         end;
  123.       end;
  124.   closesocket(hSocket);
  125.   while Assigned(lpDevice) and IsWindow(hWnd) do
  126.   begin
  127.     hSocket := socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
  128.     if (connect(hSocket, name, SizeOf(name)) = 0) and write(lpDevice) and write('framebuffer:') and (read(@Version, SizeOf(Version)) = SizeOf(Version)) then
  129.     begin
  130.       Header.size := 0;
  131.       if Version = 16 then
  132.       begin
  133.         Header.bpp := 16;
  134.         read(@Header.size, 3 * 4);
  135.         Header.red_offset := 11;
  136.         Header.red_length := 5;
  137.         Header.green_offset := 5;
  138.         Header.green_length := 6;
  139.         Header.blue_offset := 0;
  140.         Header.blue_length := 5;
  141.         Header.alpha_offset := 0;
  142.         Header.alpha_length := 0;
  143.       end
  144.       else if Version = 1 then
  145.       read(@Header, 12 * 4);
  146.       if Header.size > 0 then
  147.       begin
  148.         lpBuffer := Ptr(LocalAlloc(0, Header.size));
  149.         if read(lpBuffer, Header.size) = Header.size then
  150.         with BitmapInfo.bmiHeader do
  151.         begin
  152.           w := Header.width;
  153.           h := Header.height;
  154.           if isSwap then
  155.           begin
  156.             w := h;
  157.             h := Header.width;
  158.           end;
  159.           if (biWidth <> w) or (biHeight <> h) then
  160.           begin
  161.             if biWidth * biHeight <> w * h then
  162.             begin
  163.               Pos.X := (GetSystemMetrics(SM_CXSCREEN) - w) div 2;
  164.               Pos.Y := (GetSystemMetrics(SM_CYSCREEN) - h) div 2;
  165.             end;
  166.             biWidth := w;
  167.             biHeight := h;
  168.             biSizeImage := w * 4 * h;
  169.             isDown := False;
  170.           end
  171.           else if isDown then
  172.           if (GetKeyState(VK_LBUTTON) and $80) = 0 then isDown := False else
  173.             begin
  174.             GetCursorPos(Pos);
  175.             Dec(Pos.X, Cursor.X);
  176.             Dec(Pos.Y, Cursor.Y);
  177.             end;
  178.  
  179.           hScreen := GetDC(0);
  180.           hdibCanvas := CreateDIBSection(hScreen, BitmapInfo, DIB_RGB_COLORS, Pointer(lpCanvas), 0, 0);
  181.           hCanvas := CreateCompatibleDC(0);
  182.           SelectObject(hCanvas, hdibCanvas);
  183.           ReleaseDC(0, hScreen);
  184.  
  185.           Dec(Header.width);
  186.           Dec(Header.height);
  187.           lpPixel := lpBuffer;
  188.           for y := 0 to Header.height do
  189.           for x := 0 to Header.width do
  190.             begin
  191.             Pixel := PCardinal(lpPixel)^;
  192.             Inc(Cardinal(lpPixel), Header.bpp div 8);
  193.             if isSwap then Value := y + (x * biWidth) else
  194.               Value := ((Header.height - y) * biWidth) + x;
  195.             with argb(lpCanvas[Value]) do
  196.               begin
  197.               r := ((Pixel shr Header.red_offset) and ((1 shl Header.red_length) - 1)) shl (8 - Header.red_length);
  198.               g := ((Pixel shr Header.green_offset) and ((1 shl Header.green_length) - 1)) shl (8 - Header.green_length);
  199.               b := ((Pixel shr Header.blue_offset) and ((1 shl Header.blue_length) - 1)) shl (8 - Header.blue_length);
  200.               a := ((Pixel shr Header.alpha_offset) and ((1 shl Header.alpha_length) - 1)) shl (8 - Header.alpha_length);
  201.               end;
  202.             end;
  203.           SetWindowPos(hWnd, HWND_TOPMOST, Pos.X, Pos.Y, w, h, SWP_SHOWWINDOW);
  204.           InvalidateRect(hWnd, nil, False);
  205.           BitBlt(BeginPaint(hWnd, PaintStruct), 0, 0, biWidth, biHeight, hCanvas, 0, 0, SRCCOPY);
  206.           EndPaint(hWnd, PaintStruct);
  207.           DeleteObject(hdibCanvas);
  208.           DeleteObject(hCanvas);
  209.         end;
  210.         LocalFree(Cardinal(lpBuffer));
  211.       end;
  212.     end
  213.     else
  214.     lpDevice := nil;
  215.     closesocket(hSocket);
  216.     while PeekMessage(Msg, 0, 0, 0, PM_REMOVE) do
  217.     if Msg.message = WM_RBUTTONDOWN then isSwap := not isSwap else
  218.     if Msg.message = WM_LBUTTONUP then isDown := False else
  219.     if Msg.message = WM_LBUTTONDOWN then
  220.       begin
  221.       GetCursorPos(Cursor);
  222.       Dec(Cursor.X, Pos.X);
  223.       Dec(Cursor.Y, Pos.Y);
  224.       isDown := True;
  225.       end
  226.     else
  227.       DispatchMessage(Msg);
  228.   end;
  229.   ShowWindow(hWnd, SW_HIDE);
  230. until not IsWindow(hWnd);
  231. end.


  • 0

#13 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.448 mensajes
  • LocationMéxico

Escrito 13 febrero 2012 - 01:39

Bueno, he compilado y ejecutado el programa, pero me imagino que debo tener mi Androide conectado con su cable USB ¿no?.

Como no traigo mi cable cuando regrese a casa lo pruebo :)

Saludos
  • 0

#14 cHackAll

cHackAll

    Advanced Member

  • Administrador
  • 599 mensajes

Escrito 13 febrero 2012 - 02:07

Bueno, he compilado y ejecutado el programa, pero me imagino que debo tener mi Androide conectado con su cable USB ¿no?.

Como no traigo mi cable cuando regrese a casa lo pruebo :)

Saludos


Si, funciona con el cable, en general requiere:

[Driver USB]
[adb.exe
AdbWinApi.dll
AdbWinUsbApi.dll]

Pero si no hay cable, hay varios paquetes en el Market que permiten comunicar al Demonio de depuración del dispositivo con el Depurador en sí, sobre una red Wireless. (busca “ADB”)

Me olvidama amigo seoane, la información la encuentras en el repositirio del Kernel del Android, específicamente en /platform/sdk/ddms/libs/ddmlib/src/com/android/ddmlib/AdbHelper.java.

Salud!!
  • 0

#15 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 13 febrero 2012 - 02:17

cHackAll, me parece un excelente trabajo. Ahora salgo de trabajar, cuando llegue a casa, si tengo un rato libre, lo pruebo.


Saludos.
  • 0

#16 root

root

    mister

  • Miembro Platino
  • PipPipPip
  • 529 mensajes
  • LocationMexico D.F:

Escrito 14 febrero 2012 - 10:02

bien mr

algun manual que recomiendes para iniciarme en android

y pregunta alguien sabe algo de la migracion de aplicaciones de android a black berry ?


  • 0

#17 seoane

seoane

    Advanced Member

  • Administrador
  • 1.259 mensajes
  • LocationEspaña

Escrito 14 febrero 2012 - 04:39

El Driver se comunica con el Dispositvo.
ADB se comunica con el Driver (ADB es un puente de comunicación con fines de depuración).
ADB escucha en el puerto por defecto 5037.
El protocolo de comunicación con ADB no es binario, es mas bien una secuencia de comandos con respuestas como "OKAY" ó "FAIL" (STAT,RECV,DATA,DONE,SEND,...)

Cuando ADB recibe "host:track-devices" retorna un listado de los Dispositivos a los cuales se puede acceder, retorna una lista ID[tab]TYPE[cr].
Cuando ADB recibe "host:transport:" + ID, establece una conexión con el Dispositivo identificado por ID.
Cuando ADB recibe "framebuffer:" envía un pantallazo del Dispositivo.
El pantallazo que ADB envía al cliente está compuesto por un cabezal y el vector de pixeles.
Existen dos versiones de cabezales conocidos, el 16 (modo compatibilidad) y el 1.
El modo compatibilidad consta del tamaño de buffer y el ancho por el alto del mismo, obviando que la resolución es un estándar de 16 Bits 565.
Ver también

Salud!!


Gracias amigo  (y) ... que pena que ahora no tenga tiempo para mirar esto con mas detenimiento  :(
  • 0

#18 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 17 febrero 2012 - 06:46

He probado la aplicación y aunque todavía debo estudiarla mas a fondo, me ha parecido genial.

Debo aclarar cuatro cosillas que me parecen de interés para evitar frustraciones a algunos:
1.- Debemos tener instalados los drivers del teléfono.
2.- Tenemos que tener en el path los archivos adb.exe, AdbWinApi.dll y AdbWinUsbApi.dll. Lo mejor es copiar ashot.exe en la carpeta donde estén los archivos mencionados.
3.- El teléfono debe estar configurado en modo depuración USB.
4.- La aplicación termina normalmente con Alt - F4.

He visto que el programa se bloquea si no se inicia ADB o si no responde el socket, para evitarlo me he permitido meter mano al código para añadir lo siguiente:
1.- Comprobación de que se ejecuta ADB, en caso contrario termina informando de ello.
2.- TimeOut de 5 segundos en la función recv para la respuesta del driver, en caso de fallo un diálogo preguntará si finalizamos la aplicación.

Los cambios del código son los siguientes:
Sustitución de WinExec('adb start-server', SW_HIDE) por:


delphi
  1. if WinExec('adb start-server', SW_HIDE) <= 31 then
  2. begin
  3.   MessageBox(0, 'I Can´t open adb.exe, the program will end.', 'ashot', MB_ICONINFORMATION);
  4.   exit;
  5. end;



y sustitución de recv por esta versión con TimeOut:


delphi
  1. function recv_t(hSocket: TSOCKET; var Buffer; Size, flags, TimeOut: integer): integer;
  2. var
  3.   FDSet: TFDSET;
  4.   Tv: timeval;
  5. begin
  6.   Result:= 0;
  7.   Tv.tv_sec:= TimeOut div 1000;
  8.   Tv.tv_usec:= TimeOut mod 1000;
  9.   FD_ZERO(FDSet);
  10.   FD_SET(hSocket, FDSet);
  11.   if select(0, @FDSet, 0, 0, @Tv) > 0 then
  12.     Result:= recv(hSocket, Buffer, Size, flags)
  13.   else
  14.     if MessageBox(hWnd, 'Communication failure, exit the program?', 'ashot', MB_OKCANCEL) = IDOK then
  15.       DestroyWindow(hWnd);
  16.  
  17. end;



Subo la versión modificada.
Espero que esta brava intrusión el tu código, cHackAll, no te moleste. Ya se que no  :).  Gracias de nuevo.


Saludos.
  • 0

#19 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.448 mensajes
  • LocationMéxico

Escrito 17 febrero 2012 - 07:20

He instalado los drivers de mi telefono, baje la nueva versión de Androide la 2.3.4, no tengo en ningún lado adb.exe ni las dll's :(

Por otro lado, ésta versión consume de forma exagerada la batería de mi celular, con la versión 2.2.2 me duraba todo el día la batería, ahora me dura medio día  8o| 8o| 8o| :@

Saludos
  • 0

#20 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 18 febrero 2012 - 12:23

He instalado los drivers de mi telefono, baje la nueva versión de Androide la 2.3.4, no tengo en ningún lado adb.exe ni las dll's :(

Lo descargas con el SDK de Android. Lee esto.
Esto también te puede interesar.

Por otro lado, ésta versión consume de forma exagerada la batería de mi celular, con la versión 2.2.2 me duraba todo el día la batería, ahora me dura medio día  8o| 8o| 8o| :@

¿No puedes hacer un downgrade?


Saludos.
  • 0




IP.Board spam blocked by CleanTalk.