Está en la página 1de 85

Hemos vuelto con entrevistas, con códigos y mucho ganas de enseñar; damos por terminada 

la sección de la Run Time Library de Eternal_Idol y veremos como poner a Windows a hacer 
lo que quiera de la mano de Cronodragon; esta edición se ha demorado por que he tenido un 
pequeño problema en la casa y es que se me inundo el fin de semana y hasta hoy se arreglo el 
chicharrón.

Espero disfruten leyendola tanto como yo hicé editandola!!!

Gracias a todos los lectores de Código Latino.
● Crear nuestra propia RunTime Library III (C)
● Autenticación en .NET I (VB.NET)
● Manejador de procesos I – Fundamentos (Sistemas Operativos)
● Entrevista a CHECMATED
● ZTIC TAC TOE (ABAP)
● Windows te ordeno que trabajes por mi (Autoit)
● Incluir documentos HTML o datos complejos (Perl)
● Entrevista a Daniel Bermudez
● Software para captura de Inventarios (PHP)
Crear nuestra propia RunTime Library (Tercera Parte)
Por Eternal_Idol
En la MSDN encontré algo interesante sobre la opción /ENTRY del linker: 

"Type a function name in the Entry­Point Symbol text box (or in the function argument on the command 
line). The function must be defined with the __stdcall calling convention. The parameters and return value 
must be defined as documented in the Win32 API for WinMain (for an .EXE file) or DllEntryPoint (for a 
DLL). It is recommended that you let the linker set the entry point so that the C run­time library is initialized 
correctly, and C++ constructors for static objects are executed." 

Vamos a probar un poco de código con objetos estáticos: 

ESTATICOS.CPP 
#include <windows.h>
void SayLong(int number)
{
  char Data[10];
  ltoa(number,Data,10);
  MessageBox(0,Data,"El Numero",0);
}

class Man
{
  public:
  Man()
  {
     SayLong(66);
  }

  ~Man()
  {
     SayLong(99);
  }
};

Man Jacinto;
Man Pedrito;

void main()
{

Compilando y linkeando este código con la Run Time Library por defecto conseguimos cuatro MessageBox, 
dos con 66 (el constructor) y dos con 99 (el destructor). 
Ahora tratamos de compilar y linkear con nuestra Run Time Library y nos encontramos con lo siguiente: 
estaticos.obj : error LNK2001: unresolved external symbol _atexit 
estaticos.exe : fatal error LNK1120: 1 unresolved externals 
Si vamos a la MSDN podemos ver que lo que hace esta función es ejecutar la función que le es pasada como 
parámetro al final del programa. Usando una estructura de pila (LIFO). 
Entonces qué nos detiene? Qué nos imposibilita crear una función simple como esa? Nada, manos a la obra 
señores. 

C_ATEXIT.CPP 
#include <malloc.h>
unsigned long *Funcs = 0;
int n_funcs = 0;

extern "C" int atexit(void (__cdecl *func)(void))
{
  if (!Funcs) { Funcs = (unsigned long*)malloc(1); }
  Funcs = (unsigned long*)realloc(Funcs,(n_funcs+1)*4);
  Funcs[n_funcs] = (unsigned long)func;
  n_funcs++;
  return 0; 
}

extern "C" void destructores()
{
  for (int x = n_funcs­1;x >= 0;x­­)
  {
    void (__cdecl *calla)(void) = (void (__cdecl *)(void))Funcs[x];
    calla();
  }
  free(Funcs);
}

Hermoso el código verdad? Cada vez que se llama a la función atexit() se comprueba si ya tiene valor la 
estructura donde vamos a guardar los punteros a las funciones. Se realloca la memoria necesaria y se le 
asigna al elemento actual el parámetro func. Siempre devolvemos cero que indica que no hubo ningún error. 

Pero este código hermoso que hace exactamente hasta ahora? Ir llenando una lista de punteros a funciones, 
perfecto pero nos falta algo muy importante, recordemos que atexit() crea una lista de funciones que van a ser 
llamadas al final del programa. El principio del programa es la función de ENTRADA (solo nos interesan 
main, WinMain y DllMain ya que si fuera otra no usaría la Run Time Library, ni la nuestra ni la de VC++) 
que sabemos como se ejecuta, la llamamos nosotros desde nuestra Run Time Library por lo tanto sabemos 
perfectamente cuando termina de ejecutarse; en la siguiente instrucción a la llamada a main() el programa 
debe ejecutar la lista de funciones de atexit() y limpiar el buffer utilizado. Estas dos cosas las hace la función 
destructores() que está también en C_ATEXIT.CPP. 

Ahora mismo podríamos compilar el programa ESTATICOS.CPP pero no pasaría nada, la compilación y el 
linkeo serían satisfactorios pero nuestro programa no haría absolutamente nada. 
La pregunta del millón, quién llama a la función atexit(): la propia Run Time Library la llama. Acertaron? No 
me mientan eh. 
Y cuando y porqué la llama? Porque el compilador le pasa el puntero del destructor al ejecutar el constructor, 
por lo tanto, al no tener implementado nuestro código para manejar los constructores estáticos no recibimos 
ninguna llamada a atexit() y destructores() se ejecuta sin ningún puntero al que llamar. 

Qué hace el compilador para decirnos que existen constructores de objetos estáticos? El compilador crea un 
función diferente para cada uno de los objetos estáticos (esto lo podemos comprobar viendo las direcciones 
que le pasa por cada objeto a atexit) y nos pasa dentro del ejecutable las 'etiquetas' (posición en el archivo) de 
esas funciones a ejecutarse. 

data_seg 
#pragma data_seg( ["section­name"[, "section­class"] ] ) 

Specifies the default section for data. For example: 

#pragma data_seg( "MY_DATA" ) 

causes data allocated following the #pragma statement to be placed in a section called MY_DATA. 

Data allocated using the data_seg pragma does not retain any information about its location. 

Estas secciones que se definen con #pragma data_seg son escritas por el linker dentro del ejecutable y tienen 
punteros,  a inicializadores de C, constructores de C++, pre­terminadores de C y terminadores de C  que 
forman tablas, estas se guardan en variables que tienen el comienzo y el fin de la tabla y son pasadas a una 
función llamada _initterm() que se encarga de llamar a todos esos punteros ejecutando su código. Esta es la 
forma en la que se llama a al constructor de un objeto estático. 

Nuestro nuevo C_MAIN.CPP: 
#include <malloc.h>
#include <string.h>
extern "C" int __argc = 1;
extern "C" char** __argv = 0;
extern "C" void __stdcall ExitProcess(unsigned long uExitCode);
extern "C" char* __stdcall GetCommandLineA(void);
extern int main(int argc, char *argv[],char *env[]);
extern "C" int __stdcall MessageBoxA(int a,char *b,char *c,unsigned int p);
typedef void (__cdecl *_PVFV)(void);

#pragma data_seg(".CRT$XIA")
_PVFV __xi_a[] = { 0 };

#pragma data_seg(".CRT$XIZ")
_PVFV __xi_z[] = { 0 };

#pragma data_seg(".CRT$XCA")
_PVFV __xc_a[] = { 0 };

#pragma data_seg(".CRT$XCZ")
_PVFV __xc_z[] = { 0 };
typedef void (* PFV)(void);
#pragma data_seg(".CRT$XPA")
PFV __xp_a = 0; /* C pre­terminators */

#pragma data_seg(".CRT$XPZ")
PFV __xp_z = 0;

#pragma data_seg(".CRT$XTA")
PFV __xt_a = 0; /* C terminators */

#pragma data_seg(".CRT$XTZ")
PFV __xt_z = 0;

extern "C" void __cdecl _initterm(_PVFV *, _PVFV *);
//__xi_a[], __xi_z[]; /* C initializers */
//__xc_a[], __xc_z[]; /* C++ initializers */
//__xp_a[], __xp_z[]; /* C pre­terminators */
//__xt_a[], __xt_z[]; /* C terminators */
extern "C" void destructores();

#define FALSE 0
#define TRUE 1

extern "C" void mainCRTStartup()
{
  char *parámetros = GetCommandLineA();
  char *temp = (char*)malloc(2048);
  memset(temp,0,2048);
  __argc = 0;
  __argv = (char**)malloc(4);
  char Except = FALSE;
  while(*parámetros)
  {
    if (*parámetros == 34)
    {
      if (Except == FALSE)
      {
        Except = TRUE;
      }
      else
      {
        Except = FALSE;
        if (strlen(temp) > 0)
        {
           __argv = (char**)realloc(__argv,4 * (__argc+1));
           __argv[__argc] = (char*)malloc(strlen(temp) + 1);
           memset(__argv[__argc],0,strlen(temp) + 1);
           strcpy(__argv[__argc],temp);
           strcpy(temp,"");
           __argc++; 
        }
      }
      parámetros++;
      continue;
   }

   if ( (*parámetros == 32) && (Except == FALSE) )
   { 
     if (strlen(temp) > 0)
     {
       __argv = (char**)realloc(__argv,4 * (__argc+1));
       __argv[__argc] = (char*)malloc(strlen(temp) + 1);
       memset(__argv[__argc],0,strlen(temp) + 1);
       strcpy(__argv[__argc],temp);
       strcpy(temp,"");
       __argc++; 
     }
   } 
   else
   {
     unsigned long pos = strlen(temp);
     temp[pos] = *parámetros;
     temp[pos+1] = 0;
   }
   parámetros++;
  }
  if (strlen(temp) > 0)
  {
    __argv = (char**)realloc(__argv,4 * (__argc+1));
    __argv[__argc] = (char*)malloc(strlen(temp) + 1);
    memset(__argv[__argc],0,strlen(temp) + 1);
    strcpy(__argv[__argc],temp);
    strcpy(temp,"");
    __argc++;
  } 
  free(temp);
  _initterm(__xi_a,__xi_z);
  _initterm(__xc_a,__xc_z);
  main(__argc,__argv,0);
  _initterm(&__xp_a,&__xp_z);
  _initterm(&__xt_a,&__xt_z);
  destructores();

  for (int y = 0;y < __argc;y++) { free(__argv[y]); }
  free(__argv);
  ExitProcess(0);
}

static void __cdecl _initterm(_PVFV *pfbegin,_PVFV *pfend)
{
  while (pfbegin < pfend)
  {
    if (*pfbegin) { (**pfbegin)(); }
    ++pfbegin;
  }
}
Este nuevo main define las diferentes secciones donde se encontrarán las benditas tablas, llama a las tablas de 
inicio justo antes que a main() y a las de terminaciones justo después, además de llamar a nuestra función 
destructores().   Las   tablas   son   procesadas   por   la   función   initterm()   que   recorre   la   tabla   de   punteros   a 
funciones, ejecutando cada uno de ellas, hasta encontrar un puntero nulo. 

Creamos nuestra libreria y ESTATICOS.EXE: 

cl /c *.cpp 
lib *.obj /out:clib.lib 
cl /c ESTATICOS.CPP 
link ESTATICOS.OBJ /NODEFAULTLIB USER32.LIB KERNEL32.LIB \CLIB\CLIB.LIB 
Ahora   si,   tenemos   el   mismo   comportamiento   que   con   la   Run   Time   Library   de   VC++   para   los   objetos 
estáticos. 

Un regalito en esta parte, vamos a ver como manejar las variables de entorno: 

C_MAIN.CPP 
#include <malloc.h>
#include <string.h>

//entorno
extern "C" int vars = 0;
extern "C" char** _environ = 0;
extern "C" char* __stdcall GetEnvironmentStrings(void);
extern "C" bool __stdcall FreeEnvironmentStringsA(char *block);
void __cdecl _envinit(void);
//parámetros
extern "C" int __argc = 1;
extern "C" char** __argv = 0;
extern "C" void __stdcall ExitProcess(unsigned long uExitCode);
extern "C" char* __stdcall GetCommandLineA(void);
extern int main(int argc, char *argv[],char *env[]);
extern "C" int __stdcall MessageBoxA(int a,char *b,char *c,unsigned int p);
typedef void (__cdecl *_PVFV)(void);

#pragma data_seg(".CRT$XIA")
_PVFV __xi_a[] = { 0 };
#pragma data_seg(".CRT$XIZ")
_PVFV __xi_z[] = { 0 };
#pragma data_seg(".CRT$XCA")
_PVFV __xc_a[] = { 0 };
#pragma data_seg(".CRT$XCZ")
_PVFV __xc_z[] = { 0 };
typedef void (* PFV)(void);
#pragma data_seg(".CRT$XPA")
PFV __xp_a = 0; /* C pre­terminators */
#pragma data_seg(".CRT$XPZ")
PFV __xp_z = 0;
#pragma data_seg(".CRT$XTA")
PFV __xt_a = 0; /* C terminators */
#pragma data_seg(".CRT$XTZ")
PFV __xt_z = 0;
extern "C" void __cdecl _initterm(_PVFV *, _PVFV *);
//__xi_a[], __xi_z[]; /* C initializers */
//__xc_a[], __xc_z[]; /* C++ initializers */
//__xp_a[], __xp_z[]; /* C pre­terminators */
//__xt_a[], __xt_z[]; /* C terminators */
extern "C" void destructores();

#define FALSE 0
#define TRUE 1

extern "C" void mainCRTStartup()
{
  char *parámetros = GetCommandLineA();
  char *temp = (char*)malloc(2048);
  memset(temp,0,2048);
  __argc = 0;
  __argv = (char**)malloc(4);
  char Except = FALSE;
  while(*parámetros)
  {
    if (*parámetros == 34)
    {
      if (Except == FALSE)
      {
        Except = TRUE;
      }
      else
      {
        Except = FALSE;
        if (strlen(temp) > 0)
        {
          __argv = (char**)realloc(__argv,4 * (__argc+1));
          __argv[__argc] = (char*)malloc(strlen(temp) + 1);
          memset(__argv[__argc],0,strlen(temp) + 1);
          strcpy(__argv[__argc],temp);
          strcpy(temp,"");
          __argc++; 
         }
       }
       parámetros++;
       continue;
    }

     if ( (*parámetros == 32) && (Except == FALSE) )
     { 
        if (strlen(temp) > 0)
       {
          __argv = (char**)realloc(__argv,4 * (__argc+1));
          __argv[__argc] = (char*)malloc(strlen(temp) + 1);
          memset(__argv[__argc],0,strlen(temp) + 1);
          strcpy(__argv[__argc],temp);
          strcpy(temp,"");
          __argc++; 
        }
      } 
      else
      {
         unsigned long pos = strlen(temp);
         temp[pos] = *parámetros;
         temp[pos+1] = 0;
      }
      parámetros++;
    }
    if (strlen(temp) > 0)
    {
       __argv = (char**)realloc(__argv,4 * (__argc+1));
       __argv[__argc] = (char*)malloc(strlen(temp) + 1);
       memset(__argv[__argc],0,strlen(temp) + 1);
       strcpy(__argv[__argc],temp);
       strcpy(temp,"");
       __argc++;
    } 
    free(temp);
    _initterm(__xi_a,__xi_z);
    _initterm(__xc_a,__xc_z);
    _envinit(); 
    main(__argc,__argv,_environ);
    _initterm(&__xp_a,&__xp_z);
    _initterm(&__xt_a,&__xt_z);
    destructores();

    for (int y = 0;y < __argc;y++) { free(__argv[y]); }
    free(__argv);
    for (int z = 0;z < vars;z++) 
    { 
      if (_environ[z]) { free(_environ[z]); }
    } 
    free(_environ);
    ExitProcess(0);
}

static void __cdecl _initterm(_PVFV *pfbegin,_PVFV *pfend)
{
while (pfbegin < pfend)
{
 if (*pfbegin) { (**pfbegin)(); }
 ++pfbegin;
}
}

void __cdecl _envinit(void)
{
char *var = GetEnvironmentStrings();
_environ = (char**)malloc(4);
while(*var)
{
 _environ = (char**)realloc(_environ,(vars + 1) * 4);
 _environ[vars] = (char*)malloc(strlen(var) + 1);
 memset(_environ[vars],0,strlen(var) + 1);
 strcpy(_environ[vars],var); 
 (char*)var += strlen((char*)var);
 (char*)var +=1;
 vars++;
}
FreeEnvironmentStringsA(var);
}

Esta nueva versión del C_MAIN.CPP incorpora la función _envinit, que cre la lista de variables de entorno y 
le pasa la variable _environ a la función main() de nuestro programa. 

Ahora vamos a implementar getenv y putenv: 

C_PUTENV.CPP 
#include <malloc.h>
#include <string.h>

extern "C" int vars;
extern "C" char** _environ;

bool compararPut(char *s1,const char *s2)
{
while(*s2)
{
 if (*s1 != *s2)
 {
 return false;
 }
 s1++;
 s2++;

return true;
}

extern "C" int putenv(const char *envstring)
{
for (int x = 0;x < vars;x++)
{
 if (!_environ[x]) { continue; }
 if (compararPut(_environ[x],envstring) == true)
 {
 char *ptr = (char*)envstring;
 while(*envstring)
 {
 if ( (*ptr == '=') && (*++ptr == 0) )
 {
 free(_environ[x]);
 _environ[x] = 0;
 return 0;
 } 
 ptr++; 
 } 
 strcpy(_environ[x],envstring); 
 return 0;
 }
}
_environ = (char**)realloc(_environ,(vars + 1) * 4);
_environ[vars] = (char*)malloc(strlen(envstring) + 1);
memset(_environ[vars],0,strlen(envstring) + 1);
strcpy(_environ[vars],envstring); 
vars++;
return 0;
}

C_GETENV.CPP 
#include <string.h>

extern "C" int vars;
extern "C" char** _environ;

bool compararGet(char *s1,const char *s2)
{
while(*s2)
{
 if (*s1 != *s2)
 {
 return false;
 }
 s1++;
 s2++;

if (*s1 == '=') { return true; }
return false;
}

extern "C" char *getenv(const char *varname)
{
for (int x = 0;x < vars;x++)
{
 if (!_environ[x]) { continue; }
 if (compararGet(_environ[x],varname) == true)
 {
 return (_environ[x]+strlen(varname)+1);
 }
}
return 0;
}

Podemos   probar   su   correcto   funcionamiento   con   cualquier   programa   que   use   el   parámetro   envp   o 
simplemente cambiando variables del entorno como TMP (el path de los archivos temporales). 

En la cuarta parte veremos como implementar las funciones de entrada y salida por consola. 

Saludos, 
Mariano. 
Autenticación en .NET (Primera Parte)
Por Piyey http://piyeycorp.wordpress.com/

¿Cuántos métodos de encriptación has probado para tus aplicaciones?
Hoy   en   día   sabemos   que   la   seguridad   en   nuestras   aplicaciones   es   un   factor   muy   importante.   Debemos 
brindarle   a   nuestros   clientes   o   a   la   empresa   donde   trabajemos   seguridad   en   las   aplicaciones   que 
desarrollamos. En este punto, hablaré sobre la seguridad ejemplificando el login de usuarios.
Existen muchos métodos de encriptación, en lo personal he probado un par de ellos. Cuando trabajé con php 
lo hacía con MD5, el cual php ya incluye una función para hacer un hash con este método. En otra ocasión 
utilicé  un  método  de encriptación el cual se tiene una “semilla” o “clave” con la cual encriptas  y  para 
desencriptar debes conocerla. También utilicé un algoritmo que te generaba una matriz aleatoria y te incluida 
la “semilla” dentro de la cadena encriptada, y el método de desencriptación la buscaba en la cadena y con ella 
lo desencriptaba.
Ahora, con .NET, en la ayuda que brinda pude ver que ellos ofrecen un método en el cual utilizan una “salt” 
el cual es el complemento de la contraseña. En uno de los métodos que utilizaba antes sería la semilla, pero 
en esos algoritmos la semilla iba en código duro, a diferencia del método que implementaré en este ejemplo, 
el cual se almacena en la BD.
Como ejemplo tomaremos un requerimiento inicial como el siguiente:
“Se necesita crear un módulo de seguridad en el que los usuarios tengan acceso con su nombre de usuario y  
contraseña. La seguridad deberá ser muy importante en este módulo. Los usuarios tendrán roles, un usuario  
podrá tener uno o más roles. Existirán permisos a las distintas funciones que se establecerán por rol o 
exclusivamente por usuario, esto es, un usuario podrá tener acceso a funciones heredadas desde sus roles o 
a funciones específicas asignadas a su cuenta exclusivamente.”
Acá mostraré un ejemplo de cómo implementar seguridad en la autenticación y autorización utilizando las 
Interfaces IIdentity & IPrincipal suplantando la identidad por defecto de la aplicación que es la identidad de 
Windows estableciendo My.User.CurrentPrincipal, el cual es una clase implementando la interface IPrincipal, 
en la cual crearemos una clase utilice dicha interface.

Creando una Identidad
A como se mencionó anteriormente, .NET utiliza las interfaces  IIdentity  y  IPrincipal  como base para la 
autenticación   y   autorización,   para   este   ejemplo   utilizaremos   la   autenticación   de   usuario   personalizada, 
haciendo uso de estas interfaces.

Implementando IIdentity.
Primeramente   crearemos   una   nueva   clase   (Menú   Proyecto­>Agregar   clase)   y   le   pondremos   el   nombre 
AplicationIIdentity.vb. Una vez creada se nos abrirá la ventana de código de dicha clase con el siguiente 
código:
Public Class ApplicationIIdentity
End Class
en la linea siguiente de public class ApplicationIIdentity escribiremos la siguiente linea:
Implements System.Security.Principal.IIdentity
y   al   final   presionamos   enter,  el   editor  de   código   crea   las   propiedades   que   se  deben   implementar   de   la 
interface utilizada, quedando de la siguiente manera:
Public Class AplicationIIdentity
  Implements System.Security.Principal.IIdentity
  Public ReadOnly Property AuthenticationType() As String Implements System.Security.Principal.IIdentity.AuthenticationType
    Get
    End Get
  End Property
  Public ReadOnly Property IsAuthenticated() As Boolean Implements System.Security.Principal.IIdentity.IsAuthenticated
    Get
    End Get
  End Property
  Public ReadOnly Property Name() As String Implements System.Security.Principal.IIdentity.Name
    Get
    End Get
  End Property
End Class

luego añadimos unos atributos privados para almacenar el nombre de usuario y un valor que indicará si el 
usuario está autenticado o no:
Private nameValue As String
Private authenticatedValue As Boolean
Private roleValue As ApplicationServices.BuiltInRole
en la propiedad AuthenticationType añadimos el siguiente código:
Return “Autenticación personalizada”
esto   indica   que   el   tipo   de   autenticación   es   personalizada   por   el   usuario   y   no   por   windows.
En la propiedad IsAuthenticated escribimos el siguiente código:
Return authenticatedValue
esta   propiedad   indica   si   el   usuario   está   autenticado   o   no   en   el   sistema.
Ahora escribimos el código para la propiedad Name, la cual retorna el nombre del usuario autenticado:
Return nameValue
En   nuestro   ejemplo,   los   usuarios   trabajarán   con   los   distintos   roles   asignados   a   su   cuenta,   por   lo   tanto 
crearemos una propiedad que retorne los roles del usuario:
Public ReadOnly Property Role() As ApplicationServices.BuiltInRole
 Get
   Return roleValue
 End Get
End Property
Cabe mencionar que en este ejemplo estamos tomando los roles de la enumeración BuiltInRole que viene en 
el espacio de nombres (namespace) ApplicationServices, puede quedar como proyecto del lector (pa que no 
boludee y lo deje todo al autor jejeje) escribir el código para trabajar con distintos roles que se implementen 
en su aplicación.
Bien,   hasta   acá   hemos   terminado   con  las   propiedades   que   deben   implementarse   por  ley   de   la   interface 
utilizada, añadiendo una propiedad extra para controlar los roles del usuario.
Ahora crearemos el constructor de la clase, el cual inicializará la clase mediante la autenticación del usuario, 
brindandole el nombre de usuario y la contraseña. El código es el siguiente:
Public Sub New(ByVal name As String, ByVal password As String)
 If IsValidNameAndPassword(name, password) Then
   nameValue = name
   authenticatedValue = True
   roleValue = ApplicationServices.BuiltInRole.Administrator
 Else
   nameValue = ""
   authenticatedValue = False
   roleValue = ApplicationServices.BuiltInRole.Guest
 End If
End Sub
En el constructor hacemos uso de un método denominado IsValidNameAndPassword el cual lo definimos a 
continuación:
Nota: como método didáctico en este ejemplo obtendremos los datos del usuario desde código duro. En una  
segunda entrega se hará desde la base de datos.

Private Function IsValidNameAndPassword( _
 ByVal username As String, _
 ByVal password As String) _
 As Boolean

 ' Obtenemos la contraseña encriptada y la salt.
 Dim storedHashedPW As String = GetHashedPassword(username)
 Dim salt As String = GetSalt(username)

 'Creamos el hash con la salt leida y la contraseña brindada.
 Dim rawSalted As String = salt & Trim(password)
 Dim saltedPwBytes() As Byte = _
 System.Text.Encoding.Unicode.GetBytes(rawSalted)
 Dim sha1 As New _
 System.Security.Cryptography.SHA1CryptoServiceProvider
 Dim hashedPwBytes() As Byte = sha1.ComputeHash(saltedPwBytes)
 Dim hashedPw As String = Convert.ToBase64String(hashedPwBytes)

 ' Comparamos la contraseña con el hash contra la contraseña almacenada.
 Return hashedPw = storedHashedPW
End Function
Ahora   creamos   las   funciones   utilizadas   en   el   método   anterior   (GetHashedPassword   y   GetSalt):
Nota: a como se dijo anteriormente, en esta entrega trabajaremos desde código duro la salt y la contraseña,  
en la próxima entrega lo trataremos desde la base de datos.
Private Function GetHashedPassword(ByVal username As String) As String
 ' Aca va el código que obtiene la contraseña con hash del usuario desde la BD.
 ' En este ejemplo usaremos código duro para obtenerla.
 ' Por buena práctica, la contraseña hash debe ser almacenada fuera
 ' del código de la aplicación.
 If Trim(username).ToLower = "testuser" Then
   Return "ZFFzgfsGjgtmExzWBRmZI5S4w6o="
 Else
   Return ""
 End If
End Function

Private Function GetSalt(ByVal username As String) As String
 ' El código que obtiene la sal del usuario va acá.
 ' En este ejemplo usaremos código duro para obtener la salt.
 ' Por buena práctica, la salt debe ser almacenada fuera
 ' del código de la aplicación.
 If Trim(username).ToLower = "testuser" Then
   Return "Debe ser un valor aleatorio diferente para cada usuario"
 Else
   Return ""
 End If
End Function
Hasta acá está el código de la clase ApplicationIIdentity. El código completo de la clase debe quedar como el 
siguiente:
Public Class ApplicationIIdentity
  Implements System.Security.Principal.IIdentity
  Private nameValue As String
  Private authenticatedValue As Boolean
  Private roleValue As ApplicationServices.BuiltInRole
  Public ReadOnly Property AuthenticationType() As String Implements System.Security.Principal.IIdentity.AuthenticationType
    Get
      Return “Autenticación personalizada”
    End Get
  End Property
  Public ReadOnly Property IsAuthenticated() As Boolean Implements System.Security.Principal.IIdentity.IsAuthenticated
    Get
     Return authenticatedValue
    End Get
  End Property
  Public ReadOnly Property Name() As String Implements System.Security.Principal.IIdentity.Name
    Get
      Return nameValue
    End Get
  End Property
  Public ReadOnly Property Role() As ApplicationServices.BuiltInRole
    Get
      Return roleValue
    End Get
  End Property
  Public Sub New(ByVal name As String, ByVal password As String)
    If IsValidNameAndPassword(name, password) Then
      nameValue = name
      authenticatedValue = True
      roleValue = ApplicationServices.BuiltInRole.Administrator
    Else
      nameValue = “”
      authenticatedValue = False
      roleValue = ApplicationServices.BuiltInRole.Guest
    End If
  End Sub
  Private Function IsValidNameAndPassword( _
    ByVal username As String, _
    ByVal password As String) _
    As Boolean
    ‘ Obtenemos la contraseña encriptada y la salt.
    Dim storedHashedPW As String = GetHashedPassword(username)
    Dim salt As String = GetSalt(username)
    ‘Creamos el hash con la salt leida y la contraseña brindada.
    Dim rawSalted As String = salt & Trim(password)
    Dim saltedPwBytes() As Byte = _
    System.Text.Encoding.Unicode.GetBytes(rawSalted)
    Dim sha1 As New _
    System.Security.Cryptography.SHA1CryptoServiceProvider()
    Dim hashedPwBytes() As Byte = sha1.ComputeHash(saltedPwBytes)
    Dim hashedPw As String = Convert.ToBase64String(hashedPwBytes)
    ‘ Comparamos la contraseña con el hash contra la contraseña almacenada.
    Return hashedPw = storedHashedPW
  End Function
  Private Function GetHashedPassword(ByVal username As String) As String
    ‘ Aca va el código que obtiene la contraseña con hash del usuario desde la BD.
    ‘ En este ejemplo usaremos código duro para obtenerla.
    ‘ Por buena práctica, la contraseña hash debe ser almacenada fuera
    ‘ del código de la aplicación.
    If Trim(username).ToLower = “testuser” Then
      Return “ZFFzgfsGjgtmExzWBRmZI5S4w6o=”
    Else
      Return “”
    End If
  End Function
  Private Function GetSalt(ByVal username As String) As String
    ‘ El código que obtiene la sal del usuario va acá.
    ‘ En este ejemplo usaremos código duro para obtener la salt.
    ‘ Por buena práctica, la salt debe ser almacenada fuera
    ‘ del código de la aplicación.
    If Trim(username).ToLower = “testuser” Then
      Return “Debe ser un valor aleatorio diferente para cada usuario“
    Else
      Return “”
    End If
  End Function
End Class

Bien, ya tenemos la identidad, ahora trabajaremos con la clase ApplicationIPrincipal.

Crear una clase Principal.
En   este   punto   debemos   crear   una   nueva   clase   que   implemente   la   interface  IPrincipal.
Creamos una nueva clase (Proyecto­>Agregar clase) y le pondremos el nombre  ApplicationIPrincipal. Una 
vez creada la clase, en el código ponemos lo siguiente justo despues de la linea
Public Class ApplicationIPrincipal:
Implements System.Security.Principal.IPrincipal
al presionar enter al final de esta línea, el editor de código agregará una propiedad y un método que deben 
implementarse en nuestra clase. Luego agregamos un atributo privado que almacenará la identidad asociada a 
nuestro objeto principal:
Private identityValue As ApplicationIIdentity
Luego, en la propiedad Identity agregamos el siguiente código:
Return identityValue
y en el método IsInRole agregamos el siguiente código:
Return role = identityValue.Role.ToString
Ahora   crearemos   el   constructor   de   la   clase,   el   cual   inicializa   la   clase   con   una   instancia   de 
ApplicationIIdentity, brindando el nombre de usuario y la contraseña:
Public Sub New(ByVal name As String, ByVal password As String)
  identityValue = New SampleIIdentity(name, password)
End Sub
aca establecemos la identidad del usuario haciendo uso de la clase ApplicationIIdentity.
El código de la clase
ApplicationIPrincipal debe quedar de la siguiente manera:
Public Class ApplicationIPrincipal
  Implements System.Security.Principal.IPrincipal
  Private identityValue As ApplicationIIdentity
  Public ReadOnly Property Identity() As System.Security.Principal.IIdentity Implements 
System.Security.Principal.IPrincipal.Identity
    Get
      Return identityValue
    End Get
  End Property
  Public Function IsInRole(ByVal role As String) As Boolean Implements System.Security.Principal.IPrincipal.IsInRole
    Return role = identityValue.Role.ToString
  End Function
  Public Sub New(ByVal name As String, ByVal password As String)
     identityValue = New ApplicationIIdentity(name, password)
  End Sub
End Class

Probando nuestra clase de autenticación.
Para probar nuestra clase de autenticación de usuarios personalizada, haremos uso del formulario de inicio de 
sesión que nos brinda Visual Basic .NET. Nos vamos a la opción  proyecto­>Agregar Windows Forms… y 
seleccionamos Formulario de inicio de sesión y le ponemos el nombre frmLogin.vb.
Luego que lo creamos nos aparece el formulario en diseño, damos doble clic en el botón Aceptar y nos 
aparecerá el código para el evento Click del botón. Nos aparecerá un código autogenerado por el IDE, el cual 
reemplazaremos con el siguiente código:
Private Sub OK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdAceptar.Click
  Dim samplePrincipal As New ApplicationIPrincipal( _
  Me.UsernameTextBox.Text, Me.PasswordTextBox.Text)
  Me.PasswordTextBox.Text = “”
  If (Not samplePrincipal.Identity.IsAuthenticated) Then
    ‘ The user is still not validated.
    MsgBox(“The username and password pair is incorrect”)
  Else
    ‘ Update the current principal.
    My.User.CurrentPrincipal = samplePrincipal
    Me.Close()
  End If
End Sub

LISTO!!!!

Ahora solo queda hacer la llamada de nuestro formulario de login para terminar de probarlo. Añadiremos un 
formulario a nuestro proyecto y le agregaremos 2 etiquetas (Label) y un botón (Button) dejándolos todos con 
el nombre por defecto (Label1, Label2 y Button1), luego borramos el texto de las etiquetas dejándolo vacío. 
Al botón le pondremos en la propiedad text a Autenticar. Luego hacemos doble clic sobre el botón y en el 
evento clic añadimos el siguiente código:

My.Forms.frmLogin.ShowDialog()
' Verificamos si el usuario está autenticado.
If My.User.IsAuthenticated Then
 Me.Label1.Text = "Autenticado como " & My.User.Name
Else
 Me.Label1.Text = "User not authenticated"
End If

If My.User.IsInRole(ApplicationServices.BuiltInRole.Administrator) Then
 Me.Label2.Text = "El usuario es un Administrador"
Else
 Me.Label2.Text = "El usuario no es Administrador"
End If

Este pequeño código lo que haces es: llama al formulario de login, el cual se encarga de verificar si el usuario 
introduce usuario y contraseña correcta, luego que se cierre el formulario de login, verifica en la instancia de 
aplicación My.User, la cual la sustituimos por nuestra instancia creada en nuestra clase.
My.User es una instancia de la aplicación que contiene la información del usuario, la cual implementa la 
interface IPrincipal… en este caso, nosotros hemos creado una clase que implementa de esta misma interface 
para sustituir el contenido de My.User por el nuestro.
En la próxima entrega trataremos el punto sobre la seguridad en el almacenamiento de la contraseña y la salt 
en nuestra base de datos. Haremos el diseño de nuestra BD para poder acceder a ella y mejorar nuestro 
código.
Espero les haya servido este “breve” tutorial sobre seguridad en .NET en la implementación de usuarios y 
contraseñas xD jejeje…

Saludos,
Ing. Paúl Somarriba
Sistemas Operativos
Manejador de Procesos (Primera parte) ­ Fundamentos
Por JuanK http://juank.black­byte.com
Esta es una serie de 2 o 3 post introductorios acerca de lo que es el manejador de procesos, la idea es tener un 
concepto muy general de lo que hace esta parte de todo sistema operativo, sin embargo es un tema muy 
extenso   y   que  puede  llegar a  ser  bastante  complejo,  por lo  cual  cabe  aclarar  que  por el  momento   solo 
trataremos los conceptos de manera muy superficial.

El   manejador   de   procesos   (también   llamado   planificador,   scheduler,   calendarizador   etc.)   es   la   parte 


fundamental de todo sistema operativo, de hecho se puede decir que para crear un sistema operativo básico 
basta con crear cuatro componentes fundamentales:

• Planificador de procesos 
• Administrador de memoria 
• Manejador de E/S (como mínimo con controladores para video, teclado y disco) 
• Sistema de archivos 

El   manejador   de   procesos   es   el   encargado,   como   su   nombre   lo   indica,   de   permitir   le   ejecución   de   los 


diferentes procesos en una o varias CPU. A simple vista esta tarea es sencilla, pero esta lejos de serlo.

El procesador es un dispositivo que ejecuta un conjunto de instrucciones y devuelve un resultado, así que 
desde el punto de vista del procesador el concepto de proceso no existe más allá de ejecutar una instrucción 
en cada ciclo de procesamiento; es el sistema operativo quien determina que es un proceso en si: un conjunto 
de instrucciones agrupadas con un(os) objetivo(s) especifico(s). 

Cuando estamos utilizando un sistema operativo como Windows siempre tenemos la percepción de que hay 
múltiples   programas   ejecutándose   al   mismo   tiempo,   podemos   ver   varias   ventanas   abiertas   mientras 
escuchamos música, navegamos por internet y diligenciamos una hoja de cálculo de excel, pero esto no es 
más que una ilusión. 

Para simplificar un poco el trabajo examinaremos la situación cuando solo hay presente un procesador de un 
único núcleo.

funcionamiento básico de una CPU
La CPU, como ya lo mencionamos, solo puede ejecutar una instrucción a la vez, pero como es esto?

Bueno la forma mas sencilla de explicarlo es con un ejemplo: digamos que queremos sumar los valores 2+3 
utilizando la CPU, la CPU tiene una especie de ‘ranuras’ llamadas registros algunas de estas ranuras reciben 
los nombres de Ax, Bx, Cx (pero hay varias más.) y son utilizados por la CPU como fuente de entrada y 
salida de información.

Lo que se hace entonces para la suma es colocar los valores a sumar en los registros, esto es un mini ejemplo 
en lenguaje ensamblador:
mov AX, 2 ; poner el número 2 en el registro AX
add AX, 3 ;sumar al contenido de AX el valor 3, la respuesta queda en AX
veamos estos dos pasos en el siguiente gráfico (lo he expandido a 4 pasos para mayor claridad)

El procesador posee un registro que es un apuntador que le permite saber en que instrucción del programa se 
encuentra de tal manera que cada vez que ejecuta una instrucción el mueve al apuntador a la  siguiente 
instrucción a ser ejecutada.

Cualquier instrucción ejecutada por la CPU funciona de manera similar, utilizando los registros como ranuras 
de intercambio de datos.

Cómo se ejecutan varios procesos?
De acuerdo al tema tratado anteriormente pudimos ver que una CPU solo puede ejecutar una instrucción a la 
vez, y como es de suponerse dicha instrucción pertenece a un proceso determinado. 
Hay varias maneras de llevar a cabo la ejecución de procesos
Sistemas Operativos Monotarea
La CPU por si sola no puede iniciar la ejecución de otro proceso, es el sistema operativo es quien le dice a la 
CPU cuando comenzar a ejecutar un conjunto de instrucciones determinado, sin embargo la CPU ejecutaría 
todas las instrucciones de un proceso hasta finalizar y en ese momento continuaría la ejecución del sistema 
operativo (que en si es otro proceso) el cual seleccionaría el siguiente proceso a ejecutar suspendiéndose a si 
mismo   hasta   que   el   proceso   finalice,   luego   nuevamente   volvería   a   seleccionar   un   nuevo   proceso   y   así 
sucesivamente hasta que no hubiesen procesos por ejecutar.

Algunos dirán y como es que se vuelve a ejecutar el sistema operativo cuando acaba de terminar un proceso?, 
bueno el truco es sencillo, devolvámonos a algunos sistemas mono tarea tipo DOS en sus primeras versiones, 
si   hacíamos   un   programa   en   C   este   al   final   del   main   siempre   tenia   la   instrucción   return,   pues   bien   el 
compilador al compilar código convertía esa expresión return en instrucciones de maquina que hacían que la 
siguiente ‘línea’ de código a ejecutar fuera… el sistema operativo, así que básicamente todo programa hecho 
finaliza con una instrucción para devolver el control al sistema operativo.

Este tipo de comportamiento es el habitual en sistemas operativos mono­proceso , es decir que solo pueden 
ejecutar un proceso a la vez de tal forma que todos los procesos deben esperar su turno en una larga fila de 
procesos pendientes: esto también es conocido como: planificación por lotes.

Si Windows funcionara de esta manera no podríamos hacer nada con el pues no podríamos tener sino un 
programa a la vez y esto excluye de manea inevitable los propios servicios que el sistema operativo corre en 
segundo plano, incluso si mandaras un trabajo de impresión no podrías hacer absolutamente nada más hasta 
que el trabajo de impresión finalice.

Esto esta muy lejos de ser el comportamiento que estamos habituados a ver, es decir un sistema con decenas 
de procesos ejecutándose ‘al tiempo’, entonces como funciona esto? bueno todo se resuelve con un truco que 
realiza el sistema operativo.

Sistemas Operativos Multitarea
Como su nombre lo indica ‘multitarea’ se refiere a que puede realizar varias tareas a la vez, al menos eso es 
lo que parece.

Realmente lo que sucede es que el sistema operativo esta hecho para tomar la sabia decisión de no permitirle 
a un programa ejecutarse sino por una fracción de tiempo (muy pequeña), de tal forma que en  un solo 
segundo   muchos   programas   han   tenido   tiempo   de   procesamiento,   es   decir   muchos   programas   se   han 
ejecutado en lapsos de pequeñas fracciones de tiempo. En esencia el concepto es sencillo, implementarlo 
suele ser más complicado pues hay muchos más aspectos involucrados, estudiaremos algunos.

Interrupción de la Ejecución de un Proceso
Al   ejecutarse   un   proceso   en   un   sistema   multitarea,   este   tiene   la   oportunidad   de   realizar   un   conjunto 
indeterminado de instrucciones, lo que alcance a hacer en un tiempo limitado, una vez ese tiempo se ha 
cumplido el sistema operativo debe decidir que proceso debe continuar su ejecución ( bien sean procesos de 
usuario o procesos de sistema ), esto lo hace teniendo en cuenta una lista de procesos y unas listas por 
prioridades de procesos, donde algunos procesos tienen más tiempo de ejecución que otros y tienen una 
prioridad mayor que les permite ‘avanzar más rápido en la fila’.

El sistema operativo sabe que se ha cumplido el tiempo de ejecución de un proceso cuando recibe una señal 
de interrupción por parte del procesador, esta señal se activa solo cada determinado tiempo (este lapso de 
tiempo   es   llamado   Quantum),  básicamente   existe  un  microprograma  que  en  ese   momento  le  permite   al 
procesador suspender la ejecución y enviar el control (es decir ejecutar) al sistema operativo para que lleve a 
cabo la planificación necesaria .

Sin embargo hay otros mecanismos que pueden generar interrupciones como por ejemplo:
• Una Señal enviada desde un dispositivo de hardware 
• Un proceso puede optar por suspenderse a si mismo 

Hay muchas situaciones donde las dos condiciones anteriores puede ocurrir, este es un ejemplo típico:

El proceso P1 se encuentra en ejecución y en un momento determinado espera respuesta desde un dispositivo 
de E/S(por ejemplo una tarjeta de red), pero no sabe en que momento se recibirá dicha respuesta, así que el 
proceso   se   encuentra   en   espera   y   suspende   su  ejecución.   El   sistema   operativo   coloca   al   proceso   P2   en 
ejecución y este comienza a ejecutarse durante su Quantum, seguidamente termina su tiempo de ejecución y 
siguen en ejecución otros procesos P3…Pn.

En un momento determinado el proceso P5 se encontraba en ejecución cuando el dispositivo de red envió la 
respuesta que estaba esperando P1, el procesador conoce de esa respuesta y genera una nueva interrupción (es 
decir   devuelve   el   control   otra   vez   al   sistema   operativo)   suspendiendo   inmediatamente   el   proceso   en 
ejecución. El sistema operativo revisa los buffer de los dispositivos de entrada, encuentra la respuesta que 
esperaba P1 y activa inmediatamente P1 para que este continúe con su ejecución por un nuevo Quantum de 
tiempo o en tanto no se genere una nueva interrupción cualquiera que sea su origen.

Tenemos   entonces   tres   maneras   que   permiten   que   un   proceso   suspenda   su   ejecución   para   que   otros   se 
ejecuten:
1. Interrupción por el reloj del procesador (Quantum de tiempo) 
2. Interrupción por dispositivos de E/S 
3. Auto suspensión del proceso o finalización del proceso. 
Estado De La Ejecución De Un Proceso
Ya hemos visto como es que el sistema operativo alterna entre varios procesos para dar la impresión de que 
esta haciendo varias cosas a la vez, pero puede que alguno de ustedes ya les haya surgido la pregunta: ¿Cómo 
sabe el sistema en que iba mi proceso justo antes de suspenderlo? veamos el caso anterior (el de 2 +3) en un 
entorno multitarea:
En   la   gráfica   vemos   al   proceso   P1   justo   terminando   de   finalizar   su   primera   instrucción,   así   que   como 
respuesta a esta instrucción el procesador dejó el valor 2 en el registro AX, luego viene los demás procesos 
cada uno utilizando los registros según sus necesidades como se ve en la gráfica:

hasta  que  por  alguna razón le vuelve a tocar el turno de ejecución al proceso P1 y ooops!!! P1  estaba 


esperando que en AX estuviera el valor 2 para que así su suma sea 2+3, pero en este momento ya el proceso 
P1 no tendría en los registros los mismos valores que tenia justo antes de suspenderse!!!
Por otro lado el sistema operativo también necesita saber en que instrucción estaba la ejecución de P1 para 
continuar justo donde estaba antes de suspender su ejecución, y algunos otros datos más, entonces como hace 
para que todo pueda continuar normal?

Como lo dije anteriormente cuando un proceso se suspende básicamente se devuelve la ejecución al sistema 
operativo, allí el sistema lleva a acabo la planificación de procesos y otras tareas, pero que hace realmente?

El sistema lo primero que hace es guardar el estado del proceso en algún sitio, el estado del proceso es una 
estructura   en   memoria   que   guarda   los   valores   de   TODOS   los   registros   y   banderas   del   procesador   (las 
banderas   son   un   registro   utilizado   por   el   procesador   para   indicar   situaciones   como   división   por   cero, 
overflow, signo negativo etc.) es decir esto incluye el registro IP(Instruction Pointer) que es un registro que 
contiene un apuntador que indica al procesador en que instrucción de código va la ejecución, y los registros 
Ax, Bx, Cx, etc.

Una vez ese dato queda guardado el sistema verifica cual es el siguiente proceso que debe tener un Quantum 
de ejecución, digamos el proceso P2, así que el sistema operativo lee el estado del proceso P2 y comienza a 
dejar   las   cosas   en   su   lugar,   es   decir   lee   los   valores   que   deberían   tener   cada   uno   de   los   registros   ,   las 
banderas,etc.  y  establece esos valores en el procesador, una vez todos los valores están establecidos  los 
últimos   valores   que  establece   el  sistema  son  los  de  los  registros  de  segmento  y  el   registro  IP,  una   vez 
realizada esta  labor  inicia la ejecución de P2 hasta que sea interrumpido y se continúe con la labor   de 
planificación una y otra vez.
Si desean más información acerca de los registros los invito a consultar este Tutorial de Assembler.
Esto es todo por el momento, los más conocedores me perdonaran por todas las cosas que he podido pasar 
por alto pero recuerden que esto es solo un post introductorio y no pretendo detallar las cosas más allá de los 
conocimientos generales, de igual forma cualquier duda o corrección que tengan es bienvenida.

Saludos.
CHECMATED es un excelente programador del foro code­makers maneja muy bien Python y es uno de los 
moderadores más queridos del foro; acá les dejo la entrevista que nos concedió.

1) ¿De dónde eres? planeo   dedicarme   a   esta   por   unos   años   mas. 


Soy de Venezuela, para ser mas especifico, de turen, Actualmente   estoy   en   la   programacion   de   un   juego 
un pequeño pueblo del estado portuguesa. llamado "The CM Incident" el cual, se prevee estara 
listo alrededor de julio ­ septiembre de este año
2) ¿Hace cuánto que comenzaste a programar?
Llevo aproximadamente 2 años con la programación, 9) ¿Que te gustaría ver en los próximos años en el 
pero   mi   "aprendizaje"   fue   muy   interrumpido   por mundo de la programación?
distintos motivos. Pues,   el   progreso   en   el   area   de   programacion   en 
latinoamérica   en   los   ultimos   años   a   sido   realmente 
3)   ¿Cuáles   son   tus   lenguajes   de   programación bueno,  dejemos  que  todo  "fluya" y  ya  veremos   que 
favoritos? pasa, es decir, no espero nada en especifico :P
No lo llamaria favoritismo pero prefiero trabajar con 
python por su facilidad, ademas de que es un lenguaje 10) ¿Cuál es tu mensaje final para la comunidad?
muy   flexible   con   el   cual   puedes   tener   buenos Un saludo a código latino, gracias por la oportunidad
resultados con cualquier proyecto. Aparte de python, 
uso Visual Basic, y porsupuesto, C/C++.

4) ¿Cuáles son tus programas favoritos de Diseño?
Aunque  debo admitir que nunca se me a dado muy 
bien   el   diseño,   es   un   pasatiempo   que   tengo.   Por 
Windows uso Adobe Photo Shop, pero por el lado de 
Linux no tengo ningun programa predilecto

5) ¿Qué te inspiró a ser programador?
Diria que fue por simple curiosidad que me inicie en 
este   mundo.   Dicha   curiosidad   comenzo   cuando   un 
primo (ahora ingeniero en informatica) instala VB en 
mi PC para hacer unas practicas. Luego de varios dias, 
comenze   a   leerme   el   manual   que   venia   con   este   y 
pues, por hay comenze jaja

6) ¿Cuéntanos un poco acerca de tu compañía?
Sin comentarios jaja

7) ¿Qué opinas de la escena de programadores en 
Latinoamérica?
Creo que es bastante desarollada y prometedora. En 
latinoamérica hay mucho, talento, por así llamarlo

8) ¿Cuáles son tus nuevos proyectos?
Ya   que   me   apasiona   la   programacion   de   juegos, 
ZTIC_TAC_TOE (Juego en ABAP)
Por Blag http://atejada.blogspot.com
El otro día estaba aburrido en la oficina, esperando una orden de transporte y que una tabla me devolviera 
algunos resultados...Entonces, me puse a pensar acerca de mi nuevo blog... Como ya he escrito tantas cosas, 
me es un poco dificil crear algo nuevo y extraño ­;) Felizmente me acordé que hace algún tiempo hice un Tic­
Tac­Toe (Michi o Gato) en Ruby, así que pensé que hacerlo en ABAP no sería muy díficil...Y no lo fué ­;) Me 
tomó solamente 20 minutos hacer esto...

El   juego   tiene   una   pobre   y   limitada   Inteligencia   Artificial...Debemos   ingresar   un   número   del   1   al   9   y 
presionar Play! para que la computadora haga su jugada debemos presionar Play! nuevamente...

Ahora, el código fuente...
*&­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­*
*& Report ZTIC_TAC_TOE                   *
*&­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­*
REPORT ZTIC_TAC_TOE NO STANDARD PAGE HEADING.
TYPES: BEGIN OF TY_PLAYS,
   PLAY TYPE C,
   END OF TY_PLAYS.
DATA: T_PLAYS TYPE STANDARD TABLE OF TY_PLAYS.
FIELD­SYMBOLS: <FS_PLAYS> LIKE LINE OF T_PLAYS.
DATA: RANDOM TYPE REF TO CL_ABAP_RANDOM.
DATA: SEED TYPE I,
   WIN_FLAG TYPE C,
   FLAG_OK TYPE C,
   W_LINES TYPE I,
   FLAG TYPE C,
   PLAYER_ONE TYPE C,
   PLAYER_TWO TYPE C,
   ONE TYPE C,
   TWO TYPE C,
   THREE TYPE C,
   FOUR TYPE C,
   FIVE TYPE C,
   SIX TYPE C,
   SEVEN TYPE C,
   EIGHT TYPE C,
   NINE TYPE C.
*­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­*
*    START­OF­SELECTION                 *
*­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­*
START­OF­SELECTION.
 FLAG = '1'.
 SET PF­STATUS 'BAR'.
 PERFORM BOARD USING '' '' ''.
 PERFORM PLAYER_ONE.
*­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­*
*    FORM PLAYER_ONE                   *
*­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­*
FORM PLAYER_ONE.
 IF WIN_FLAG EQ SPACE.
  WRITE:/ 'Player one: '.
  FORMAT INPUT ON.
  WRITE: PLAYER_ONE.
  FORMAT INPUT OFF.
 ENDIF.
ENDFORM.          "player_one
*­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­*
*    FORM PLAYER_TWO                   *
*­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­*
FORM PLAYER_TWO.
 IF WIN_FLAG EQ SPACE.
  WRITE:/ 'Player two: '.
  FORMAT INPUT ON.
  WRITE: PLAYER_TWO.
  FORMAT INPUT OFF.
 ENDIF.
ENDFORM.          "player_two
*­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­*
*    FORM BOARD                     *
*­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­*
FORM BOARD USING P_PLAYER P_NUMBER FLAG_OK.
 IF P_PLAYER NE SPACE AND P_NUMBER NE SPACE.
  READ TABLE T_PLAYS WITH KEY PLAY = P_NUMBER
  ASSIGNING <FS_PLAYS>.
  IF NOT <FS_PLAYS> IS ASSIGNED OR SY­SUBRC NE 0.
   APPEND INITIAL LINE TO T_PLAYS
   ASSIGNING <FS_PLAYS>.
   <FS_PLAYS>­PLAY = P_NUMBER.
   UNASSIGN <FS_PLAYS>.
   FLAG_OK = 'X'.
  ELSE.
   WRITE:/ 'Please select another number!'.
   CLEAR: P_NUMBER,FLAG_OK.
  ENDIF.
 ENDIF.
 CASE P_NUMBER.
  WHEN '1'.
   IF P_PLAYER EQ '1'.
    ONE = 'X'.
   ELSE.
    ONE = 'O'.
   ENDIF.
  WHEN '2'.
   IF P_PLAYER EQ '1'.
    TWO = 'X'.
   ELSE.
    TWO = 'O'.
   ENDIF.
  WHEN '3'.
   IF P_PLAYER EQ '1'.
    THREE = 'X'.
   ELSE.
    THREE = 'O'.
   ENDIF.
  WHEN '4'.
   IF P_PLAYER EQ '1'.
    FOUR = 'X'.
   ELSE.
    FOUR = 'O'.
   ENDIF.
  WHEN '5'.
   IF P_PLAYER EQ '1'.
    FIVE = 'X'.
   ELSE.
    FIVE = 'O'.
   ENDIF.
  WHEN '6'.
   IF P_PLAYER EQ '1'.
    SIX = 'X'.
   ELSE.
    SIX = 'O'.
   ENDIF.
  WHEN '7'.
   IF P_PLAYER EQ '1'.
    SEVEN = 'X'.
   ELSE.
    SEVEN = 'O'.
   ENDIF.
  WHEN '8'.
   IF P_PLAYER EQ '1'.
    EIGHT = 'X'.
   ELSE.
    EIGHT = 'O'.
   ENDIF.
  WHEN '9'.
   IF P_PLAYER EQ '1'.
    NINE = 'X'.
   ELSE.
    NINE = 'O'.
   ENDIF.
 ENDCASE.
 PERFORM CHECK_WHO_WINS.
 DESCRIBE TABLE T_PLAYS LINES W_LINES.
 IF WIN_FLAG EQ SPACE AND W_LINES EQ 9.
  WIN_FLAG = 'X'.
  WRITE: 'It''s a tie!'.
 ENDIF.
 WRITE:/ ONE,'|',TWO,'|',THREE.
 WRITE:/ '­­+­­­+­­­'.
 WRITE:/ FOUR,'|',FIVE,'|',SIX.
 WRITE:/ '­­+­­­+­­­'.
 WRITE:/ SEVEN,'|',EIGHT,'|',NINE.
 IF P_PLAYER EQ '2'.
  PERFORM PLAYER_ONE.
 ELSEIF P_PLAYER EQ '1'.
  PERFORM PLAYER_TWO.
 ENDIF.
ENDFORM.          "board
*­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­*
*    FORM check_who_wins                 *
*­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­*
FORM CHECK_WHO_WINS.
 IF ONE EQ TWO AND TWO EQ THREE.
  IF THREE EQ 'X'.
   WRITE:/ 'Player 1 Wins!'.
   WIN_FLAG = 'X'.
   SKIP 2.
  ELSEIF THREE EQ 'O'.
   WRITE:/ 'Player 2 Wins!'.
   WIN_FLAG = 'X'.
   SKIP 2.
  ENDIF.
 ENDIF.
 IF FOUR EQ FIVE AND FIVE EQ SIX.
  IF SIX EQ 'X'.
   WRITE:/ 'Player 1 Wins!'.
   WIN_FLAG = 'X'.
   SKIP 2.
  ELSEIF SIX EQ 'O'.
   WRITE:/ 'Player 2 Wins!'.
   WIN_FLAG = 'X'.
   SKIP 2.
  ENDIF.
 ENDIF.
 IF SEVEN EQ EIGHT AND EIGHT EQ NINE.
  IF NINE EQ 'X'.
   WRITE:/ 'Player 1 Wins!'.
   WIN_FLAG = 'X'.
   SKIP 2.
  ELSEIF NINE EQ 'O'.
   WRITE:/ 'Player 2 Wins!'.
   WIN_FLAG = 'X'.
   SKIP 2.
  ENDIF.
 ENDIF.
 IF ONE EQ FOUR AND FOUR EQ SEVEN.
  IF SEVEN EQ 'X'.
   WRITE:/ 'Player 1 Wins!'.
   WIN_FLAG = 'X'.
   SKIP 2.
  ELSEIF SEVEN EQ 'O'.
   WRITE:/ 'Player 2 Wins!'.
   WIN_FLAG = 'X'.
   SKIP 2.
  ENDIF.
 ENDIF.
 IF TWO EQ FIVE AND FIVE EQ EIGHT.
  IF EIGHT EQ 'X'.
   WRITE:/ 'Player 1 Wins!'.
   WIN_FLAG = 'X'.
   SKIP 2.
  ELSEIF EIGHT EQ 'O'.
   WRITE:/ 'Player 2 Wins!'.
   WIN_FLAG = 'X'.
   SKIP 2.
  ENDIF.
 ENDIF.
 IF THREE EQ SIX AND SIX EQ NINE.
  IF NINE EQ 'X'.
   WRITE:/ 'Player 1 Wins!'.
   WIN_FLAG = 'X'.
   SKIP 2.
  ELSEIF NINE EQ 'O'.
   WRITE:/ 'Player 2 Wins!'.
   WIN_FLAG = 'X'.
   SKIP 2.
  ENDIF.
 ENDIF.
 IF ONE EQ FIVE AND FIVE EQ NINE.
  IF NINE EQ 'X'.
   WRITE:/ 'Player 1 Wins!'.
   WIN_FLAG = 'X'.
   SKIP 2.
  ELSEIF NINE EQ 'O'.
   WRITE:/ 'Player 2 Wins!'.
   WIN_FLAG = 'X'.
   SKIP 2.
  ENDIF.
 ENDIF.
 IF SEVEN EQ FIVE AND FIVE EQ THREE.
  IF THREE EQ 'X'.
   WRITE:/ 'Player 1 Wins!'.
   WIN_FLAG = 'X'.
   SKIP 2.
  ELSEIF THREE EQ 'O'.
   WRITE:/ 'Player 2 Wins!'.
   WIN_FLAG = 'X'.
   SKIP 2.
  ENDIF.
 ENDIF.
 IF FOUR EQ FIVE AND FIVE EQ SIX.
  IF SIX EQ 'X'.
   WRITE:/ 'Player 1 Wins!'.
   WIN_FLAG = 'X'.
   SKIP 2.
  ELSEIF SIX EQ 'O'.
   WRITE:/ 'Player 2 Wins!'.
   WIN_FLAG = 'X'.
   SKIP 2.
  ENDIF.
 ENDIF.
ENDFORM.          "check_who_wins
*­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­*
*    AT USER­COMMAND                   *
*­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­*
AT USER­COMMAND.
 IF SY­UCOMM EQ 'BACK'.
  SET SCREEN 0.
  LEAVE PROGRAM.
 ELSE.
  IF WIN_FLAG EQ SPACE.
   IF FLAG = '1'.
    PLAYER_ONE = SY­LISEL+12(1).
    PERFORM BOARD USING FLAG PLAYER_ONE FLAG_OK.
    IF FLAG_OK = 'X'.
     FLAG = '2'.
    ENDIF.
   ELSE.
    SEED = CL_ABAP_RANDOM=>SEED( ).
    RANDOM = CL_ABAP_RANDOM=>CREATE( SEED ).
    PLAYER_TWO = RANDOM­>INTINRANGE( LOW = 1 HIGH = 9 ).
    PERFORM BOARD USING FLAG PLAYER_TWO FLAG_OK.
    IF FLAG_OK = 'X'.
     FLAG = '1'.
    ENDIF.
   ENDIF.
  ENDIF.
 ENDIF.

Espero que les guste y si pueden, mejorenlo ­:)

Saludos,

Blag.
Windows te ordeno que trabajes por Mi!!!
Por Cronodragon
Este artículo trata sobre como convertir a Windows en un robot que hace lo que se le pida. Puede usarse para 
el mal o para bien, queda a conciencia del programador, pero mejor que sea algo útil y divertido.

Les presento AutoIt v3, una sencilla pero poderosa herramienta de automatización que es gratuita. Con esta 
podemos   lograr   que   Windows   haga   cualquier   cosa   que   le   pidamos,   aparte   de   levantarse   y   preparar   el 
desayuno, aunque talvez un día... un día de estos. Esta es realmente el arma perfecta para acabar con esas 
tareas largas y rutinarias.

Para comenzar programaremos un Hola Mundo. así que creamos un nuevo archivo de texto con extensión 
.au3 . Ahora abrimos el archivo con el editor que trae AutoIt, o con su editor de texto favorito, e insertamos 
las siguientes líneas:

Run("notepad.exe")
Sleep(1000)
Send("Hola Mundo!{ENTER}")

Guardamos el cambio, y ejecutamos el archivo... fuera manos!! El script abrira automaticamente el notepad y 
escribira por si solo. Es importante no intervenir mientras se ejecuta el script, o podria terminar escribiendo 
en otra aplicación. Hagase la salvedad que podemos intervenir para pausar el script presionando en el icono 
del tray bar, esto es útil por si el script se desboca. AutoIt es un amigo fiel y bien entrenado, aun así se debe 
tener cuidado para manipularlo.

La mejor forma de aprender a usar AutoIt es consultando la ayuda que trae. Entre las funciones mas útiles 
estan   las   de   manipulación   del   teclado   y   el   ratón,   que  convierten   a  Windows   en   un   automata   a   nuestro 
servicio.

La única desventaja que he encontrado es que es díficil hacer portables los scripts de un sistema a otro. Si 
abren el ejemplo de notepad que viene incluido con AutoIt, veran las siguientes lineas:

; Wait for the Notepad become active ­ it is titled "Untitled ­ Notepad" on English systems
WinWaitActive("Untitled ­ Notepad")

En vez de esperar una cantidad de tiempo como en nuestro Hola Mundo, usando Sleep(1000), este ejemplo 
espera que se abra la ventana de notepad, pero solo funciona para Windows en ingles. Como ven es un 
metodo mas seguro, pero pierde portabilidad, así  que se debe tomar en cuenta la configuración del sistema, 
su velocidad, etc. Además posiblemente se deben preconfigurar y abrir los programas que el script va a 
utilzar, para que encuentre las cosas tal y como las necesita.

Debido a este problema de portabilidad no puedo simplemente pasarles un script que resuelva un problema de 
la vida real, sino que deben adaptarlo a sus necesidades y a su sistema. Por eso voy a explicarles un problema 
que tengo que resolver, para que vean un flujo de trabajo para crear los scripts. 
Estoy creando un diccionario ingles­espanol de 1500 palabras en Excel, y quiero insertarle a cada palabra el 
sonido de su pronunciación. Me va a llevar demasiado tiempo ponerle todos los sonidos, así que voy a crear 
un script para acelerar el trabajo. Por supuesto Excel tiene sus propios macros para automatizar estas tareas, 
pero veran lo fácil que se programa con AutoIt, y ademas funciona en cualquier software, de hecho funciona 
sobre todo el sistema operativo.

Lo primero que hago es probar a mano con que combinaciones del teclado puedo activar las funciones de 
Excel para insertar un objeto de archivo .wav . Me doy cuenta que presionando [alt]+[i] > [o] > [w] > [enter] 
se abre la grabadora de sonidos, y luego con [alt]+[e] > [i] se abre el dialogo para insertar el archivo. Escribo 
el nombre del archivo, cierro con [alt]+[f] > [x]. Luego paso a la siguiente celda presionando [esc] > [enter]. 
Con esto puedo crear la primera version del script como sigue:

Sleep(5000)
Send("!iow{ENTER}")
Sleep("500")
Send("!ei")
Sleep("500")
Send("able0001.wav")    ; archivo de prueba
Send("{ENTER}")
Sleep("500")
Send("!fx")
Sleep("500")
Send("{ESC}{ENTER}")

El primer Sleep() me da 5 segundos de tiempo para darle foco a la ventana de Excel y colocarme en la 
primera celda. Ahora solo necesito hacer ese mismo paso para cada uno de los 1500 archivos de sonido que 
tengo almacenados. Para esto voy a usar la función FileFindFirstFile() y sus amigas. En la ayuda viene un 
ejemplo que convenientemente voy a copiar para no reinventar el agua tibia, así mi código quedaría de la 
siguiente manera:

Sleep(5000)
$search = FileFindFirstFile("C:\PROYECTOS\Dictionary\*.*") 

If $search = ­1 Then
  MsgBox(0, "Error", "No files/directories matched the search pattern")
  Exit
EndIf
While 1
  $file = FileFindNextFile($search) 
  If @error Then ExitLoop

        Sleep(1000)
        Send("!iow{ENTER}")
        Sleep("500")
        Send("!ei")
        Sleep("500")
       MsgBox(4096, "File:", $file)       ; para depuracion
        Send($file)
        Send("{ENTER}")
        Sleep("500")
        Send("!fx")
        Sleep("500")
        Send("{ESC}{ENTER}")
WEnd

FileClose($search)

Y con esto me ahorre varios días de aburrido trabajo! Espero que este tutorial sea de su entero provecho. 
Hasta pronto!
Incluir documentos HTML o datos Complejos
Por 100% Telch
Vamos a aprender a incluir documentos HTML o datos complejos, con el Html­Template a tú archivo.tmpl

Introducción.

Una vez me vi en el gran problema de incluir un documento HTML completo dentro de una plantilla o un 
template; y quiero compartir con ustedes una forma con la cual solucioné este problema, que para muchos 
quizás no lo sea.

En un lenguaje como PHP me fue muy fácil hacer algo como esto:

If ($do == "articulos") {
        Include ("articulos.html");
}elseif ($do == "noticias") {
        Include ("noticias.html");
Elseif
.
.
 N... etc...
}

Bueno pero me vi en el gran problema de necesitar incluir no solo documentos HTML, si no también un 
flash, un jpg, un despliegue de un DBI etc…, También se presento en inconveniente de que la pobre plantilla 
se me iba llenando de código y mas código a medida que ingresaba secciones.
Si necesita crear a un menú nuevo, tenia que hacer toda la conexión a la base de datos y el desplegué de html 
dentro de la misma plantilla, y no que pereza la verdad eso parece mas una sopa y no un template, se también 
que se podría solucionar este problema en otros lenguajes.

Bueno, aun así la idea general era solucionar este problema usando Perl y sé que en PHP o ASP no lo podría 
solucionar como en Perl.

Desarrollo:
Imagino que ya conocerás en HTML­Template, si no estudiate uno des los tutoriales que andan por ahí, 
aunque no es tan complicada la cosa, con este ejemplo puedes ver como funciona

Resulta que tenemos esto que me devuelve un dato a una plantilla, 
Plantilla “template1.tmpl”
<html> 
  <head> 
    <title>Template</title> 
  </head> 
<body> 
  Today is <tmpl_var name=dia> 
  </body> 
</html>
Mi archivo de Perl:
#!c:/perl/bin/perl
use CGI qw(:all); 
use HTML::Template; 
use POSIX; 
print header; 
my $template = HTML::Template­>new(filename => 'template1.tmpl'); 
$template­>param(dia => strftime('%A', localtime()) ); 
print $template­>output();

Acá sencillamente tenemos una plantilla que me muestra la fecha en pantalla, pero lo que queremos devolver 
no solo un dato en variable si no un documento HTML completo, una imagen, un DHTML, un componente 
Active X, manteniendo el código Perl COMPLETAMENTE separado de la plantilla o template.
Bueno veamos un ejemplo de un template que tiene sus vínculos que no solo desplegaran datos de variable, si 
no un documento HTML completo, un jpg, una consulta de una BD etc... 
Esta plantilla es un poco mas compleja, tiene una barra de navegación superior, un menú izquierdo y su 
cuerpo; también tiene tres variables de template el <tmpl_loop name="menu"> ­ <tmpl_var name=vinculo> 
para el menú izquierdo y el <tmpl_var name=contenido> donde se desplegara el contenido de tus secciones.

Plantilla “template.tmpl”
<html> 
  <head> 
    <title>Template</title> 
  </head> 
<body> 
  <table width="41%" border="0" cellspacing="0" cellpadding="0">
   <tr> 
      <td></td>
       <td> <a    href="config.pl?go=home">Home</a></td>
       <td> <a    href="config.pl?go=contactos">Contactos</a></td>
   </tr>
   <tr> 
      <td>
        <table>
           <tmpl_loop name="menu"> 
           <tr> 
             <td><tmpl_var name="vinculo"></td> 
           </tr> 
           </tmpl_loop>
       </table>
     </td>
     <td colspan="2">
       <tmpl_var name=contenido>
     </td>
   </tr>
  </table>
</body> 
</html>
Mi archivo de Perl “config.pl”:
#!c:/perl/bin/perl
   use CGI qw(:all);
   use HTML::Template;
my(%dato); #Iniciamos el hash
#Leemos el query enviado
my $buffer = $ENV{'QUERY_STRING'};
my @pairs = split(/&/, $buffer);
foreach my $pair (@pairs) {
    my ($name, $value) = split(/=/, $pair);
    $name =~ tr/+/ /;
    $name =~ s/%([a­fA­F0­9][a­fA­F0­9])/pack("C", hex($1))/eg;
    $value =~ tr/+/ /;
    $value =~ s/%([a­fA­F0­9][a­fA­F0­9])/pack("C", hex($1))/eg;
    $dato{$name} = $value;
};
# función para desplegar un f ichero html
sub desplegar{
  open(ARCHIVO, $file) || die "No se pudo abrir archivo";
     while(!eof(ARCHIVO)){
        $clave=<ARCHIVO>;
        # se guarda en include el documento html completo
        $include = $include.$clave;
        }
  close(ARCHIVO);
};
#creamos un menu de las secciones de nuestra pagina web ej.
 my @menu = (
   {vinculo => 'Perl'},
   {vinculo => 'PHP5'},
   {vinculo => 'ASP'},
 );

if ($dato{'go'} eq "home") {
  $include = "<img src='imagen.jpg'>"; # El contenido de la pagina principal es una imagen
}elsif ($dato{'go'} eq "contactos") {
   $file = "contactos.html";
   #llamamos el procedimiento que desplega el fichero HTML en el include
   &desplegar
}elsif ($dato{'go'} eq "") {
 $include = "<img src='imagen.jpg'>";
}else{
   # en caso de lo contrario abre un documento con el nombre guardado en $dato{'go'} .html
   $file = $dato{'go'}."html";
   &desplegar
};
#indicamos como se llama la plantilla a utilizar
$plantilla = "template.tmpl";
# Salida de la plantilla
my $template = HTML::Template­>new(filename => $plantilla);
 $template­>param(contenido => $include );
 $template­>param(menu => \@menu  );
 print "Content­Type: text/html\n\n", $template­>output;
EXPLICACION 
Estas primeras líneas :

#!c:/perl/bin/perl
   use CGI qw(:all);
   use HTML::Template;

Es donde definimos el módulo CGI y el poderoso módulo HTML­Template.
Con las siguientes líneas decodificamos el Query envíado

my(%dato); #Iniciamos el hash
#Leemos el query enviado
my $buffer = $ENV{'QUERY_STRING'};
my @pairs = split(/&/, $buffer);
foreach my $pair (@pairs) {
    my ($name, $value) = split(/=/, $pair);
    $name =~ tr/+/ /;
    $name =~ s/%([a­fA­F0­9][a­fA­F0­9])/pack("C", hex($1))/eg;
    $value =~ tr/+/ /;
    $value =~ s/%([a­fA­F0­9][a­fA­F0­9])/pack("C", hex($1))/eg;
    $dato{$name} = $value;
};

Este siguiente bloque nos hace es desplegar todo el contenido de un fichero HTML dentro del contenedor 
$include   el   cual   es   el   que   se   usa   para   desplegar   dentro   de   la   variable   $contenido   en   la   plantilla 
“template.tmpl”; como es una función, solo hará su trabajo cuando la llamemos

# función para desplegar un f ichero html
sub desplegar{
  open(ARCHIVO, $file) || die "No se pudo abrir archivo";
     while(!eof(ARCHIVO)){
        $clave=<ARCHIVO>;
        # se guarda en include el documento html completo
        $include = $include.$clave;
        }
  close(ARCHIVO);
};

Nuestras siguientes líneas son sencillas:

#creamos un menu de las secciones de nuestra pagina web ej.
 my @menu = (
   {vinculo => 'Perl'},
   {vinculo => 'PHP5'},
   {vinculo => 'ASP'},
 );

Acá lo que hacemos es crear un array de hash para crear el menú, como puedes ver esta es la forma donde 
decides   que   secciones   incluir,   puedes   definir   de   una   vez   desde   aquí   los   vínculos   es   decir   remplazando 
{vinculo => ‘perl’} por {vinculo => ‘ <a ref.=’config.pl?go=perl’>Perl</a> ’} con esto ya tienes para que el 
menú del template en vez de dejarte solo texto, te cree ya un vínculo activo para ser manipulado por el 
config.pl;   también   si   deseas   puedes   remplazar   las   etiquetas   de   tu   template.tmpl   para   que   te   ponga 
directamente las etiquetas de hipervínculos “<a ref.> y</a>” y así te ahorras de ensuciar un poco tu código 
perl pero si la plantilla ej:

Código de Plantilla actual:
<tmpl_loop name="menu"> 
<tr> 
 <td><tmpl_var name="vinculo"></td> 
 </tr> 
</tmpl_loop>

Código de Plantilla propuesta
<tmpl_loop name="menu"> 
<tr> 
  <td> <a
    href="config.pl?go=<tmpl_var name="vinculo">" <tmpl_var name="vinculo"> </a></td> 
 </tr> 
</tmpl_loop>

Con esta propuesta listo solamente si tus archivos son extensión html te será útil y creo que es así, ya te 
evitastes ensuciar tu código perl, el automáticamente te hace los vínculos tomando como referencia el valor 
de la variable en el hash y suponiendo que el nombre del archivo html a incluir es el mismo valor del valor de 
la llave actual del hash y su extensión es html.

Ahora ustedes quieren saber como puedo incluir otra cosa que no sea un simple dato de una variable y un 
documento html completo; bueno acá les indicare como pueden hacerlo estoy seguro que con esto ya se hacen 
idea de cómo pueden hacerlo 

if ($dato{'go'} eq "home") {
  $include = "<img src='imagen.jpg'>";
}elsif ($dato{'go'} eq "contactos") {
   $file = "contactos.html";
   #llamamos el procedimiento que desplega el fichero HTML en el include
   &desplegar
}elsif ($dato{'go'} eq "") {
 $include = "<img src='imagen.jpg'>";
}else{
   # en caso de lo contrario abre un documento con el nombre guardado en $dato{'go'} .html
   $file = $dato{'go'}."html";
   &desplegar
};

Si el valor de la llave dato{‘go’} es equivalente a home entonces la variable $include toma el valor de una 
etiqueta html que me dice que lo que quiero  es una imagen $include = "<img src='imagen.jpg'>"

Explicando también como es que se hace para desplegar quizas un vínculo que es un documento HTML que 
no este en nuetro menú, usamos el siguiente elsif

}elsif ($dato{'go'} eq "contactos") {
   $file = "contactos.html";
   #llamamos el procedimiento que desplega el fichero HTML en el include
   &desplegar
}

Esto   nos   despliega   el   fichero   llamado   contactos.html;   es   acá   donde   llamamos   la   función   desplegar   que 
sencillamente el archivo a desplegar es el que contenga la variable $file, en este caso es contactos, pero en el 
caso del menú es otro que ya lo explicaremos

elsif ($dato{'go'} eq "") {
 $include = "<img src='imagen.jpg'>";
}

Sencillamente si no toma ningún valor en este caso queremos que nos regrese al home, o en otras palabras 
que nos incluya la misma imagen para cuando la llave es equivalente a “home”

Si no se cumple ninguno de los casos , entonces ahora es donde juega lo que hicimos en el menú.

else{
   #en caso de lo contrario abre un documento con el nombre guardado en $dato{'go'} .html
   $file = $dato{'go'}."html";
   &desplegar
};

El $file que se utilizara en el procedimiento o función como lo llamo yo será el mismo valor de la llave actual 
mas la extensión “html” así nos evitamos tener que crear como me toco hacer en php menús en una base de 
datos y después hacer esa conexión a BD y etc… me imagino que en este nivel ya sabrán a lo que me refiero.

#indicamos como se llama la plantilla a utilizar
$plantilla = "template.tmpl";
# Salida de la plantilla
my $template = HTML::Template­>new(filename => $plantilla);
 $template­>param(contenido => $include );
 $template­>param(menu => \@menu  );
 print "Content­Type: text/html\n\n", $template­>output;

y ya este ultimo bloque (y no me refiero a bloques en términos de programación si no a bloques en términos 
de textos) tenemos definido cual es la plantilla que queremos utilizar  $plantilla = "template.tmpl" y el resto 
ya lo saben lo que contendrá la variable de template sera lo que tenga contenido “$include” y bueno ahí 
vemos como desplegamos el menú también  $template­>param(menu => \@menu    );

Si ustedes me preguntan si lo que quieren es una conexión a una base de datos un gif un flash,, bueno lo 
mismo colocan las etiquetas necesarias para llamar el flash el script, active x, o lo que deseen,  claro que en 
el caso de una conexión a base de datos lo mejor es crear un procedimiento y guardar todo el despliegue 
HTML  dentro de una variable contenedor.
Daniel Bermudez es un Colombiano igual que yo y administrador del espectacular foro  aprender­python, 
promueve la enseñanza de este lenguaje de programación tan emocionante y pues hace poco promovió un 
curso en el foro para aprender Python, del cual soy asiduo lector, acá dejo esta entrevista que nos ha regalado.

1) ¿De dónde eres?
Colombia, Bogota 9) ¿Que te gustaría ver en los próximos años en el 
mundo de la programación?
2) ¿Hace cuánto que comenzaste a programar? Un lenguaje de programacion totalmente en Español.
Hace 2 años aproximadamente.
10) ¿Cuál es tu mensaje final para la comunidad?
3)   ¿Cuáles   son   tus   lenguajes   de   programación Como lo dijo alguien: Ignorante no es el que no sabe 
favoritos? leer, sino el que sabiendo leer no lee.
Primeroque nada Python, PHP, y pues los demas no 
losconozco mucho.

4) ¿Cuáles son tus programas favoritos de Diseño?
Flash   es   mi   favorito,   Firework   meparece   excelente 
para   la   edicion   de   imagenes,   claroque   sin 
menospreciar   los   otros   programascomo   Photoshop, 
Corel Draw e Illustrater.

5) ¿Qué te inspiró a ser programador?
Bueno   la   verdad   Python   ver   su   sintaxis   la   facilidad 
deaprendizaje  el  ver el potencialque tenia, todos  los 
modulos que tiene, ademas libre, ysepresta desarrollar 
cualquier aplicacion.

6) ¿Cuéntanos un poco acerca de tu compañía?
Actualmente no tengo compañia, pero a futuros tengo 
planeado crear una dedicada al software libre.

7) ¿Qué opinas de la escena de programadores en 
Latinoamérica?
Bueno creo que no somos los mejores pero tampoco 
los mas malos, creo que aun falta mucho para llegar a 
ser los mejores.

8) ¿Cuáles son tus nuevos proyectos?
Continuarcon el proyecto de Aprender Python, trabajar 
para   difundir   Python   y   que   todo   mundose   anime   a 
aprenderlo   y   vean   lo   facil   y   podero   que   puedeser, 
tambien crear un futuro proyecto ya con bases de datos 
que es otra de mispasiones.
Software para captura de inventarios
Por RadicalEd http://radicalpython.blogspot.com
Como no todo es Python en esta vida :'( , hace rato pusé en el blog que iba a compartir un software para 
captura de inventarios, primero lo probé en el trabajo y ya puedo soltar esta pequeña casí belleza, no tiene 
módulos grandes, tampoco POO (no manejo POO en PHP) pero es funcional y nos ha hecho quedar bien; 
colocaré cada módulo y pues como están comentados no necesitan mucha explicación.

Lo  voy  a dejar   con  los  datos  de ejemplo para que se pueda obtener información de este y practicar,  el 


software se maneja a la perfección con códigos de barras, tanto en los productos como en las ubicaciones de 
la bodega, ya verán ustedes como lo modificaran a sus gustos.

Esta obra está bajo Licencia Atribución­No Comercial 2.5 Colombia License de Creative Commons.

Empecemos por el script SQL que se necesita para que funcióne el programa:

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";

CREATE TABLE IF NOT EXISTS `tbinventario_bodega` (
 `id` int(2) NOT NULL AUTO_INCREMENT,
 `ubicacion` varchar(25) NOT NULL,
 `nombre` varchar(50) NOT NULL,
 `código` varchar(15) NOT NULL,
 `conteo` varchar(1) NOT NULL DEFAULT '0',
 `cerrado` varchar(1) NOT NULL DEFAULT '0',
 `asig_planilla` varchar(1) NOT NULL DEFAULT '0',
 `num_planilla` varchar(5) NOT NULL DEFAULT '0',
 PRIMARY KEY (`id`),
 KEY `código` (`código`)
);

CREATE TABLE IF NOT EXISTS `tbinventario_conteos` (
 `id` int(2) NOT NULL AUTO_INCREMENT,
 `item_código` varchar(10) NOT NULL,
 `posicion` varchar(8) NOT NULL,
 `primer` varchar(5) NOT NULL,
 `segundo` varchar(5) NOT NULL,
 `tercer` varchar(5) NOT NULL,
 `conto_primero` varchar(3) NOT NULL,
 `conto_segundo` varchar(3) NOT NULL,
 `conto_tercero` varchar(3) NOT NULL,
 PRIMARY KEY (`id`)
);
CREATE TABLE IF NOT EXISTS `tbinventario_errores` (
 `id` int(2) NOT NULL AUTO_INCREMENT,
 `id_user` varchar(2) NOT NULL,
 `posicion` varchar(8) NOT NULL,
 `item` varchar(10) NOT NULL,
 `conteo` varchar(1) NOT NULL,
 PRIMARY KEY (`id`)
);

CREATE TABLE IF NOT EXISTS `tbinventario_items` (
 `id` int(5) NOT NULL AUTO_INCREMENT,
 `código` varchar(10) NOT NULL,
 `nombre` varchar(45) NOT NULL,
 `conteo` varchar(1) NOT NULL DEFAULT '0',
 `unidad` varchar(5) NOT NULL,
 `precio` varchar(11) NOT NULL,
 `cantidad` varchar(5) DEFAULT NULL,
 `cod_barra01` varchar(15) DEFAULT NULL,
 `cod_barra02` varchar(15) DEFAULT NULL,
 `cod_barra03` varchar(15) DEFAULT NULL,
 `cod_barra04` varchar(15) DEFAULT NULL,
 `cod_barra05` varchar(15) DEFAULT NULL,
 `cod_barra06` varchar(15) DEFAULT NULL,
 `cod_barra07` varchar(15) DEFAULT NULL,
 `cod_barra08` varchar(15) DEFAULT NULL,
 `cod_barra09` varchar(15) DEFAULT NULL,
 PRIMARY KEY (`id`)
);

CREATE TABLE IF NOT EXISTS `tbinventario_planilla` (
 `id` int(2) NOT NULL AUTO_INCREMENT,
 `contado` varchar(20) DEFAULT NULL,
 PRIMARY KEY (`id`)
);

CREATE TABLE IF NOT EXISTS `tbinventario_subconteo` (
 `id` int(2) NOT NULL AUTO_INCREMENT,
 `cod_item` varchar(10) NOT NULL,
 `cod_bodega` varchar(10) NOT NULL,
 `cantidad` varchar(4) NOT NULL,
 `indexado` varchar(1) NOT NULL,
 `indexado_por` varchar(3) NOT NULL,
 PRIMARY KEY (`id`)
);
CREATE TABLE IF NOT EXISTS `tbinventario_ubicacion` (
 `id` int(4) NOT NULL AUTO_INCREMENT,
 `rak` varchar(1) NOT NULL,
 `cara` varchar(1) NOT NULL,
 `piso` varchar(1) NOT NULL,
 `ubicacion` varchar(1) NOT NULL,
 `item` varchar(10) NOT NULL,
 `conteo1` varchar(4) NOT NULL,
 `conteo2` varchar(4) DEFAULT NULL,
 `conteo3` varchar(4) DEFAULT NULL,
 PRIMARY KEY (`id`)
);

CREATE TABLE IF NOT EXISTS `tbinventario_users` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `login` varchar(10) NOT NULL,
 `password` varchar(35) NOT NULL,
 `tipo` varchar(2) NOT NULL,
 `nombre` varchar(45) NOT NULL,
 `companero` varchar(45) NOT NULL,
 PRIMARY KEY (`id`)
);

Ahora trabajemos con los scripts; no voy a explicar ni el de conexión ni el de hacer el formulario de login ni 
nada de eso :P 

index2.php
<?php  
  include 'configuration.php';
  $id = $_GET['id'];
  $tipo = $_GET['tipo'];
?>
<!DOCTYPE HTML PUBLIC '­//W3C//DTD HTML 4.01 Transitional//EN'>
<html>
<head>
<title>Pantalla Inicial</title>
<meta http­equiv="Content­Type" content="text/html; charset=iso­8859­1">
<!­­ PARA REFRESCAR LA P&#193;GINA CON UN INTERVALO DE 60 SEGUNDOS !­­>
<meta http­equiv="refresh" content="10">
<LINK REL="StyleSheet" HREF="style.css" TYPE="text/css">
</head>
<body>
<?php
  //CON ESTA SE ACTIVARAN LOS CONTEOS
  $query_conteos = "SELECT * FROM tbinventario_planilla";
  $result_conteos = mysql_query($query_conteos) or die(mysql_error());

  if ($row_conteos=mysql_fetch_array($result_conteos))
  {
   $cual_conteo = $row_conteos[1];
  }
?>
<div align="center">
<table border=1 cellpadding=1 cellspacing=1>
<?php
  //PARA MOSTRAR LOS ENLACES A LOS CONTEOS
  if ($cual_conteo==1 || $tipo==69)
  {
?>
<tr>
 <td>
  <a href="javascript: window.open('conteo.php?conteo=1&id=<? echo $id; ?
>','','resizable=yes,scrollbars=yes,width=400,height=400,menubar=no,status=yes,top=1,left=1').focus();">
   Primer Conteo
  </a> 
 </td>
 <td align='center'>­­></td>
 <td>
  <a href="javascript: window.open('conteo.php?conteo=4&id=<? echo $id; ?
>','','resizable=yes,scrollbars=yes,width=400,height=400,menubar=no,status=yes,top=1,left=1').focus();">
   C&oacute;digo de Barras
  </a>
 </td>
</tr>
<?php
  }
  //PARA MOSTRAR LOS ENLACES A LOS CONTEOS
  if ($cual_conteo==2 || $tipo==69)
  {
?>
<tr>
 <td>
  <a href="javascript: window.open('conteo.php?conteo=2&id=<? echo $id; ?
>','','resizable=yes,scrollbars=yes,width=400,height=400,menubar=no,status=yes,top=1,left=1').focus();">
   Segundo Conteo
  </a>
 </td>
 <td align='center'>­­></td>
 <td>
  <a href="javascript: window.open('conteo.php?conteo=5&id=<? echo $id; ?
>','','resizable=yes,scrollbars=yes,width=400,height=400,menubar=no,status=yes,top=1,left=1').focus();">
   C&oacute;digo de Barras
  </a>
 </td>
</tr>
<?php
  }
  //PARA MOSTRAR LOS ENLACES A LOS CONTEOS
  if ($cual_conteo==3 || $tipo==69)
  {
?>
<tr>
 <td>
  <a href="javascript: window.open('conteo.php?conteo=3&id=<? echo $id; ?
>','','resizable=yes,scrollbars=yes,width=400,height=400,menubar=no,status=yes,top=1,left=1').focus();">
   Tercer Conteo
  </a>
 </td>
 <td align='center'>­­></td>
 <td>
  <a href="javascript: window.open('conteo.php?conteo=6&id=<? echo $id; ?
>','','resizable=yes,scrollbars=yes,width=400,height=400,menubar=no,status=yes,top=1,left=1').focus();">
   C&oacute;digo de Barras
  </a>
 </td>
</tr>
<?php
  }
  if ($tipo==3 || $tipo==69)
  {
?>
<tr>
 <td>
  <a href="javascript: window.open('consultar.php?conteo=<? echo $cual_conteo; ?>&id=<? echo $id; ?
>','','resizable=yes,scrollbars=yes,width=400,height=400,menubar=no,status=yes,top=1,left=1').focus();">
   Modificar Datos
  </a>
 </td>
<?php
  }
?>
 <td>
  <a href="./ver_items.php?show=0&forma=1&tipo=<? echo $tipo; ?>" target="_blank">
   Conteos
  </a>
 </td>
 <td>
<?php
  //PARA MOSTRAR LOS ENLACES A LOS CONTEOS
  if ($tipo==69)
  {
?>
 <a href="./items.php?show=0&forma=1" target="_blank">
  Items
 </a>
<? } ?>
 </td>
</tr>
</table>
<?php
  //PARA MOSTRAR LOS ENLACES A LOS CONTEOS
  if ($tipo==69)
  {
?><br>
<form name='cuentaconteos' method="post" action="<? $_SERVER['PHP_SELF']; ?>">
 <input type='hidden' name='contadito' value='<?php echo $cual_conteo; ?>' READONLY>
 <input type='submit' name='elconteo' value='<?php $cual_conteo += 1; if ($cual_conteo<=3) { echo 'Activar conteo '.
$cual_conteo; }else{ echo 'Conteos terminados'; }?>'>
</form>
<?php
  if ($_POST['elconteo'])
  {
   $contadito = $_POST['contadito'];
   $contadito += 1;
   $query_upd = "UPDATE tbinventario_planilla SET contado='".$contadito."'";
   $result_upd = mysql_query($query_upd) or die(mysql_error());
  }
?>
<?php
  //SABER CUANTOS HAN SIDO CONTADOS
  $query_porcen = "SELECT * FROM tbinventario_bodega WHERE ubicacion LIKE 'Bodega 12 Punto Sur'";
  $result_porcen = mysql_query($query_porcen) or die(mysql_error);

  $numrows = mysql_num_rows($result_porcen);

  while($row_porcen=mysql_fetch_array($result_porcen))
  {
    $sumatoria = $row_porcen[4];
    if ($sumatoria==1)
    {
      $vale += 1;
    } 
  }

  $por_conteos = round($vale/$numrows*100,2);
?>
<table border=1 cellspacing=1 cellpadding=1>
 <tr>
  <td class="letratd" align="center" colpan="4"><b>EL INVENTARIO LLEVA UN <? echo $por_conteos; ?>% DE 
CONTEO</b></td>
 </tr>
</table>
<table border=1 cellspacing=1 cellpadding=1>
 <tr>
  <td class="letratd" align="center" colspan=4"><b>ESTOS GRUPOS HICIERON RECONTEO SOBRE POSICIONES YA 
CONTADAS</b></td>
 </tr>
 <tr>
  <td class="letratd" align="center"><b>GRUPO</b></td>
  <td class="letratd" align="center"><b>POSICION</b></td>
  <td class="letratd" align="center"><b>ITEM</b></td>
  <td class="letratd" align="center"><b>CONTEO</b></td>
 </tr>

 <?php
  //PARA LISTAR A LOS INTELIGENTES QUE LA HAYAN EMBARRADO Y HAYAN VUELTO A CONTAR UN ITEM
  $query = "SELECT * FROM tbinventario_errores";
  $result = mysql_query($query) or die(mysql_error());

  while($row=mysql_fetch_array($result))
  {
   $id_user = $row[1];
   $posicion = $row[2];
   $item = $row[3];
   $conteo = $row[4];

   //HACEMOS QUERY AL USUARIO
   $query_user = "SELECT * FROM tbinventario_users WHERE id=".$id_user;
   $result_user = mysql_query($query_user) or die(mysql_error());

   if($row_user=mysql_fetch_array($result_user))
   {
    $nombre1 = $row_user[4];
    $nombre2 = $row_user[5];
   }

   //HACEMOS QUERY A LA POSICION
   $query_posi = "SELECT * FROM tbinventario_bodega WHERE código=".$posicion;
   $result_posi = mysql_query($query_posi) or die(mysql_error());

   if($row_posi=mysql_fetch_array($result_posi))
   {
    $ubicacion = $row_posi[1];
    $nombre = $row_posi[2];
   }

   //HACEMOS QUERY A LA POSICION
   $query_item = "SELECT * FROM tbinventario_items WHERE código LIKE '".$item."'";
   $result_item = mysql_query($query_item) or die(mysql_error());

   if($row_item=mysql_fetch_array($result_item))
   {
    $nombre_item = $row_item[2];
   }
   echo '<tr><td class="letratd" align="center">'.$nombre1.'<br>'.$nombre2.'</td><td class="letratd" align="center">'.
$ubicacion.'<br>'.$nombre.'</td><td class="letratd" align="center">'.$nombre_item.'</td><td class="letratd" align="center">'.
$conteo.'</td></tr>';
  }
?>
</table>
<? } ?>
</div>
</body>
</html>

conteo.php
<?php
  include 'configuration.php';
  $conteo = $_GET['conteo'];
  $id_cuenta = $_GET['id'];
?>
<!DOCTYPE html PUBLIC "­//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1­
transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http­equiv="Content­Type" content="text/html; charset=iso­8859­1" />
<title>Ingreso Conteo ITEMS</title>
<LINK REL="StyleSheet" HREF="style.css" TYPE="text/css">
<?php
  echo '<script languaje="JavaScript">
 function OpenPopup(texto1, texto2, texto3)
 {
  window.open("captura.php?conteo=" + texto1 + "&id=" + texto2 + "&posicion=" + texto3, "_self", 
"width=400,height=400,toolbar=no,menubar=no,directories=yes,status=yes,resizable=no,location=yes,scrollbars=yes")
 }
 function cargar()
 {';
 if ($conteo==1 || $conteo==4)
 {
  echo 'f = document.frmconteo1;';
 }
 elseif ($conteo==2 || $conteo==5)
 {
  echo 'f = document.frmconteo2;';
 }
 else
 {
  echo 'f = document.frmconteo3;';
 }
 echo 'if (f)
        {
   if (f.posicion.value == null || f.posicion.value == "")
         { 
    f.posicion.focus();
   }
  } 
 }
</script>';
?>
</head>
<body onLoad="cargar()">
<div align="center">
<?php
 if($conteo==1 || $conteo==4)
 {
?>
  <form name="frmconteo1" method="post" action="<? $_SERVER['PHP_SELF']; ?>">
   <table border="1" cellspacing="1" cellpadding="1">
    <tr>
     <td class="letratd" align="center"><b>POSICI&Oacute;N</b></td>
    </tr>
    <tr>
     <td class="letratd" align="center"><input type="text" name="posicion" style="text­align:center;" size="10" 
maxlength="8"></td>
    </tr>
    <tr>
     <td class="letratd" align="center" colspan="3">
      <input type="hidden" name="conteo" value="<? echo $conteo; ?>"> 
      <input type="hidden" name="id" value="<? echo $id_cuenta; ?>"> 
      <!­­<input type="button" class="button" name="guardar1" value="Continuar" onClick="OpenPopup(frmconteo1.conteo.value, 
frmconteo1.id.value, frmconteo1.posicion.value)">!­­>
      <input type="submit" class="button" name="guardar1" value="Continuar">
     </td>
    </tr>
   </table>
  </form>
<?php
 }
 elseif($conteo==2 || $conteo==5)
 {
?>
  <form name="frmconteo2" method="post" action="<? $_SERVER['PHP_SELF']; ?>">
   <table border="1" cellspacing="1" cellpadding="1">
    <tr>
     <td class="letratd" align="center"><b>POSICI&Oacute;N</b></td>
    </tr>
    <tr>
     <td class="letratd" align="center"><input type="text" name="posicion" style="text­align:center;" size="10" 
maxlength="8"></td>
    </tr>
    <tr>
     <td class="letratd" align="center" colspan="3">
       <input type="hidden" name="conteo" value="<? echo $conteo; ?>"> 
       <input type="hidden" name="id" value="<? echo $id_cuenta; ?>"> 
       <!­­<input type="button" class="button" name="guardar2" value="Continuar" 
onClick="OpenPopup(frmconteo2.conteo.value, frmconteo2.id.value, frmconteo2.posicion.value)">!­­>
       <input type="submit" class="button" name="guardar2" value="Continuar">
     </td>
    </tr>
   </table>
  </form>
<?php
 }
 else
 {
?>
  <form name="frmconteo3" method="post" action="<? $_SERVER['PHP_SELF']; ?>">
   <table border="1" cellspacing="1" cellpadding="1">
    <tr>
     <td class="letratd" align="center"><b>POSICI&Oacute;N</b></td>
    </tr>
    <tr>
     <td class="letratd" align="center"><input type="text" name="posicion" style="text­align:center;" size="10" 
maxlength="8"></td>
    </tr>
    <tr>
     <td class="letratd" align="center" colspan="3">
       <input type="hidden" name="conteo" value="<? echo $conteo; ?>">
       <input type="hidden" name="id" value="<? echo $id_cuenta; ?>"> 
       <!­­<input type="button" class="button" name="guardar3" value="Continuar" 
onClick="OpenPopup(frmconteo3.conteo.value, frmconteo3.id.value, frmconteo3.posicion.value)">!­­>
       <input type="submit" class="button" name="guardar3" value="Continuar">
     </td>
    </tr>
   </table>
  </form>
<? } ?>
</div>
</body>
</html>
<?php
  if ($_POST['guardar1'])
  {
    echo $posicion = $_POST['posicion'];
    echo $conteo = $_POST['conteo'];
    echo $id = $_POST['id'];
    echo '<script languaje="JavaScript">
            OpenPopup('.$conteo.', '.$id.', '.$posicion.');
          </script>';
  }

  if ($_POST['guardar2'])
  {
    echo $posicion = $_POST['posicion'];
    echo $conteo = $_POST['conteo'];
    echo $id = $_POST['id'];
    echo '<script languaje="JavaScript">
            OpenPopup('.$conteo.', '.$id.', '.$posicion.');
          </script>';
  }

  if ($_POST['guardar3'])
  {
    echo $posicion = $_POST['posicion'];
    echo $conteo = $_POST['conteo'];
    echo $id = $_POST['id'];
    echo '<script languaje="JavaScript">
            OpenPopup('.$conteo.', '.$id.', '.$posicion.');
          </script>';
  }
?>

captura.php
<?php
  include 'configuration.php';
  $conteo = $_GET['conteo'];
  $posicion = $_GET['posicion'];
  $id_cuenta = $_GET['id'];
?>
<!DOCTYPE html PUBLIC "­//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1­
transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http­equiv="Content­Type" content="text/html; charset=iso­8859­1" />
<title>Ingreso Conteo ITEMS</title>
<LINK REL="StyleSheet" HREF="style.css" TYPE="text/css">
<script type="text/javascript" src="./ajax.js"></script>
</head>
<body>
<div align="center">
<?php
 //VEMOS SI LA POSICION EXISTE 
 $query_posiexist = "SELECT * FROM tbinventario_bodega WHERE código LIKE '".$posicion."'";
 $result_posiexist = mysql_query($query_posiexist) or die(mysql_error);

 $numrows = mysql_num_rows($result_posiexist);

 if ($numrows==0)
 {
  echo "<blink class='letratd'><font color='#0000ff'>LA POSICI&Oacute;N ".$posicion." NO EXISTE</font></blink><br>
     <a href='conteo.php?conteo=".$_GET['conteo']."&id=".$_GET['id'].">Volver</a>";
 }
 else
 { 
  if ($row_posiexist=mysql_fetch_array($result_posiexist))
  {
   echo $row_posiexist[1]."<br>".$row_posiexist[2];
  }
 }
 if($conteo==1 || $conteo==4)
 {
?>
  <div id="capaInfo" class="letratd"><b>Nombre del ITEM</b></div>
        <form name="frmconteo1" method="post" action="<? $_SERVER['PHP_SELF']; ?>">
   <table border="1" cellspacing="1" cellpadding="1">
    <tr>
     <?php if ($conteo==1){ ?><td class="letratd" align="center"><b>C&Oacute;DIGO ITEM</b></td>
     <td class="letratd" align="center"><b>CANTIDAD</b></td>
     <?php } elseif ($conteo==4){ ?><td class="letratd" align="center"><b>CANTIDAD</b></td>
     <td class="letratd" align="center"><b>C&Oacute;DIGO BARRAS</b></td> <? } ?>
     <td class="letratd" align="center"><b>POSICI&Oacute;N</b></td>
    </tr>
    <tr>
     <?php if ($conteo==1){ ?><td class="letratd" align="center"><input type="text" name="items" 
onblur="traerDatos(frmconteo1.items.value)" style="text­align:center;" size="12" maxlength="10" <? if ($numrows==0){ echo 
'disabled';} ?>></td>
     <td class="letratd" align="center"><input type="text" name="cantidad" style="text­align:center;" size="5" maxlength="5" <? if 
($numrows==0){ echo 'disabled';} ?>></td>
     <?php } elseif ($conteo==4){ ?><td class="letratd" align="center"><input type="text" name="cantidad" style="text­
align:center;" size="5" maxlength="5" <? if ($numrows==0){ echo 'disabled';} ?>></td>
     <td class="letratd" align="center"><input type="text" name="item" style="text­align:center;" size="12" maxlength="28" <? if 
($numrows==0){ echo 'disabled';} ?>></td><? } ?>
     <td class="letratd" align="center"><input type="text" name="posicion" style="text­align:center;" size="10" maxlength="8" 
value="<? echo $posicion; ?>" readonly="readonly"></td>
    </tr>
    <tr>
     <td class="letratd" align="center" colspan="3">
      <input type="hidden" name="conteo" value="<? echo $conteo; ?>"> 
      <input type="hidden" name="id_cuenta" value="<? echo $id_cuenta; ?>"> 
      <input type="submit" class="button" name="save" value="Capturar"> 
      <input type="submit" class="button" name="guardar1" value="Guardar"> 
     </td>
    </tr>
   </table>
  </form>
   <table border="1" cellspacing="1" cellpadding="1">
                <tr>
                 <td class="letratd" align="center" colspan="4"><b>POSICI&Oacute;N <? echo $posicion; ?></b></td>
    </tr>
    <tr>
     <td class="letratd" align="center"><b>C&Oacute;DIGO ITEM</b></td>
     <td class="letratd" align="center"><b>DESC ITEM</b></td>
     <td class="letratd" align="center"><b>CANTIDAD</b></td>
     <td class="letratd" align="center"><b>ELIMINAR</b></td>
    </tr>
                <?php
                  //SE VA A IMPRIMIR UNA TABLA CON LOS ITEMS QUE SE INDEXARAN DENTRO DE LA TABLA 
tbinventario_conteos
                  $query_sacar = "SELECT * FROM tbinventario_subconteo WHERE cod_bodega LIKE '".$posicion."' AND 
indexado=0";
                  $result_sacar = mysql_query($query_sacar) or die(mysql_error());

                  echo $numrows = mysql_num_rows($result_sacar);

                  while ($row_sacar=mysql_fetch_array($result_sacar))
                  {
                         $id_sub = $row_sacar[0];
                   $cod_item = $row_sacar[1];

                         $query_item = "SELECT * FROM tbinventario_items WHERE código LIKE '".$cod_item."'";
                         $result_item = mysql_query($query_item) or die(mysql_error());

                         if ($row_item=mysql_fetch_array($result_item))
                         {
                          $nombre_item = $row_item[2];
                         }
                         $cantidad = $row_sacar[3];
                         echo "<tr>
                             <td class='letratd' align='center'>".$cod_item."</td>
                                         <td class='letratd' align='center'>".$nombre_item."</td>
                                         <td class='letratd' align='center'>".$cantidad."</td>
                                         <td class='letratd' align='center'>";
                ?>
                       <a href='javascript: window.open("edi_eli.php?conten=<? echo $id_sub; ?>&conteo=<? echo $conteo; ?
>&id_cuenta=<? echo $conteo; ?>&posicion=<? echo $posicion; ?
>","","resizable=yes,scrollbars=yes,width=250,height=80,menubar=no,status=yes,top=1,left=1").focus();'><img src='b_drop.png' 
border=0></a></td>
                <?php   
                         echo "</tr>";
                  }
                ?>
         </table>
<?php
 }
 elseif($conteo==2 || $conteo==5)
 {
?>
  <div id="capaInfo" class="letratd"><b>Nombre del ITEM</b></div>
        <form name="frmconteo2" method="post" action="<? $_SERVER['PHP_SELF']; ?>">
   <table border="1" cellspacing="1" cellpadding="1">
    <tr>
     <?php if ($conteo==2){ ?><td class="letratd" align="center"><b>C&Oacute;DIGO ITEM</b></td>
     <td class="letratd" align="center"><b>CANTIDAD</b></td>
     <?php } elseif ($conteo==5){ ?><td class="letratd" align="center"><b>CANTIDAD</b></td>
     <td class="letratd" align="center"><b>C&Oacute;DIGO BARRAS</b></td> <? } ?>
     <td class="letratd" align="center"><b>POSICI&Oacute;N</b></td>
    </tr>
    <tr>
     <?php if ($conteo==2){ ?><td class="letratd" align="center"><input type="text" name="items" 
onblur="traerDatos(frmconteo2.items.value)" style="text­align:center;" size="12" maxlength="10"></td>
     <td class="letratd" align="center"><input type="text" name="cantidad" style="text­align:center;" size="5" 
maxlength="5"></td>
     <?php } elseif ($conteo==5){ ?>
     <td class="letratd" align="center"><input type="text" name="cantidad" style="text­align:center;" size="5" 
maxlength="5"></td>
     <td class="letratd" align="center"><input type="text" name="item" style="text­align:center;" size="12" 
maxlength="28"></td><? } ?>
     <td class="letratd" align="center"><input type="text" name="posicion" style="text­align:center;" size="10" maxlength="8" 
value="<? echo $posicion; ?>" readonly="readonly"></td>
    </tr>
    <tr>
     <td class="letratd" align="center" colspan="3">
      <input type="hidden" name="conteo" value="<? echo $conteo; ?>"> 
      <input type="hidden" name="id_cuenta" value="<? echo $id_cuenta; ?>"> 
      <input type="submit" class="button" name="save" value="Capturar">
      <input type="submit" class="button" name="guardar2" value="Guardar"> 
     </td>
    </tr>
   </table>
  </form>
   <table border="1" cellspacing="1" cellpadding="1">
                <tr>
                 <td class="letratd" align="center" colspan="4"><b>POSICI&Oacute;N <? echo $posicion; ?></b></td>
    </tr>
    <tr>
     <td class="letratd" align="center"><b>C&Oacute;DIGO ITEM</b></td>
     <td class="letratd" align="center"><b>DESC ITEM</b></td>
     <td class="letratd" align="center"><b>CANTIDAD</b></td>
     <td class="letratd" align="center"><b>ELIMINAR</b></td>
    </tr>
                <?php
                  //SE VA A IMPRIMIR UNA TABLA CON LOS ITEMS QUE SE INDEXARAN DENTRO DE LA TABLA 
tbinventario_conteos
                  $query_sacar = "SELECT * FROM tbinventario_subconteo WHERE cod_bodega LIKE '".$posicion."' AND 
indexado=0";
                  $result_sacar = mysql_query($query_sacar) or die(mysql_error());

                  echo $numrows = mysql_num_rows($result_sacar);

                  while ($row_sacar=mysql_fetch_array($result_sacar))
                  {
                         $id_sub = $row_sacar[0];
                   $cod_item = $row_sacar[1];

                         $query_item = "SELECT * FROM tbinventario_items WHERE código LIKE '".$cod_item."'";
                         $result_item = mysql_query($query_item) or die(mysql_error());

                         if ($row_item=mysql_fetch_array($result_item))
                         {
                          $nombre_item = $row_item[2];
                         }
                         $cantidad = $row_sacar[3];
                         echo "<tr>
                             <td class='letratd' align='center'>".$cod_item."</td>
                                         <td class='letratd' align='center'>".$nombre_item."</td>
                                         <td class='letratd' align='center'>".$cantidad."</td>
                                         <td class='letratd' align='center'>";
                ?>
                     <a href='javascript: window.open("edi_eli.php?conten=<? echo $id_sub; ?>&conteo=<? echo $conteo; ?
>&id_cuenta=<? echo $conteo; ?>&posicion=<? echo $posicion; ?
>","","resizable=yes,scrollbars=yes,width=250,height=80,menubar=no,status=yes,top=1,left=1").focus();'><img src='b_drop.png' 
border=0></a></td>
                <?php   
                         echo "</tr>";
                  }
                ?>
         </table>
<?php
 }
 else
 {
?>
  <div id="capaInfo" class="letratd"><b>Nombre del ITEM</b></div>
        <form name="frmconteo3" method="post" action="<? $_SERVER['PHP_SELF']; ?>">
   <table border="1" cellspacing="1" cellpadding="1">
    <tr>
     <?php if ($conteo==3){ ?><td class="letratd" align="center"><b>C&Oacute;DIGO ITEM</b></td>
     <td class="letratd" align="center"><b>CANTIDAD</b></td>
     <?php } elseif ($conteo==6){ ?><td class="letratd" align="center"><b>CANTIDAD</b></td>
     <td class="letratd" align="center"><b>C&Oacute;DIGO BARRAS</b></td> <? } ?>
     <td class="letratd" align="center"><b>POSICI&Oacute;N</b></td>
    </tr>
    <tr>
     <?php if ($conteo==3){ ?><td class="letratd" align="center"><input type="text" name="items" 
onblur="traerDatos(frmconteo3.items.value)" style="text­align:center;" size="12" maxlength="10"></td>
     <td class="letratd" align="center"><input type="text" name="cantidad" style="text­align:center;" size="5" 
maxlength="5"></td>
     <?php } elseif ($conteo==6){ ?>
     <td class="letratd" align="center"><input type="text" name="cantidad" style="text­align:center;" size="5" 
maxlength="5"></td>
     <td class="letratd" align="center"><input type="text" name="item" style="text­align:center;" size="12" 
maxlength="28"></td><? } ?>
     <td class="letratd" align="center"><input type="text" name="posicion" style="text­align:center;" size="10" maxlength="8" 
value="<? echo $posicion; ?>" readonly="readonly"></td>
    </tr>
    <tr>
     <td class="letratd" align="center" colspan="3">
      <input type="hidden" name="conteo" value="<? echo $conteo; ?>"> 
      <input type="hidden" name="id_cuenta" value="<? echo $id_cuenta; ?>"> 
      <input type="submit" class="button" name="save" value="Capturar"> 
      <input type="submit" class="button" name="guardar3" value="Guardar"> 
     </td>
    </tr>
   </table>
  </form>
   <table border="1" cellspacing="1" cellpadding="1">
                <tr>
                 <td class="letratd" align="center" colspan="4"><b>POSICI&Oacute;N <? echo $posicion; ?></b></td>
    </tr>
    <tr>
     <td class="letratd" align="center"><b>C&Oacute;DIGO ITEM</b></td>
     <td class="letratd" align="center"><b>DESC ITEM</b></td>
     <td class="letratd" align="center"><b>CANTIDAD</b></td>
     <td class="letratd" align="center"><b>ELIMINAR</b></td>
    </tr>
                <?php
                  //SE VA A IMPRIMIR UNA TABLA CON LOS ITEMS QUE SE INDEXARAN DENTRO DE LA TABLA 
tbinventario_conteos
                  $query_sacar = "SELECT * FROM tbinventario_subconteo WHERE cod_bodega LIKE '".$posicion."' AND 
indexado=0";
                  $result_sacar = mysql_query($query_sacar) or die(mysql_error());

                  echo $numrows = mysql_num_rows($result_sacar);

                  while ($row_sacar=mysql_fetch_array($result_sacar))
                  {
                         $id_sub = $row_sacar[0];
                   $cod_item = $row_sacar[1];

                         $query_item = "SELECT * FROM tbinventario_items WHERE código LIKE '".$cod_item."'";
                         $result_item = mysql_query($query_item) or die(mysql_error());
                         if ($row_item=mysql_fetch_array($result_item))
                         {
                          $nombre_item = $row_item[2];
                         }
                         $cantidad = $row_sacar[3];
                         echo "<tr>
                             <td class='letratd' align='center'>".$cod_item."</td>
                                         <td class='letratd' align='center'>".$nombre_item."</td>
                                         <td class='letratd' align='center'>".$cantidad."</td>
                                         <td class='letratd' align='center'>";
                ?>
                    <a href='javascript: window.open("edi_eli.php?conten=<? echo $id_sub; ?>&conteo=<? echo $conteo; ?
>&id_cuenta=<? echo $conteo; ?>&posicion=<? echo $posicion; ?
>","","resizable=yes,scrollbars=yes,width=250,height=80,menubar=no,status=yes,top=1,left=1").focus();'><img src='b_drop.png' 
border=0></a></td>
                <?php   
                         echo "</tr>";
                  }
                ?>
         </table>
<? } ?>
</div>
</body>
</html>
<?php
  //SE SALVARAN LOS DATOS EN LA TABLA tbinventario_subconteo
  if($_POST['save'])
  {
   $item = $_POST['item'];
   $cantidad = $_POST['cantidad'];
   $posicion = $_POST['posicion'];
   $conteo = $_POST['conteo'];
   $id_cuenta = $_POST['id_cuenta'];
         $items = $_POST['items'];

         echo "El item es ".$item;
   if ($conteo==4){ $contar=1; }
   if ($conteo==5){ $contar=2; }
   if ($conteo==6){ $contar=3; }

         if ($items)
         {
          echo $query_coditem = "SELECT * FROM tbinventario_items
                     WHERE código LIKE '".$items."'";
         }
         else
         {
          echo $query_coditem = "SELECT * FROM tbinventario_items
                     WHERE cod_barra01 LIKE '".$item."' OR cod_barra02 LIKE '".$item."'
                     OR cod_barra03 LIKE '".$item."' OR cod_barra04 LIKE '".$item."'
                     OR cod_barra05 LIKE '".$item."' OR cod_barra06 LIKE '".$item."'
                     OR cod_barra07 LIKE '".$item."' OR cod_barra08 LIKE '".$item."'
                     OR cod_barra09 LIKE '".$item."'";
         }
         $result_coditem = mysql_query($query_coditem) or die(mysql_error());

         if ($row_coditem=mysql_fetch_array($result_coditem));
         {
          $item = $row_coditem[1];
         }

  $query_sub = "INSERT INTO tbinventario_subconteo VALUES (NULL, '".$item."', '".$posicion."', '".$cantidad."', '0', '".
$id_cuenta."')";
         $result_sub = mysql_query($query_sub) or die(mysql_error());

         echo "<script languaje='JavaScript'>
             window.opener.location.href='captura.php?conteo=$conteo&id=$id_cuenta&posicion=$posicion';
                  </script>";

  }
  //UTILIZO EL METODO POST POR QUE EN MI UBUNTU NO ME funciona
  //LA FORMA TRADICIONAL (NO S&#201; POR QU&#201; :S)
  if($_POST['guardar1'])
  {
   $posicion = $_POST['posicion'];
   $conteo = $_POST['conteo'];
   $id_cuenta = $_POST['id_cuenta'];

         //COMO EL DESOCUPADO DE RENGIFO LO PUSO A HACER POR UN ARREGLO,
         //'TONS AHORA TOCA DE ESTA FORMA
         //PRIMERO SE LEE DE LA TABLA tbsdpel_subconteo, SE EXTRAEN LOS DATOS
         //Y SE INGRESAN EN LA TABLA tbinventario_conteos
         //echo $query_extraer = "SELECT * FROM tbinventario_subconteo WHERE cod_bodega LIKE '".$posicion."' AND 
indexado=0 AND indexado_por='".$id_cuenta."'";
         echo $query_extraer = "SELECT * FROM tbinventario_subconteo WHERE cod_bodega LIKE '".$posicion."' AND 
indexado=0";
         $result_extraer = mysql_query($query_extraer) or die(mysql_error());

         while ($row_extraer=mysql_fetch_array($result_extraer))
         {
          $cod_item = $row_extraer[1];
          $cantidad = $row_extraer[3];

          //SABER SI YA SE HIZO ESE CONTEO Y SI NO ES así GUARDAR EL REGISTRO
          $query_sabersi = "SELECT * FROM tbinventario_conteos WHERE item_código LIKE '".$cod_item."' AND posicion LIKE 
'".$posicion."'";
          $result_sabersi = mysql_query($query_sabersi) or die(mysql_error());

          //LE AGREGO LA CANTIDAD DE REGISTROS ENTREGADOS POR LA CONSULTA A UNA VARIABLE
          $numrows = mysql_num_rows($result_sabersi);

          if($numrows != 0)
          {
     echo "<div align='center'><b><font size=4>A ESTE ITEM YA SE LE HIZO PRIMER CONTEO</font></b></div>";
     $query_error1 = "INSERT INTO tbinventario_errores VALUES(NULL, '".$id_cuenta."', '".$posicion."', '".$cod_item."', '".
$conteo."')";
     $result_error1 = mysql_query($query_error1) or die(mysql_error());
    }
    else
    {
     echo $query_conteo1 = "INSERT INTO tbinventario_conteos VALUES(NULL, '".$cod_item."', '".$posicion."', '".$cantidad."', '', 
'', '".$id_cuenta."', '', '')";
     $result_conteo1 = mysql_query($query_conteo1) or die(mysql_error());
     echo "<div align='center'><b><font size=4>EL ITEM HA SIDO INDEXADO SATISFACTORIAMENTE</font></b></div>";
    }

    if($result_sabersi == 0)
    {
     echo "NO SE PUDO INDEXAR LA INFORMACION";
    }

          //AHORA SE ACTUALIZA LA TABLA tbinventario_subconteo EN SU CAMPO INDEXADO
          //PARA NO VOLVER A TOMAR ESOS ITEMS
          $query_upd = "UPDATE tbinventario_subconteo SET indexado=1 WHERE cod_item LIKE '".$cod_item."' AND 
cod_bodega LIKE '".$posicion."'";
          $result_upd = mysql_query($query_upd) or die(mysql_error());

         echo "<script languaje='JavaScript'>
              window.close();
                   </script>";

          //VAMOS DANDOLE AL ITEM EN QUE CONTEO VA
          $query_itemcontado = "UPDATE tbinventario_items SET conteo=".$conteo." WHERE código LIKE '".$cod_item."'";
          $result_itemcontado = mysql_query($query_itemcontado) or die(mysql_error());
   }
   //VAMOS A CERRAR LA POSICION DESPUES DE QUE SE INGRESEN LOS DATOS
         //EN LA TABLA tbinventario_bodega
         if ($conteo==4) { $conteo==1; }
         if ($conteo==5) { $conteo==2; }
         if ($conteo==6) { $conteo==3; }
         $query_cerrar = "UPDATE tbinventario_bodega SET cerrado=1, conteo=".$conteo." WHERE código LIKE '".$posicion."'";
         $result_cerrar = mysql_query($query_cerrar) or die(mysql_error());
  }

  if($_POST['guardar2'])
  {
   $posicion = $_POST['posicion'];
   $conteo = $_POST['conteo'];
   $id_cuenta = $_POST['id_cuenta'];

         //COMO EL DESOCUPADO DE RENGIFO LO PUSO A HACER POR UN ARREGLO,
         //'TONS AHORA TOCA DE ESTA FORMA
         //PRIMERO SE LEE DE LA TABLA tbsdpel_subconteo, SE EXTRAEN LOS DATOS
         //Y SE INGRESAN EN LA TABLA tbinventario_conteos
         $query_extraer = "SELECT * FROM tbinventario_subconteo WHERE cod_bodega LIKE '".$posicion."' AND indexado=0 
AND indexado_por='".$id_cuenta."'";
         $result_extraer = mysql_query($query_extraer) or die(mysql_error());
         while ($row_extraer=mysql_fetch_array($result_extraer))
         {
          $cod_item = $row_extraer[1];
          $cantidad = $row_extraer[3];

          //SABER SI YA SE HIZO ESE CONTEO Y SI NO ES así GUARDAR EL REGISTRO
          $query_sabersi = "SELECT * FROM tbinventario_conteos WHERE item_código LIKE '".$cod_item."' AND posicion=".
$posicion." AND segundo!=0";
      $result_sabersi = mysql_query($query_sabersi) or die(mysql_error());

     //LE AGREGO LA CANTIDAD DE REGISTROS ENTREGADOS POR LA CONSULTA A UNA VARIABLE
     $numrows = mysql_num_rows($result_sabersi);

     if($numrows != 0)
     {
       echo "<div align='center'><b><font size=4>A ESTE ITEM YA SE LE HIZO SEGUNDO CONTEO</font></b></div>";
       echo $query_error1 = "INSERT INTO tbinventario_errores VALUES(NULL, '".$id_cuenta."', '".$posicion."', '".$cod_item."', 
'".$conteo."')";
     $result_error1 = mysql_query($query_error1) or die(mysql_error());
    }
    else
    {
     $query_conteo2 = "UPDATE tbinventario_conteos SET segundo='".$cantidad."', conto_segundo='".$id_cuenta."' WHERE 
item_código LIKE '".$cod_item."' AND posicion='".$posicion."'";
     $result_conteo2 = mysql_query($query_conteo2) or die(mysql_error());
     echo "<div align='center'><b><font size=4>EL ITEM HA SIDO INDEXADO SATISFACTORIAMENTE ".
$cod_item."</font></b></div>";
    }

    if($result_sabersi == 0)
    {
     echo "NO SE PUDO INDEXAR LA INFORMACION";
    }

          //AHORA SE ACTUALIZA LA TABLA tbinventario_subconteo EN SU CAMPO INDEXADO
          //PARA NO VOLVER A TOMAR ESOS ITEMS
          $query_upd = "UPDATE tbinventario_subconteo SET indexado=1 WHERE cod_item LIKE '".$cod_item."' AND 
cod_bodega LIKE '".$posicion."'";
          $result_upd = mysql_query($query_upd) or die(mysql_error());

         echo "<script languaje='JavaScript'>
              window.close();
                   </script>";

          //VAMOS DANDOLE AL ITEM EN QUE CONTEO VA
          $query_itemcontado = "UPDATE tbinventario_items SET conteo=".$conteo." WHERE código LIKE '".$cod_item."'";
          $result_itemcontado = mysql_query($query_itemcontado) or die(mysql_error());
   }
         //VAMOS A CERRAR LA POSICION DESPUES DE QUE SE INGRESEN LOS DATOS
         //EN LA TABLA tbinventario_bodega
         $query_cerrar = "UPDATE tbinventario_bodega SET cerrado=1, conteo=".$conteo." WHERE código LIKE '".$posicion."'";
         $result_cerrar = mysql_query($query_cerrar) or die(mysql_error());
  }
  if($_POST['guardar3'])
  {
   $posicion = $_POST['posicion'];
   $conteo = $_POST['conteo'];
   $id_cuenta = $_POST['id_cuenta'];

         //COMO EL DESOCUPADO DE RENGIFO LO PUSO A HACER POR UN ARREGLO,
         //'TONS AHORA TOCA DE ESTA FORMA
         //PRIMERO SE LEE DE LA TABLA tbsdpel_subconteo, SE EXTRAEN LOS DATOS
         //Y SE INGRESAN EN LA TABLA tbinventario_conteos
         $query_extraer = "SELECT * FROM tbinventario_subconteo WHERE cod_bodega LIKE '".$posicion."' AND indexado=0 
AND indexado_por='".$id_cuenta."'";
         $result_extraer = mysql_query($query_extraer) or die(mysql_error());

         while ($row_extraer=mysql_fetch_array($result_extraer))
         {
          $cod_item = $row_extraer[1];
          $cantidad = $row_extraer[3];

          //SABER SI YA SE HIZO ESE CONTEO Y SI NO ES así GUARDAR EL REGISTRO
          $query_sabersi = "SELECT * FROM tbinventario_conteos WHERE item_código LIKE '".$cod_item."' AND posicion=".
$posicion." AND tercer!=0";
      $result_sabersi = mysql_query($query_sabersi) or die(mysql_error());

      //LE AGREGO LA CANTIDAD DE REGISTROS ENTREGADOS POR LA CONSULTA A UNA VARIABLE
      $numrows = mysql_num_rows($result_sabersi);

     if($numrows != 0)
    {
       echo "<div align='center'><b><font size=4>A ESTE ITEM YA SE LE HIZO TERCER CONTEO</font></b></div>";
       echo $query_error1 = "INSERT INTO tbinventario_errores VALUES(NULL, '".$id_cuenta."', '".$posicion."', '".$cod_item."', 
'".$conteo."')";
     $result_error1 = mysql_query($query_error1) or die(mysql_error());
    }
    else
    {
     $query_conteo2 = "UPDATE tbinventario_conteos SET tercer='".$cantidad."', conto_tercero='".$id_cuenta."' WHERE 
item_código LIKE '".$cod_item."' AND posicion='".$posicion."'";
     $result_conteo2 = mysql_query($query_conteo2) or die(mysql_error());
     echo "<div align='center'><b><font size=4>EL ITEM HA SIDO INDEXADO SATISFACTORIAMENTE ".
$cod_item."</font></b></div>";
    }

    if($result_sabersi == 0)
    {
       echo "NO SE PUDO INDEXAR LA INFORMACION";
    }

          //AHORA SE ACTUALIZA LA TABLA tbinventario_subconteo EN SU CAMPO INDEXADO
          //PARA NO VOLVER A TOMAR ESOS ITEMS
          $query_upd = "UPDATE tbinventario_subconteo SET indexado=1 WHERE cod_item LIKE '".$cod_item."' AND 
cod_bodega LIKE '".$posicion."'";
          $result_upd = mysql_query($query_upd) or die(mysql_error());

         echo "<script languaje='JavaScript'>
              window.close();
                   </script>";

          //VAMOS DANDOLE AL ITEM EN QUE CONTEO VA
          $query_itemcontado = "UPDATE tbinventario_items SET conteo=".$conteo." WHERE código LIKE '".$cod_item."'";
          $result_itemcontado = mysql_query($query_itemcontado) or die(mysql_error());
   }
         //VAMOS A CERRAR LA POSICION DESPUES DE QUE SE INGRESEN LOS DATOS
         //EN LA TABLA tbinventario_bodega
         $query_cerrar = "UPDATE tbinventario_bodega SET cerrado=1, conteo=".$conteo." WHERE código LIKE '".$posicion."'";
         $result_cerrar = mysql_query($query_cerrar) or die(mysql_error());
  }
?>

Los módulos de edición son muy similares a los de captura.

consultar.php
<?php
  include 'configuration.php';
  $conteo = $_GET['conteo'];
  $id_cuenta = $_GET['id'];
?>
<!DOCTYPE html PUBLIC "­//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1­
transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http­equiv="Content­Type" content="text/html; charset=iso­8859­1" />
<title>Ingreso Conteo ITEMS</title>
<LINK REL="StyleSheet" HREF="style.css" TYPE="text/css">
<script languaje="JavaScript">
 function OpenPopup(texto1, texto2, texto3)
 {
  window.open("editar.php?conteo=" + texto1 + "&id=" + texto2 + "&posicion=" + texto3, "_self", 
"width=400,height=400,toolbar=no,menubar=no,directories=yes,status=yes,resizable=no,location=yes,scrollbars=yes")
 }
</script>
</head>
<body>
<div align="center">
<?php
 if($conteo==1 || $conteo==4)
 {
?>
  <form name="frmconteo1" method="post" action="<? $_SERVER['PHP_SELF']; ?>">
   <table border="1" cellspacing="1" cellpadding="1">
    <tr>
     <td class="letratd" align="center"><b>POSICI&Oacute;N</b></td>
    </tr>
    <tr>
     <td class="letratd" align="center"><input type="text" name="posicion" style="text­align:center;" size="10" 
maxlength="8"></td>
    </tr>
    <tr>
     <td class="letratd" align="center" colspan="3">
      <input type="hidden" name="conteo" value="<? echo $conteo; ?>"> 
      <input type="hidden" name="id" value="<? echo $id_cuenta; ?>"> 
      <input type="button" class="button" name="guardar1" value="Continuar" onClick="OpenPopup(frmconteo1.conteo.value, 
frmconteo1.id.value, frmconteo1.posicion.value)"> 
      <!­­<input type="submit" class="button" name="guardar1" value="Continuar">!­­>
     </td>
    </tr>
   </table>
  </form>
<?php
 }
 elseif($conteo==2)
 {
?>
  <form name="frmconteo2" method="post" action="<? $_SERVER['PHP_SELF']; ?>">
   <table border="1" cellspacing="1" cellpadding="1">
    <tr>
     <td class="letratd" align="center"><b>POSICI&Oacute;N</b></td>
    </tr>
    <tr>
     <td class="letratd" align="center"><input type="text" name="posicion" style="text­align:center;" size="10" 
maxlength="8"></td>
    </tr>
    <tr>
     <td class="letratd" align="center" colspan="3">
       <input type="hidden" name="conteo" value="<? echo $conteo; ?>"> 
       <input type="hidden" name="id" value="<? echo $id_cuenta; ?>"> 
       <input type="button" class="button" name="guardar2" value="Continuar" onClick="OpenPopup(frmconteo2.conteo.value, 
frmconteo2.id.value, frmconteo2.posicion.value)">
     </td>
    </tr>
   </table>
  </form>
<?php
 }
 else
 {
?>
  <form name="frmconteo3" method="post" action="<? $_SERVER['PHP_SELF']; ?>">
   <table border="1" cellspacing="1" cellpadding="1">
    <tr>
     <td class="letratd" align="center"><b>POSICI&Oacute;N</b></td>
    </tr>
    <tr>
     <td class="letratd" align="center"><input type="text" name="posicion" style="text­align:center;" size="10" 
maxlength="8"></td>
    </tr>
    <tr>
     <td class="letratd" align="center" colspan="3">
       <input type="hidden" name="conteo" value="<? echo $conteo; ?>">
       <input type="hidden" name="id" value="<? echo $id_cuenta; ?>"> 
       <input type="button" class="button" name="guardar3" value="Continuar" onClick="OpenPopup(frmconteo3.conteo.value, 
frmconteo3.id.value, frmconteo3.posicion.value)">
     </td>
    </tr>
   </table>
  </form>
<? } ?>
</div>
</body>
</html>
<?php
  if ($_POST['guardar1'])
  {
   echo $posicion = $_GET['posicion'];
         echo $conteo = $_GET['conteos'];
         echo $id = $_GET['ids'];
         echo '<script languaje="JavaScript">
                         window.open("captura.php?conteo='.$conteo.'&id='.$id.'&posicion='.$posicion.', "_self", 
"width=400,height=400,toolbar=no,menubar=no,directories=yes,status=yes,resizable=no,location=yes,scrollbars=yes")
                 </script>';
  }
?>

editar.php
<?php
  include 'configuration.php';
  $conteo = $_GET['conteo'];
  $posicion = $_GET['posicion'];
  $id_cuenta = $_GET['id'];
  $coditem = $_GET['coditem'];
  $cantidad1conteo = $_GET['cantidad'];
  $cantidad2conteo = $_GET['cantidad'];
  $cantidad3conteo = $_GET['cantidad'];
?>
<!DOCTYPE html PUBLIC "­//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1­
transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http­equiv="Content­Type" content="text/html; charset=iso­8859­1" />
<title>Ingreso Conteo ITEMS</title>
<LINK REL="StyleSheet" HREF="style.css" TYPE="text/css">
<script type="text/javascript" src="./ajax.js"></script>
</head>
<body>
<div align="center">
<?php
 if($conteo==1 || $conteo==4)
 {
?>
  <div id="capaInfo" class="letratd"><b>Nombre del ITEM</b></div>
        <form name="frmconteo1" method="post" action="<? $_SERVER['PHP_SELF']; ?>">
  <table border="1" cellspacing="1" cellpadding="1">
    <tr>
     <?php if ($conteo==1){ ?><td class="letratd" align="center"><b>C&Oacute;DIGO ITEM</b></td>
     <td class="letratd" align="center"><b>CANTIDAD</b></td>
     <?php } elseif ($conteo==4){ ?><td class="letratd" align="center"><b>C&Oacute;DIGO BARRAS</b></td> <? } ?>
     <td class="letratd" align="center"><b>POSICI&Oacute;N</b></td>
    </tr>
    <tr>
     <?php if ($conteo==1){ ?><td class="letratd" align="center"><input type="text" id="item" name="item" value="<? echo 
$coditem; ?>" style="text­align:center;" size="12" maxlength="10" readonly="readonly"></td>
    <td class="letratd" align="center"><input type="text" id="cantidad" name="cantidad" value="<? echo $cantidad1conteo; ?>" 
style="text­align:center;" size="5" maxlength="5"></td>
     <?php } elseif ($conteo==4){ ?><td class="letratd" align="center"><input type="text" name="cod_barra" style="text­
align:center;" size="12" maxlength="28"></td><? } ?>
     <td class="letratd" align="center"><input type="text" name="posicion" style="text­align:center;" size="10" maxlength="8" 
value="<? echo $posicion; ?>" readonly="readonly"></td>
    </tr>
    <tr>
     <td class="letratd" align="center" colspan="3">
      <input type="hidden" name="conteo" value="<? echo $conteo; ?>"> 
      <input type="hidden" name="id_cuenta" value="<? echo $id_cuenta; ?>"> 
      <input type="submit" class="button" name="guardar1" value="Guardar"> 
     </td>
    </tr>
   </table>
  </form>
   <table border="1" cellspacing="1" cellpadding="1">
                <tr>
                 <td class="letratd" align="center" colspan="4"><b>POSICI&Oacute;N <? echo $posicion; ?></b></td>
    </tr>
    <tr>
     <td class="letratd" align="center"><b>C&Oacute;DIGO ITEM</b></td>
     <td class="letratd" align="center"><b>DESC ITEM</b></td>
     <td class="letratd" align="center"><b>CANTIDAD</b></td>
     <td class="letratd" align="center"><b>EDITAR</b></td>
    </tr>
      <?php
         //SE VA A IMPRIMIR UNA TABLA CON LOS ITEMS QUE SE INDEXARAN DENTRO DE LA TABLA tbinventario_conteos
         $query_sacar = "SELECT * FROM tbinventario_conteos WHERE posicion LIKE '".$posicion."'";// AND segundo != ''";
         $result_sacar = mysql_query($query_sacar) or die(mysql_error());

         echo $numrows = mysql_num_rows($result_sacar);

         while ($row_sacar=mysql_fetch_array($result_sacar))
         {
           $id_sub = $row_sacar[0];
           $cod_item = $row_sacar[1];

           $query_item = "SELECT * FROM tbinventario_items WHERE código LIKE '".$cod_item."'";
           $result_item = mysql_query($query_item) or die(mysql_error());
           if ($row_item=mysql_fetch_array($result_item))
           {
             $nombre_item = $row_item[2];
           }

           $cantidad1conteo = $row_sacar[3];
           echo "<tr>
                   <td class='letratd' align='center'>".$cod_item."</td>
                   <td class='letratd' align='center'>".$nombre_item."</td>
                   <td class='letratd' align='center'>".$cantidad1conteo."</td>
                   <td class='letratd' align='center'>";
       ?>
       <!­­<input type='button' name='editor' value='Editar' onclick="editarDatos('<? echo $cod_item; ?>', 2, 
frmconteo2.posicion.value)">!­­>
        <a href='editar.php?conteo=<? echo $conteo; ?>&posicion=<? echo $posicion; ?>&id=<? echo $id_cuenta; ?>&coditem=<? 
echo $cod_item; ?>&cantidad=<? echo $cantidad1conteo; ?>'><img src='b_edit.png' border=0></a></td>
       <?php   
           echo "</tr>";
          }
       ?>
    </table>
<?php
 }
 elseif($conteo==2)
 {
?>
  <div id="capaInfos" class="letratd"><b>Nombre del ITEM</b></div>
        <form name="frmconteo2" method="post" action="<? $_SERVER['PHP_SELF']; ?>">
   <table border="1" cellspacing="1" cellpadding="1">
    <tr>
     <?php if ($conteo==2){ ?><td class="letratd" align="center"><b>C&Oacute;DIGO ITEM</b></td>
     <td class="letratd" align="center"><b>CANTIDAD</b></td>
     <?php } elseif ($conteo==4){ ?><td class="letratd" align="center"><b>C&Oacute;DIGO BARRAS</b></td> <? } ?>
     <td class="letratd" align="center"><b>POSICI&Oacute;N</b></td>
    </tr>
    <tr>
     <?php if ($conteo==2){ ?><td class="letratd" align="center"><input type="text" id="item" name="item" value="<? echo 
$coditem; ?>" style="text­align:center;" size="12" maxlength="10" readonly="readonly"></td>
     <td class="letratd" align="center"><input type="text" id="cantidad" name="cantidad" value="<? echo $cantidad2conteo; ?>" 
style="text­align:center;" size="5" maxlength="5"></td>
     <?php } elseif ($conteo==4){ ?><td class="letratd" align="center"><input type="text" name="cod_barra" style="text­
align:center;" size="12" maxlength="28"></td><? } ?>
     <td class="letratd" align="center"><input type="text" name="posicion" style="text­align:center;" size="10" maxlength="8" 
value="<? echo $posicion; ?>" readonly="readonly"></td>
    </tr>
    <tr>
     <td class="letratd" align="center" colspan="3">
      <input type="hidden" name="conteo" value="<? echo $conteo; ?>"> 
      <input type="hidden" name="id_cuenta" value="<? echo $id_cuenta; ?>"> 
      <input type="submit" class="button" name="guardar2" value="Guardar"> 
     </td>
    </tr>
   </table>
  </form>
   <table border="1" cellspacing="1" cellpadding="1">
     <tr>
       <td class="letratd" align="center" colspan="4"><b>POSICI&Oacute;N <? echo $posicion; ?></b></td>
    </tr>
    <tr>
     <td class="letratd" align="center"><b>C&Oacute;DIGO ITEM</b></td>
     <td class="letratd" align="center"><b>DESC ITEM</b></td>
     <td class="letratd" align="center"><b>CANTIDAD</b></td>
     <td class="letratd" align="center"><b>EDITAR</b></td>
    </tr>
    <?php
       //SE VA A IMPRIMIR UNA TABLA CON LOS ITEMS QUE SE INDEXARON DENTRO DE LA TABLA tbinventario_conteos
      //PARA EDITARLOS EN EL PANEL SUPERIOR
      $query_sacar = "SELECT * FROM tbinventario_conteos WHERE posicion LIKE '".$posicion."' AND segundo != ''";
      $result_sacar = mysql_query($query_sacar) or die(mysql_error());

      echo $numrows = mysql_num_rows($result_sacar);
      while ($row_sacar=mysql_fetch_array($result_sacar))
      {
        $id_sub = $row_sacar[0];
         $cod_item = $row_sacar[1];
         $query_item = "SELECT * FROM tbinventario_items WHERE código LIKE '".$cod_item."'";
         $result_item = mysql_query($query_item) or die(mysql_error());

         if ($row_item=mysql_fetch_array($result_item))
         {
            $nombre_item = $row_item[2];
         }

         $cantidad2conteo = $row_sacar[4];

         echo "<tr>
                 <td class='letratd' align='center'>".$cod_item."</td>
                 <td class='letratd' align='center'>".$nombre_item."</td>
                 <td class='letratd' align='center'>".$cantidad2conteo."</td>
                 <td class='letratd' align='center'>";
     ?>
       <!­­<input type='button' name='editor' value='Editar' onclick="editarDatos('<? echo $cod_item; ?>', 2, 
frmconteo2.posicion.value)">!­­>
        <a href='editar.php?conteo=<? echo $conteo; ?>&posicion=<? echo $posicion; ?>&id=<? echo $id_cuenta; ?>&coditem=<? 
echo $cod_item; ?>&cantidad=<? echo $cantidad2conteo; ?>'><img src='b_edit.png' border=0></a></td>
     <?php   
         echo "</tr>";
       }
     ?>
     </table>
<?php
 }
 else
 {
?>
  <div id="capaInfo" class="letratd"><b>Nombre del ITEM</b></div>
  <form name="frmconteo3" method="post" action="<? $_SERVER['PHP_SELF']; ?>">
   <table border="1" cellspacing="1" cellpadding="1">
    <tr>
     <?php if ($conteo==3){ ?><td class="letratd" align="center"><b>C&Oacute;DIGO ITEM</b></td>
     <td class="letratd" align="center"><b>CANTIDAD</b></td>
     <?php } elseif ($conteo==4){ ?><td class="letratd" align="center"><b>C&Oacute;DIGO BARRAS</b></td> <? } ?>
     <td class="letratd" align="center"><b>POSICI&Oacute;N</b></td>
    </tr>
    <tr>
     <?php if ($conteo==2){ ?><td class="letratd" align="center"><input type="text" id="item" name="item" value="<? echo 
$coditem; ?>" style="text­align:center;" size="12" maxlength="10" readonly="readonly"></td>
     <td class="letratd" align="center"><input type="text" id="cantidad" name="cantidad" value="<? echo $cantidad3conteo; ?>" 
style="text­align:center;" size="5" maxlength="5"></td>
     <?php } elseif ($conteo==4){ ?><td class="letratd" align="center"><input type="text" name="cod_barra" style="text­
align:center;" size="12" maxlength="28"></td><? } ?>
     <td class="letratd" align="center"><input type="text" name="posicion" style="text­align:center;" size="10" maxlength="8" 
value="<? echo $posicion; ?>" readonly="readonly"></td>
    </tr>
    <tr>
     <td class="letratd" align="center" colspan="3">
      <input type="hidden" name="conteo" value="<? echo $conteo; ?>"> 
      <input type="hidden" name="id_cuenta" value="<? echo $id_cuenta; ?>"> 
      <input type="submit" class="button" name="guardar3" value="Guardar"> 
     </td>
    </tr>
   </table>
  </form>
   <table border="1" cellspacing="1" cellpadding="1">
     <tr>
       <td class="letratd" align="center" colspan="4"><b>POSICI&Oacute;N <? echo $posicion; ?></b></td>
    </tr>
    <tr>
     <td class="letratd" align="center"><b>C&Oacute;DIGO ITEM</b></td>
     <td class="letratd" align="center"><b>DESC ITEM</b></td>
     <td class="letratd" align="center"><b>CANTIDAD</b></td>
     <td class="letratd" align="center"><b>EDITAR</b></td>
    </tr>
       <?php
         //SE VA A IMPRIMIR UNA TABLA CON LOS ITEMS QUE SE INDEXARON DENTRO DE LA TABLA tbinventario_conteos
        //PARA EDITARLOS EN EL PANEL SUPERIOR
        $query_sacar = "SELECT * FROM tbinventario_conteos WHERE posicion LIKE '".$posicion."' AND tercer != ''";
        $result_sacar = mysql_query($query_sacar) or die(mysql_error());

        echo $numrows = mysql_num_rows($result_sacar);

        while ($row_sacar=mysql_fetch_array($result_sacar))
        {
          $id_sub = $row_sacar[0];
          $cod_item = $row_sacar[1];
          $query_item = "SELECT * FROM tbinventario_items WHERE código LIKE '".$cod_item."'";
          $result_item = mysql_query($query_item) or die(mysql_error());

          if ($row_item=mysql_fetch_array($result_item))
          {
            $nombre_item = $row_item[2];
          }

          $cantidad3conteo = $row_sacar[4];
          echo "<tr>
                  <td class='letratd' align='center'>".$cod_item."</td>
                  <td class='letratd' align='center'>".$nombre_item."</td>
                  <td class='letratd' align='center'>".$cantidad3conteo."</td>
                  <td class='letratd' align='center'>";
       ?>
        <!­­<input type='button' name='editor' value='Editar' onclick="editarDatos('<? echo $cod_item; ?>', 2, 
frmconteo2.posicion.value)">!­­>
        <a href='editar.php?conteo=<? echo $conteo; ?>&posicion=<? echo $posicion; ?>&id=<? echo $id_cuenta; ?>&coditem=<? 
echo $cod_item; ?>&cantidad=<? echo $cantidad3conteo; ?>'><img src='b_edit.png' border=0></a></td>
       <?php   
           echo "</tr>";
         }
       ?>
       </table>
<? } ?>
</div>
</body>
</html>
<?php
  //UTILIZO EL METODO POST POR QUE EN MI UBUNTU NO ME funciona
  //LA FORMA TRADICIONAL (NO S&#201; POR QU&#201; :S)
  //SE VA A ACTUALIZAR LOS DATOS POR EL JEFE DE MESA
  if($_POST['guardar1'])
  {
   $posicion = $_POST['posicion'];
   $conteo = $_POST['conteo'];
   $id_cuenta = $_POST['id_cuenta'];
   $item = $_POST['item'];
   $cantidad = $_POST['cantidad'];

   $query_upd = "UPDATE tbinventario_conteos SET primer='".$cantidad."' WHERE item_código LIKE '".$item."' AND posicion 
LIKE '".$posicion."'";
   $result_upd = mysql_query($query_upd) or die($query_upd);

   echo "<script languaje='javascript'>
       document.location.href='editar.php?conteo=".$conteo."&posicion=".$posicion."&id=".$id_cuenta."';
      </script>";
  }

  //SE VA A ACTUALIZAR LOS DATOS POR EL JEFE DE MESA
  if($_POST['guardar2'])
  {
   $posicion = $_POST['posicion'];
   $conteo = $_POST['conteo'];
   $id_cuenta = $_POST['id_cuenta'];
   $item = $_POST['item'];
   $cantidad = $_POST['cantidad'];

   $query_upd = "UPDATE tbinventario_conteos SET segundo='".$cantidad."' WHERE item_código LIKE '".$item."' AND 
posicion LIKE '".$posicion."'";
   $result_upd = mysql_query($query_upd) or die($query_upd);

   echo "<script languaje='javascript'>
       document.location.href='editar.php?conteo=".$conteo."&posicion=".$posicion."&id=".$id_cuenta."';
      </script>";
  }

  //SE VA A ACTUALIZAR LOS DATOS POR EL JEFE DE MESA
  if($_POST['guardar3'])
  {
   $posicion = $_POST['posicion'];
   $conteo = $_POST['conteo'];
   $id_cuenta = $_POST['id_cuenta'];
   $item = $_POST['item'];
   $cantidad = $_POST['cantidad'];

   $query_upd = "UPDATE tbinventario_conteos SET tercer='".$cantidad."' WHERE item_código LIKE '".$item."' AND posicion 
LIKE '".$posicion."'";
   $result_upd = mysql_query($query_upd) or die($query_upd);
   echo "<script languaje='javascript'>
       document.location.href='editar.php?conteo=".$conteo."&posicion=".$posicion."&id=".$id_cuenta."';
      </script>";
  }
?>

ver_items.php
<?php
  include 'configuration.php';
  $show = $_GET['show'];
  $tipo = $_GET['tipo'];
?>
<!DOCTYPE HTML PUBLIC '­//W3C//DTD HTML 4.01 Transitional//EN'>
<html>
<head>
<title>Items Contados</title>
<meta http­equiv="Content­Type" content="text/html; charset=iso­8859­1">
<!­­ PARA REFRESCAR LA PAGINA CON UN INTERVALO DE 5 SEGUNDOS !­­>
<meta http­equiv="refresh" content="5">
<LINK REL="StyleSheet" HREF="style.css" TYPE="text/css">
</head>
<body>
<?php
   $query = "SELECT * FROM tbinventario_conteos ORDER BY item_código LIMIT ".$show.", 25";
   $result = mysql_query($query) or die(mysql_error());
?>
<div align="center">
<table border="1" cellspacing="1" cellpadding="1">
 <tr>
  <td class="letratd" align="center"><b>C&Oacute;DIGO</b></td>
  <td class="letratd" align="center"><b>DESCRIPCI&Oacute;N</b></td>
  <td class="letratd" align="center"><b>PRECIO</b></td>
  <td class="letratd" align="center"><b>POSICI&Oacute;N</b></td>
  <td class="letratd" align="center"><b>CONTEO 1</b></td>
  <!­­MOSTRARA A LOS ADMINISTRADORES QUIENES HAN CONTADO ESE ITEM !­­>
  <?php if($tipo==69){?><td class="letratd" align="center"><b>CONT&Oacute;</b></td><? } ?>
  <td class="letratd" align="center"><b>CONTEO 2</b></td>
  <?php if($tipo==69){?><td class="letratd" align="center"><b>CONT&Oacute;</b></td><? } ?>
  <!­­<td class="letratd" align="center"><b>CONTEO 3</b></td>
  <?php if($tipo==69){?><td class="letratd" align="center"><b>CONT&Oacute;</b></td><? } ?>!­­>
  <td class="letratd" align="center"><b>SIST­UNO</b></td>
  <!­­<td class="letratd" align="center"><b>CONTEOS</b></td>!­­>
  <td class="letratd" align="center"><b>DIFERENCIA</b></td>
  <?php if($tipo==69){?><td class="letratd" align="center"><b>COSTO UNO</b></td>
  <td class="letratd" align="center"><b>COSTO CONTEO</b></td>
  <td class="letratd" align="center"><b>DIFERENCIA</b></td><? } ?>
 </tr>
<?php
 while($row=mysql_fetch_array($result))
 {
  $id = $row[0];
  $cod = $row[1];
  $conto_primero = $row[6];
  $conto_segundo = $row[7];
  $conto_tercero = $row[8];

  //ME ASEGURO DE QUE HAYA DATO SINO ME ARROJA UN ERROR DE SINTAXIS SQL
  if($conto_segundo!="")
  {
   $query_segundo = "SELECT * FROM tbinventario_users WHERE id=".$conto_segundo; 
   $result_segundo = mysql_query($query_segundo) or die(mysql_error());
   if($row_segundo=mysql_fetch_array($result_segundo))
   {
    $nom1segundo = $row_segundo[4];
    $nom2segundo = $row_segundo[5];
    $conto_segundo = $nom1segundo."<br>".$nom2segundo;
   }
  }
  if($conto_tercero!="")
  {
   $query_tercero = "SELECT * FROM tbinventario_users WHERE id=".$conto_tercero;
   $result_tercero = mysql_query($query_tercero) or die(mysql_error());
   if($row_tercero=mysql_fetch_array($result_tercero))
   {
    $nom1tercero = $row_tercero[4];
    $nom2tercero = $row_tercero[5];
    $conto_tercero = $nom1tercero."<br>".$nom2tercero;
   }
  }
  //ESTE QUERY ES PARA SABER QUIEN HIZO LOS CONTEOS
  $query_primero = "SELECT * FROM tbinventario_users WHERE id=".$conto_primero;
  $result_primero = mysql_query($query_primero) or die(mysql_error());

  if($row_primero=mysql_fetch_array($result_primero))
  {
   $nom1primero = $row_primero[4];
   $nom2primero = $row_primero[5];
   $contaron = $nom1primero."<br>".$nom2primero;
  }

  //QUERY PARA SABER LA INFORMACION DEL ITEM
  $query_item = "SELECT * FROM tbinventario_items WHERE código LIKE '".$cod."'";
  $result_item = mysql_query($query_item) or die(mysql_error());

  if($result_item==0)
  {
   echo "La consulta no arrojo datos";
  }

  if($row_item=mysql_fetch_array($result_item))
  {
   $descripcion = $row_item[2];
   $precio = $row_item[5];
   $cantidadinve = $row_item[6];

   //HAGO LA SUMA DE TODAS LAS BODEGAS
   $suma_inventario = $cantidadinve;
  }
  $posicion = $row[2];

  //QUERY PARA SABER LA POSICION DONDE SE CONTO EL ITEM
  $query_posicion = "SELECT * FROM tbinventario_bodega WHERE código LIKE '".$posicion."'";
  $result_posicion = mysql_query($query_posicion) or die(mysql_error());

  if($result_posicion==0)
  {
   echo "La consulta no arrojo datos";
  }

  if($row_posicion=mysql_fetch_array($result_posicion))
  {
   $nombre = $row_posicion[2];
  }

  $primero = $row[3];
  $segundo = $row[4];
  $tercero = $row[5];

  //LE QUITO LA COMA PARA PODER HACER LA SUMA DE TODAS LAS BODEGAS Y LUEGO LO MULTIPLICO POR EL  
PRECIO
  $precio = str_replace(",", "", $precio);
  $suma_conteos = $primero + $segundo + $tercero;

  //$diferencia = $suma_conteos­$suma_inventario;
  $diferencia = $primero­$suma_inventario;

  //PARA NO MULTIPLICAR EL PRECIO POR 0
  //PARA MULTIPLICAR EL PRECIO POR LA CANTIDAD DE LOS ITEMS DEL UNO
  //if ($suma_inventario==0){ $suma_inventario = 1; }
  $total_uno = 1 * $precio;
   //PARA NO MULTIPLICAR EL PRECIO POR 0
   //PARA MULTIPLICAR EL PRECIO POR LA CANTIDAD DE LOS ITEMS CONTADOS
   if ($primero==0){ $primero = 1; }
   $total_cont = $primero * $precio;

   //DIFERENCIA EN PRECIOS ENTRE EL UNO Y LOS CONTEOS
   $diferencia_pre = $total_cont ­ $total_uno;

  //PARA MOSTRAR DIFERENTES TABLAS SEG&#218;N EL TIPO DE USUARIO
  if($tipo==69)
  {
   echo '<tr>
          <td class="letratd" align="center">'.$cod.'</td>
          <td class="letratd">'.$descripcion.'</td>
          <td class="letratd" align="right">$ '.$precio.'</td>
          <td class="letratd" align="center">'.$nombre.'</td>
          <td class="letratd" align="center">'.$primero.'</td>
          <td class="letratd" align="center">'.$contaron.'&nbsp;</td>
          <td class="letratd" align="center">'.$segundo.'&nbsp;</td>
          <td class="letratd" align="center">'.$conto_segundo.'&nbsp;</td>
          <td class="letratd" align="center">'.$suma_inventario.'</td>
          <td class="letratd" align="center">'.$diferencia.'</td>
          <td class="letratd" align="center">'.$total_uno.'</td>
          <td class="letratd" align="center">'.$total_cont.'</td>
          <td class="letratd" align="center">'.$diferencia_pre.'</td>';
  }
  else
  {
   echo '<tr>
          <td class="letratd" align="center">'.$cod.'</td>
          <td class="letratd">'.$descripcion.'</td>
          <td class="letratd" align="right">$ '.$precio.'</td>
          <td class="letratd" align="center">'.$nombre.'</td>
          <td class="letratd" align="center">'.$primero.'</td>
          <td class="letratd" align="center">'.$suma_inventario.'</td>
          <td class="letratd" align="center">'.$diferencia.'</td>';
  }

  echo '</tr>';
 }

  //PARA HACER LA SUMA TOTAL DE UN SOLO ITEM QUE EST&#201; EN VARIOS RAK's
  //Y COMPARARLO CON LO QUE HAY EN EL SISTEMA UNO
  if($row1=mysql_fetch_array($result))
  {
   $elcódigo = $row1[1];
   $query_sumitems = "SELECT SUM(primer+segundo+tercero) AS SUMA FROM tbinventario_conteos WHERE item_código 
LIKE '".$elcódigo."'";
   $result_sumitems = mysql_query($query_sumitems) or die(mysql_error());

   if($row_sumitems=mysql_fetch_array($result_sumitems))
   {
    $camposuma = $row_sumitems[0];
   }
  }

?>
 <!­­ <tr>
  <td class="letratd" align="right" colspan="19"><b>TOTAL GENERAL</b></td>
  <td class="letratd" align="right" colspan="19"><b><? echo $TOTAL; ?></b></td>
 </tr> !­­>
</table>
<?php
 //PAGINACI&#211;N DE LOS DATOS
 //ACA VIENE LO WENO; NO USE LA CONSULTA ANTERIOR,
 //POR QUE COMO DA LIMITE 'TONS NO ME DA LOS DATOS REALES
 $query_saber = "SELECT * FROM tbinventario_conteos";
 $result_saber = mysql_query($query_saber) or die(mysql_error());

 //EN ESTA VARIABLE SE GUARDAN LA CANTIDAD DE REGISTROS GENERADOS
 $numrows = mysql_num_rows($result_saber);

 $variable = $numrows/25;

 //SI ME DA CON DECIMALES LO REDONDEO AL MENOR
 //CON LA función floor
 $variable = floor($variable);
 $n = 0;

 //EMPIEZO A IMPRIMIR LAS PAGINAS
 echo '<br>';
 while($n<=$variable)
 {
  $show = '25';
  if ($tipo==69)
  {
    echo '<a href="'.$_SERVER['PHP_SELF'].'?show='.$show*$n.'&forma=1&tipo='.$tipo.'">'.$n.'</a> ';
  }
  else
  {
    echo '<a href="'.$_SERVER['PHP_SELF'].'?show='.$show*$n.'&forma=1">'.$n.'</a> ';
  }

  $n++;
 }
?>
</div>
</body>
</html>

items.php
<?php
  include 'configuration.php'; 
  $TOTAL = 0;
  $show = $_GET['show'];
  $forma = $_GET['forma'];
  //ESTOS DOS CAMPOS ES CUANDO SE HACEN B&#218;SQUEDAS CON FILTRO
  $buscar = $_GET['buscar'];
  $opc = $_GET['opc'];
?>
<!DOCTYPE html PUBLIC "­//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1­
transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http­equiv="Content­Type" content="text/html; charset=iso­8859­1" />
<title>Items</title>
<LINK REL="StyleSheet" HREF="style.css" TYPE="text/css">
</head>
<body>
<div align="center">
<a href="<? $_SERVER['PHP_SELF'] ?>?show=0&forma=1">Ver todos</a> | <a href="javascript: 
window.open('search.php','','resizable=yes,scrollbars=yes,width=300,height=170,menubar=no,status=yes,top=1,left=1').focus();">
  B&uacute;squeda ITEMS
 </a>

<?php
  //SI SE ESCOGE $forma=2 SIRVE PARA HACER B&#218;SQUEDAS, CON $forma=1 SE MUESTRAN TODOS LOS ITEMS
  if ($forma==2)
  {
    $query = "SELECT * FROM tbinventario_items WHERE";
    if ($opc==1)
    {
      $query = $query." código LIKE '%".$buscar."%'";
    }
    else
    {
      $query = $query." nombre LIKE '%".$buscar."%'";
    }

    $query = $query." LIMIT ".$show.", 25";
    $result = mysql_query($query) or die(mysql_error());
?>
<table border="1" cellspacing="1" cellpadding="1">
 <tr>
  <td class="letratd" align="center" colspan="5"><b>ITEM</b></td>
  <td class="letratd" align="center" colspan="14"><b>BODEGA</b></td>
  <td class="letratd" align="center"><b>&nbsp;</b></td>
 </tr>
 <tr>
  <td class="letratd" align="center"><b>ID</b></td>
  <td class="letratd" align="center"><b>C&Oacute;DIGO</b></td>
  <td class="letratd" align="center"><b>DESCRIPCION</b></td>
  <td class="letratd" align="center"><b>UM</b></td>
  <td class="letratd" align="center"><b>COSTO</b></td>
  <td class="letratd" align="center"><b>CANTIDAD</b></td>
  <td class="letratd" align="center"><b>TOTAL</b></td>
 </tr>
<?php
 while($row=mysql_fetch_array($result))
 {
  $id = $row[0];
  $cod = $row[1];
  $nombre = $row[2];
  $um = $row[4];
  $precio = $row[5];
  $cantidad = $row[6];

  //LE QUITO LA COMA PARA PODER HACER LA SUMA DE TODAS LAS BODEGAS Y LUEGO LO MULTIPLICO POR EL  
PRECIO
  $precio = str_replace(",", "", $precio);

  //PARA NO MULTIPLICAR EL PRECIO POR 0
  if ($suma==0){ $suma = 1; }

  $total = $cantidad * $precio;

  //HAGO LA SUMA TOTAL DE TODOS LOS ITEMS PARA SABER CUANTO NAY EN INVENTARIO
        $TOTAL += $total;
  echo '<tr>
          <td class="letratd" align="center">'.$id.'</td>
          <td class="letratd" align="center">'.$cod.'</td>
          <td class="letratd">'.$nombre.'</td>
          <td class="letratd" align="center">'.$um.'</td>
          <td class="letratd" align="right">$ '.$precio.'</td>
          <td class="letratd" align="center">'.$cantidad.'</td>
          <td class="letratd" align="right">$ '.$total.'</td>
        </tr>';
 }
?>
 <!­­ <tr>
  <td class="letratd" align="right" colspan="19"><b>TOTAL GENERAL</b></td>
  <td class="letratd" align="right" colspan="19"><b><? echo $TOTAL; ?></b></td>
 </tr> !­­>
</table>
<?php
 //ACA VIENE LO WENO; NO USE LA CONSULTA ANTERIOR,
 //POR QUE COMO DA LIMITE 'TONS NO ME DA LOS DATOS REALES
 $query_saber = "SELECT * FROM tbinventario_items WHERE";
 if ($opc==1)
 {
   $query_saber = $query_saber." código LIKE '%".$buscar."%'";
 }
 else
 {
   $query_saber = $query_saber." nombre LIKE '%".$buscar."%'";
 }

 $result_saber = mysql_query($query_saber) or die(mysql_error());

 //EN ESTA VARIABLE SE GUARDAN LA CANTIDAD DE REGISTROS GENERADOS
 $numrows = mysql_num_rows($result_saber);

 $variable = $numrows/25;

 //SI ME DA CON DECIMALES LO REDONDEO AL MENOR
 //CON LA función floor
 $variable = floor($variable);
 $n = 0;

 //EMPIEZO A IMPRIMIR LAS PAGINAS
 //echo '<br><a href="paginacion.php?show=0">0</a> ';
 echo '<br>';
 while($n<=$variable)
 {
  $show = '25';
  echo '<a href="'.$_SERVER['PHP_SELF'].'?show='.$show*$n.'&forma=2&buscar='.$buscar.'&opc='.$opc.'">'.$n.'</a> ';
  //echo '<a href="?show=&forma=2&buscar=></a>';
  $n++;
 }
 }
 //CIERRA LA DESICION forma 
 //ESTO DEL PRINCIPIO NO TIENE NADA EN PARTICULAR,
 //SOLAMENTE UNA CONSULTA Y UNA IMPRESION DE DATOS
 else
 {
  $query = "SELECT * FROM tbinventario_items LIMIT ".$show.", 25";
  $result = mysql_query($query) or die(mysql_error());
?>
<table border="1" cellspacing="1" cellpadding="1">
 <tr>
  <td class="letratd" align="center" colspan="3"><b>ITEM</b></td>
  <td class="letratd" align="center" colspan="3"><b>BODEGA</b></td>
  <td class="letratd" align="center"><b>&nbsp;</b></td>
 </tr>
 <tr>
  <td class="letratd" align="center"><b>ID</b></td>
  <td class="letratd" align="center"><b>C&Oacute;DIGO</b></td>
  <td class="letratd" align="center"><b>DESCRIPCION</b></td>
  <td class="letratd" align="center"><b>UM</b></td>
  <td class="letratd" align="center"><b>COSTO</b></td>
  <td class="letratd" align="center"><b>CANTIDAD</b></td>
  <td class="letratd" align="center"><b>TOTAL</b></td>
 </tr>
<?php
 while($row=mysql_fetch_array($result))
 {
  $id = $row[0];
  $cod = $row[1];
  $nombre = $row[2];
  $um = $row[4];
  $precio = $row[5];
  $cantidad = $row[6];

  //LE QUITO LA COMA PARA PODER HACER LA SUMA DE TODAS LAS BODEGAS Y LUEGO LO MULTIPLICO POR EL  
PRECIO
  $precio = str_replace(",", "", $precio);

  //PARA NO MULTIPLICAR EL PRECIO POR 0
  if ($suma==0){ $suma = 1; }

  $total = $cantidad * $precio;
  //HAGO LA SUMA TOTAL DE TODOS LOS ITEMS PARA SABER CUANTO NAY EN INVENTARIO
  $TOTAL += $total;
  echo '<tr>
          <td class="letratd" align="center">'.$id.'</td>
          <td class="letratd" align="center">'.$cod.'</td>
          <td class="letratd">'.$nombre.'</td>
          <td class="letratd" align="center">'.$um.'</td>
          <td class="letratd" align="right">$ '.$precio.'</td>
          <td class="letratd" align="center">'.$cantidad.'</td>
          <td class="letratd" align="right">$ '.$total.'</td>
        </tr>';
 }
?>
 <!­­ <tr>
  <td class="letratd" align="right" colspan="19"><b>TOTAL GENERAL</b></td>
  <td class="letratd" align="right" colspan="19"><b><? echo $TOTAL; ?></b></td>
 </tr> !­­>
</table>
<?php
 //ACA VIENE LO WENO; NO USE LA CONSULTA ANTERIOR,
 //POR QUE COMO DA LIMITE 'TONS NO ME DA LOS DATOS REALES
 $query_saber = "SELECT * FROM tbinventario_items";
 $result_saber = mysql_query($query_saber) or die(mysql_error());

 //EN ESTA VARIABLE SE GUARDAN LA CANTIDAD DE REGISTROS GENERADOS
 $numrows = mysql_num_rows($result_saber);

 $variable = $numrows/25;

 //SI ME DA CON DECIMALES LO REDONDEO AL MENOR
 //CON LA función floor
 $variable = floor($variable);
 $n = 0;

 //EMPIEZO A IMPRIMIR LAS PAGINAS
 //echo '<br><a href="paginacion.php?show=0">0</a> ';
 echo '<br>';
 while($n<=$variable)
 {
  $show = '25';
  echo '<a href="'.$_SERVER['PHP_SELF'].'?show='.$show*$n.'&forma=1">'.$n.'</a> ';

   $n++;
 }
}//CIERRA LA DECISION forma
?> 
</div>
</body>
</html>

search.php
<!DOCTYPE html PUBLIC "­//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1­
transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http­equiv="Content­Type" content="text/html; charset=iso­8859­1" />
<title>B&uacute;squeda de ITEMS</title>
<LINK REL="StyleSheet" HREF="style.css" TYPE="text/css">
</head>
<body>
<form name="busqueda" action="<? $_SERVER['PHP_SELF'] ?>" method="post">
<table border="1" cellspacing="1" cellpadding="1">
 <tr>
  <td class="letratd" align="center" colspan="2"><b>B&Uacute;SQUEDA DE ITEMS</b></td>
 </tr>
 <tr>
  <td class="letratd" align="center">
         <select name="opc">
          <option value="1">C&oacute;digo</option>
                <option value="2">Nombre</option>
         </select>
  </td>
  <td class="letratd" align="center"><input type="text" name="buscar"></td>
 </tr>
 <tr> 
  <td class="letratd" align="center" colspan="2">
   <input class="boton" type="submit" name="mostrar" value="Buscar">
 </td>
 </tr>
</table>
</form>
</body>
</html>
<?php
 if ($_POST['mostrar'])
 {
   $buscar = $_POST['buscar'];
   $opc = $_POST['opc'];
   echo "<script languaje='JavaScript'>
                   window.close();
                         window.opener.location.href='items.php?show=0&forma=2&buscar=".$buscar."&opc=".$opc."'
                 </script>";
 }
?>

En mi blog dejo un video de cómo funciona la aplicación; recuerden que funciona al full con códigos de 
barras y un lector omnidireccional.

El   software   completo   lo   dejo   en  SoloCodigo   Código   Fuente  para   que   puedan   descargarlo   funcionando, 
revisen mi blog para cualquier duda.
Descarga acá
Código Latino es posible gracias a:

Sigan con el curso de Python que está realizando

Esperamos sus comentarios, códigos y artículos para la próxima entrega, esta es una revista de todos 
y para todos.
Pueden escribirnos a willian.radicaled@gmail.com
Unetenos con Google Group http://groups.google.com/group/codigolatino
Visita nuestro Blog para más información: http://revistacodigolatino.blogspot.com

Hasta una próxima entrega.
Chao

También podría gustarte