Browse files

Spanish ch 14 corrections

  • Loading branch information...
1 parent 5ee9744 commit 49b0804dd76ba897d0d87c06a4253b37f9a8e390 @spametki spametki committed Mar 17, 2013
View
186 sources/36-web2py-spanish-translation-in-progress/14.markmin
@@ -1,20 +1,20 @@
## Otras Recetas
-### Upgrading
+### Upgrade
``upgrades``:inxx
-En el "site" página de la interfaz administrativa existe un botón "upgrade now". En caso que no esté disponible o no funcione (por ejemplo por problema de bloqueo de un archivo), actualizar web2py manualmente es muy fácil.
+En el "site" página de la interfaz administrativa existe un botón "upgrade now" (actualice la versión ahora). En caso que no esté disponible o no funcione (por ejemplo por problema de bloqueo de un archivo), actualizar web2py manualmente es muy fácil.
-------
-Simple descomprime la última versión de web2py sobre la vieja instalación.
+Simplemente descomprime la última versión de web2py sobre la vieja instalación.
-------
-Esto actualizará todas las librerías así como también las aplicaciones **admin**, **examples**, **welcome**. Además también creará un nuevo archivo vacío "NEWINSTALL". Al reiniciar, web2py elimina´ra los archivos vacíos y empaquetará la aplicación "welcome" en "welcome.w2p" esta será usada como la nueva estructura de la aplicación.
+Esto actualizará todas las librerías así como también las aplicaciones **admin**, **examples**, **welcome**. Además también creará un nuevo archivo vacío "NEWINSTALL". Al reiniciar, web2py eliminará los archivos vacíos y empaquetará la aplicación "welcome" en "welcome.w2p". Esta última será usada como la nueva estructura de la aplicación.
web2py no actualiza cualquier otro archivo existente en otra aplicación.
### Cómo distribuir tus aplicaciones como binarios
-Es posible empaquetar tus aplicaciones con la distribución binaria de web2py y distribuirla juntas. La licencia permite esto tan pronto como dejar claro en la licencia de tu aplicación que tu estas agregando web2py y añadas un enlace a ``web2py.com``.
+Es posible empaquetar tus aplicaciones con la distribución binaria de web2py y distribuirlas juntas. La licencia lo permite, siempre y cuando dejes claro en la licencia de tu aplicación que tu estas agregando web2py y añadas un enlace a ``web2py.com``.
Aquí explicamos como hacer esto para Windows:
@@ -53,12 +53,12 @@ El script "make_min_web2py.py" creará una distribución mínima de web2py que n
- raramente usados modulos contrib
Esto incluye una aplicación "welcome" que consiste de un archivo para permitir la implementación de pruebas.
-Mira este script. Al principio contiene una lista detallada de que está incluido y que es ignorado. Tu puedes fácilmente modificarlo y ajustar a tus necesidades.
+Mira este script. Al principio contiene una lista detallada de qué está incluido y qué es ignorado. Tu puedes fácilmente modificarlo y ajustar a tus necesidades.
### Obteniendo una URL externa
``fetch``:inxx
-Python includes the ``urllib`` library for fetching urls:
+Python incuye la librería ``urllib`` para descargar recursos desde un url:
``
import urllib
page = urllib.urlopen('http://www.web2py.com').read()
@@ -72,10 +72,10 @@ from google.tools import fetch
page = fetch('http://www.web2py.com')
``:code
-### Pretty dates
+### Pretty date
``prettydate``:inxx
-Es usualmente útil para representar un datetime no como "2009-07-25 14:34:56" pero como "one year ago". web2py proporciona una función para esto:
+Es usualmente útil para representar un datetime no como "2009-07-25 14:34:56" pero como "hace un año". web2py proporciona una función para esto:
``
import datetime
d = datetime.datetime(2009,7,25,14,34,56)
@@ -95,40 +95,41 @@ address = '243 S Wabash Ave, Chicago, IL, USA'
(latitude, longitude) = geocode(address)
``:code
-La función ``geocode`` require una conexión a internet además se conecta al servicio de Google de geocodificación. La función retorna ``(0,0)`` en caso de fallar. Note que el servicio de Google de geocodificación tiene un número máximo de peticiones, entonces debes verificar sus términos y condiciones. La función ``geocode`` es implementada al comienzo de la función ``fetch`` y por esto funcióna en GAE.
+La función ``geocode`` require una conexión a internet además se conecta al servicio de Google de geocodificación. La función retorna ``(0,0)`` en caso de fallar. Nota que el servicio de Google de geocodificación tiene un número máximo de peticiones, entonces debes verificar sus términos y condiciones. La función ``geocode`` es implementada al comienzo de la función ``fetch`` y por esto funcióna en GAE.
### Paginación
``pagination``:inxx
-Esta receta es un truco útil para minimizar el acceso a base de dato en el caso de la paginación, e.g., cuando necesitas mostrar una lista de filas desde una basede datos pero quieres distribuir las filas sobre multiples páginas.
+Esta receta es un truco útil para minimizar el acceso a base de datos en el caso de la paginación, e.g., cuando necesitas mostrar una lista de filas desde una base de datos pero quieres distribuir las filas sobre múltiples páginas.
-Comienza creando una aplicación **primes** que almacene los primeros 1000 números primos en una base de datos.
+Comienza creando una aplicación **primos** que almacene los primeros 1000 números primos en una base de datos.
Acá está el modelo ``db.py``:
``
-db = DAL('sqlite://primes.db')
-db.define_table('prime',Field('value','integer'))
-def isprime(p):
+db = DAL('sqlite://primos.db')
+db.define_table('primos',Field('valor','integer'))
+def esprimo(p):
for i in range(2,p):
if p%i==0: return False
return True
if len(db().select(db.prime.id))==0:
p=2
for i in range(1000):
- while not isprime(p): p+=1
- db.prime.insert(value=p)
+ while not esprimo(p): p+=1
+ db.primo.insert(value=p)
p+=1
``:code
Ahora crea una acción ``list_items`` in the "default.py" en el controlador que se lea de esta forma:
``
-def list_items():
- if len(request.args): page=int(request.args[0])
- else: page=0
- items_per_page=20
- limitby=(page*items_per_page,(page+1)*items_per_page+1)
- rows=db().select(db.prime.ALL,limitby=limitby)
- return dict(rows=rows,page=page,items_per_page=items_per_page)
+def listar_elementos():
+ if len(request.args): pagina=int(request.args[0])
+ else: pagina=0
+ elementos_por_pagina=20
+ limitby=(pagina*elementos_por_pagina,(pagina+1)*elementos_por_pagina+1)
+ registros=db().select(db.primo.ALL,limitby=limitby)
+ return dict(registros=registros,pagina=pagina,
+ elementos_por_pagina=elementos_por_pagina)
``:code
Nota que este código selecciona uno o más item de los que necesita, 20+1. el elemento extra dice a la vista si existe la siguiente página.
@@ -137,17 +138,17 @@ Aquí es la vista "default/list_items.html":
``
{{extend 'layout.html'}}
-{{for i,row in enumerate(rows):}}
-{{if i==items_per_page: break}}
-{{=row.value}}<br />
+{{for i,registro in enumerate(registros):}}
+{{if i==elementos_por_pagina: break}}
+{{=registro.valor}}<br />
{{pass}}
-{{if page:}}
-<a href="{{=URL(args=[page-1])}}">previous</a>
+{{if pagina:}}
+<a href="{{=URL(args=[pagina-1])}}">previa</a>
{{pass}}
-{{if len(rows)>items_per_page:}}
-<a href="{{=URL(args=[page+1])}}">next</a>
+{{if len(registros)>items_per_page:}}
+<a href="{{=URL(args=[pagina+1])}}">próxima</a>
{{pass}}
``:code
@@ -163,7 +164,7 @@ httpserver.log
en el directorio raíz de web2py. Un nombre alternativo y ubicación puede ser especificado a través de las opciones de la línea de comandos de web2py.
-Nuevas entradas son añadidas al final del archivo cada vez que una peticón es realizada. Cada línea luce como esto:
+Se añaden nuevas entradas al final del archivo cada vez que una peticón es realizada. Cada línea luce como esto:
``
127.0.0.1, 2008-01-12 10:41:20, GET, /admin/default/site, HTTP/1.1, 200, 0.270000
``:code
@@ -182,45 +183,45 @@ Donde
- status es el código de estado del protocolo HTTP ``status``:cite
- time_taken es la cantidad de tiempo que el servidor tarda en procesar la petición, en segundos, no incluye tiempos de upload/download.
-En el repositorio de aplicaciones ``appliances``:cite , puedrás encontrar una aplicación para el análisis de logs.
+En el repositorio de aplicaciones ``appliances``:cite , podrás encontrar una aplicación para el análisis de logs (registros del sistema).
Estos registros de logs estan deshabilitado por defecto cuando usas mod_wsgi a partir de esto podría ser igual como el log de Apache.
-### Llenando la Base de dato con dummy data.
+### Llenando la Base de datos con dummy data.
-Para propósitos de pruebas es conveniente ser capaz de llenar la base de datos con data dummy. web2py incluye un clasificador bayesiano entrenado y listo para generar textos leibles para este propósito.
+Para propósitos de pruebas es conveniente ser capaz de llenar la base de datos con información aleatoria. web2py incluye un clasificador bayesiano entrenado y listo para generar textos legibles para este propósito.
Esta es la forma más simple de usar:
``
from gluon.contrib.populate import populate
-populate(db.mytable,100)
+populate(db.mitabla,100)
``:code
-Esto insertará 100 registros dummy en db.mytable. E intentará hacer inteligentemente la generación de textos cortos para campos que sean cadenas, enteros, doubles, fecha, datetimes, times, booleans, etc. para el campo correspondiente. Intentará respectar los requerimientos impuestos por los validadores. Para campos que contienen la palabra "name" , intentará generar nombres dummy. Para campos referencias serán generadas válidas referencias.
+Esto insertará 100 registros aleatorios en db.mitabla, e intentará hacer inteligentemente la generación de textos cortos para campos que sean cadenas, enteros, double, date, datetime, time, booleanos, etc. para el campo correspondiente. Intentará respetar los requerimientos impuestos por los validadores. Para campos que contienen la palabra "name" , intentará generar nombres dummy. Para campos reference se generarán referencias válidas.
-Si tienes dos tablas (A y B) donde B referencias a A, comprueba llenar primero a A y a B segundo.
+Si tienes dos tablas (A y B) donde B hace referencia a A, comprueba llenar primero A y luego B.
-Porque las inserciones son hechas en una transacción, no intente insertar muchísimos registros al mismo tiempo, particularmente si estan involucradas referencias. en su lugar, has un ciclo, insertando 100 cada vez, y commit.
+Como las inserciones son hechas en una transacción, no intentes insertar muchísimos registros al mismo tiempo, particularmente si estan involucradas referencias. en su lugar, has un ciclo, insertando 100 cada vez, y luego un commit().
``
for i in range(10):
- populate(db.mytable,100)
+ populate(db.mitabla,100)
db.commit()
``:code
-También puedes usar el clasificador bayesiano para aprender características de algunos textos y generar textos dummys que sean similares, pero podría no tener sentido:
+También puedes usar el clasificador bayesiano para aprender características de algunos textos y generar textos aleatorios que sean similares, pero podría no tener sentido:
``
from gluon.contrib.populate import Learner, IUP
ell=Learner()
-ell.learn('some very long input text ...')
+ell.learn('una entrada de texto realmente larga ...')
print ell.generate(1000,prefix=None)
``:code
-### Aceptando pagos de tarjetas de créditos
+### Aceptando pagos con tarjetas de crédito
``Google Wallet``:inxx ``Paypal``:inxx ``Stripe.com``:inxx
``Authorize.net``:inxx ``DowCommerce``:inxx
-Existen multiples maneras de aceptar pagos de tarjetas de créditos por internet. web2py proporciona una API especifica para algunos de los más populares y prácticos:
+Existen múltiples maneras de aceptar pagos con tarjetas de crédito por internet. web2py proporciona una API especifica para algunos de los más populares y prácticos:
- Google Wallet ``googlewallet``:cite
- PayPal ``paypal``cite
@@ -229,25 +230,25 @@ Existen multiples maneras de aceptar pagos de tarjetas de créditos por internet
- DowCommerece ``dowcommerce``:cite
-Los primeros dos mecanismos en delegar el proceso de autenticación del pago en un external servicio. Mientras este es la mejor solución para la seguridad (tu aplicación no tiene que manejar alguna información de tarjeta de créditos) esto hace el proceso incómodo (el usuario debe loguearse dos veces; por ejemplo, una vez que tu aplicación, y otra con Google) y no permite que tu aplicación maneje pagos recurrentes en una forma automatizada.
+Los primeros dos mecanismos delegan el proceso de autenticación del pago en un servicio de terceros. Mientras esta es la mejor solución de seguridad (tu aplicación no tiene que manejar ninguna información de tarjetas de crédito) esto hace el proceso incómodo (el usuario debe loguearse dos veces; por ejemplo, una vez para tu aplicación, y otra con Google) y no permite que tu aplicación maneje pagos sucesivos en una forma automatizada.
-Hay veces cuando necesitas más control y quieres generar el formulario de entrada para la información de las tarjetas de créditos y que programaticalmente pregunte a quién lo procesa transferir dinero desde la tarjeta de créditos a tu cuenta.
+Hay veces que necesitas más control y quieres generar el formulario de entrada para la información de las tarjetas de crédito y que programaticalmente pregunte a quién lo procesa cómo transferir el dinero desde la tarjeta de crédito a tu cuenta.
Por esta razón web2py provee integración lista para usar con Stripe, Authorize.net (el modulo fue desarrollado por John Conde y ligeramente modificado) y DowCommerce. Stripe es la aplicación más simple de usar y también la más económica para bajo volumen de transacciones (No cobran un cargo fijo pero el costo por transacción está sobre el 3%). Authorize.net es mejor para altos volúmenes (tiene una tarifa fija anual más un bajo costo por transacción).
-Ten en cuenta que en el caso de Stripe y Authorize.net tu programa estará aceptando la información de las tarjetas de créditos. No tienes que almacenar esta información y nosotros te aconsejamos no hacerlo, por los requerimientos legales que involucra (verificar con Visa o Mastercard) pero hay veces cuando tu puedes querer almacenar la información para pagos recurrentes o reproducir el botón de pago de un sólo click de Amazon.
+Ten en cuenta que en el caso de Stripe y Authorize.net tu programa estará aceptando la información de las tarjetas de crédito. No tienes que almacenar esta información y nosotros te aconsejamos no hacerlo, por los requerimientos legales que involucra (verificar con Visa o Mastercard) pero hay ocasiones en las que tu puedes querer almacenar la información para pagos sucesivos o reproducir el botón de pago de un sólo click de Amazon.
#### Google Wallet
-La manera más sencilla de usar Google Wallet (Level 1) consiste en integrar un botón a tu página, cuando hagan click, redirigir tus visitantes a la página de pagos provista por Google.
+La manera más sencilla de usar Google Wallet (Level 1) consiste en integrar un botón a tu página y cuando hagan click, redirigir a tus visitantes a la página de pagos provista por Google.
Primero que todo necesitas registrar una cuenta de Google Merchant en la siguiente url:
``
https://checkout.google.com/sell
``
-Necesitarás indicarle a Google tu información bancaria. Google te asignará un identificador ``merchant_id`` y una llave ``merchant_key`` (no los confundas, Mantenlos en secreto).
+Necesitarás indicarle a Google tu información bancaria. Google te asignará un identificador ``merchant_id`` y una clave ``merchant_key`` (no los confundas, mantenlos en secreto).
Entonces simplemente necesitas crear el siguiente código en tu vista:
@@ -261,15 +262,15 @@ Entonces simplemente necesitas crear el siguiente código en tu vista:
description="running shoes black")])}}
``
-Cuando un visitante hace click en el botón, el visitante será redireccionado a la página de google donde ella/el puede pagar por los artículos. Aquí productos son una lista de productos y cada producto es un diccionario de parámetros que quieres pasar describiendo tus artículos (nombre, cantidad, precio, moneda, descripción, y otros opcionales el cual puedes encontrar descrito en la documentación de Google Wallet).
+Cuando un visitante hace click en el botón, el visitante será redireccionado a la página de google donde ella o él pueden pagar por los artículos. Aquí productos son una lista de productos y cada producto es un diccionario de parámetros que quieres pasar describiendo tus artículos (nombre, cantidad, precio, moneda, descripción, y otros opcionales que puedes encontrar descriptos en la documentación de Google Wallet).
-Si eliges usar este mecanismo, quieres generar los valores pasados al botón programado con información basada en tu inventario y del carrito de compra del visitante.
+Si eliges usar este mecanismo, debes generar los valores pasados al botón programado con información basada en tu inventario y del carrito de compra del visitante.
-Todas la información de tasas y tarifas será manejado del lado de Google. De igual forma para la información de la cuenta. Por defecto tu aplicación no es informada si la transacción ha sido completada sin embargo podrías tener que visitar tu cuenta de Google Merchant para ver cuales productos han sido vendidos y pagado por ellos, y cuales productos necesitan ser enviados a sus compradores. también Google te enviará un email con la información.
+Todas la información de tasas y tarifas será manejada del lado de Google. Lo mismo vale para la información de la cuenta. Por defecto tu aplicación no es informada si la transacción ha sido completada sin embargo podrías tener que visitar tu cuenta de Google Merchant para ver cuáles productos han sido vendidos y pagado por ellos, y cuáles productos necesitan ser enviados a sus compradores. también Google te enviará un email con la información.
Si quieres una integración más estricta tienes que usar el nivel 2 de notificaciones de la API. En ese caso puedes pasar más información a Google y Google llamará a tu API para notificar las ventas. Esto permite mantener la información de la cuenta dentro de tu aplicación pero esto requiere que tengas servicios web que puedan comunicarse con Google Wallet.
-Esto es considerado un problema con mayor dificultad pero tal API ya ha sido implementada y está disponible como un plugin.
+Esto último podría llegar a resultar complicado de programar para una app determinada, pero ya disponemos de un plugin que implementa una API para este propósito.
``
http://web2py.com/plugins/static/web2py.plugin.google_checkout.w2p
@@ -289,7 +290,7 @@ http://www.web2pyslices.com/main/slices/take_slice/9
Esta es probablemente uno de las más fáciles y flexibles maneras de aceptar pagos con tarjetas de crédito.
-Necesitas registrar con Stripe.com y eso es un proceso muy fácil, de hecho Stripe te asignará una llave de la API para incluso intentar antes que crees cualquier credencial.
+Necesitas registrar con Stripe.com y eso es un proceso muy fácil, de hecho Stripe te asignará una llave de la API para pruebas antes de que crees cualquier credencial.
Una vez que tienes tu llave de la API, puedes aceptar tarjetas de crédito, con el siquiente código:
@@ -309,7 +310,7 @@ elif:
# error is in d.get('error','unknown')
``
-La respuesta, ``d``, es un diccionario el cual puedes explorar tu mismo. El número de tarjeta usado en el ejemplo es un sandbox y siempre será exitoso. Cada transacción es asociado a un identificador almacenado en ``d['id']``.
+La respuesta, ``d``, es un diccionario que puedes explorar tu mismo. El número de tarjeta usado en el ejemplo es un sandbox y siempre será exitoso. Cada transacción está asociada a un identificador almacenado en ``d['id']``.
Stripe también permite verificar una transaccion tiempo después:
@@ -322,7 +323,7 @@ y una transacción de reembolso:
``
r = Stripe(key).refund(d['id'])
if r.get('refunded',False):
- # refund was successful
+ # el reembolso se realizó con éxito
elif:
# error is in d.get('error','unkown')
``
@@ -333,32 +334,32 @@ todas las comunicaciones entre tu aplicación y Stripe se realizan sobre servici
#### Authorize.Net
-Otra simple manera de aceptar tarjetas de crédito es usar Authorize.Net. Como es usual necesitas registrarte y obtener un ``login`` y una llave para las transacciones (``transkey``). Una vez que tengas esto, funciona muy similar en espiritu como lo hace Stripe:
+Otra simple manera de aceptar tarjetas de crédito es usar Authorize.Net. Como es usual, necesitas registrarte y obtener un ``login`` y una llave para las transacciones (``transkey``). Una vez que tengas esto, funciona muy similar en espíritu como lo hace Stripe:
``
from gluon.contrib.AuthorizeNet import process
if process(creditcard='4427802641004797',
expiration="122012,
total=100.0,cvv='123',tax=None,invoice=None,
login='cnpdev4289', transkey='SR2P8g4jdEn7vFLQ',testmode=True):
- # pago was procesado
+ # el pago se ha procesado
else:
- # pago was rechazado
+ # el pago se ha rechazado
``:code
Si tienes una cuenta válida de Authorize.Net deberías reemplazar el sandbox ``login`` y ``transkey`` con estos de tu cuenta, configurar ``testmode=False`` para ejecutar en la plataforma real en lugar del sandbox, y usar la información de la tarjeta de crédito dada por el visitante.
-Si ``process`` returna ``True``, el dinero ha sido transferido desde la tarjeta de crédito del visitante a tu cuenta en Authorize.Net. ``invoice`` es solo un string que puede ser configurado y será almacenado por Authorize.Net con esta transacción entonces tienes que conciliar la data con la información en tu aplicación.
+Si ``process`` devuelve ``True``, el dinero ha sido transferido desde la tarjeta de crédito del visitante a tu cuenta en Authorize.Net. ``invoice`` es sólo un string que puede ser configurado y será almacenado por Authorize.Net con esta transacción. Luego, tienes que conciliar la data con la información en tu aplicación.
-Aquí un ejemplo más complejo del workflow donde más variables son expuestas:
+Aquí un ejemplo más complejo del workflow donde se exponen más variables:
``
from gluon.contrib.AuthorizeNet import AIM
payment = AIM(login='cnpdev4289',
transkey='SR2P8g4jdEn7vFLQ',
testmod=True)
payment.setTransaction(creditcard, expiration, total, cvv, tax, invoice)
-payment.setParameter('x_duplicate_window', 180) # three minutes duplicate windows
-payment.setParameter('x_cust_id', '1324') # customer ID
+payment.setParameter('x_duplicate_window', 180) # duplicate_window de tres minutos
+payment.setParameter('x_cust_id', '1324') # ID del cliente
payment.setParameter('x_first_name', 'Agent')
payment.setParameter('x_last_name', 'Smith')
payment.setParameter('x_company', 'Test Company')
@@ -383,15 +384,15 @@ if payment.isApproved():
print 'Approval Code: ', payment.response.AuthCode
print 'AVS Result: ', payment.response.AVSResponse
elif payment.isDeclined():
- print 'Your credit card was declined by your bank'
+ print 'Su tarjeta de crédito fue rechazada por el banco'
elif payment.isError():
- print 'It did not work'
-print 'approved',payment.isApproved()
-print 'declined',payment.isDeclined()
+ print 'No ha funcionado'
+print 'aprovada',payment.isApproved()
+print 'rechazada',payment.isDeclined()
print 'error',payment.isError()
``:code
-Nota el código de arriba usa una cuenta dummy. Necesitas registrarte con Authorize.Net (no es un servicio gratuito) y provee tu propio login, transkey, testmode=True or False para el constructor AIM.
+Nota el código de arriba usa una cuenta de pruebas. Necesitas registrarte con Authorize.Net (no es un servicio gratuito) y provee tu propio login, transkey, testmode=True or False para el constructor AIM.
### Dropbox API
@@ -405,13 +406,13 @@ Puedes accedes a dropbox fácilmente registrandote en
https://www.dropbox.com/developers
``
-Y obtendrás una ``APP_KEY`` y un ``APP_SECRET``. Una vez que tu tengas esto puedes usar Dropbox para autenticar tus usuarios.
+Y obtendrás una ``APP_KEY`` y un ``APP_SECRET``. Una vez que tu tengas esto puedes usar Dropbox para autenticar a tus usuarios.
-Crea un archivo llamado "yourapp/private/dropbox.key" y en el escribe
+Crea un archivo llamado "tuapp/private/dropbox.key" y en él escribe
``
<APP_KEY>:<APP_SECERT>:app_folder
``
-donde ``<APP_KEY>`` y ``APP_SECRET`` es tu llave(app_key) y y llave secreta (app_secret).
+donde ``<APP_KEY>`` y ``APP_SECRET`` son tu llave (app_key) y la llave secreta (app_secret).
Entonces en "models/db.py" coloca:
@@ -424,36 +425,36 @@ mydropbox = auth.settings.login_form
Esto permite a los usuarios autenticarse en tu aplicación usando sus credenciales dropbox, y tu programa será capaz de subir archivos en sus cuentas dropbox:
``
-stream = open('localfile.txt','rb')
-mydropbox.put('destfile.txt',stream)
+stream = open('archivolocal.txt','rb')
+mydropbox.put('archivodestino.txt',stream)
``
descargando archivos:
``
-stream = mydropbox.get('destfile.txt')
-open('localfile.txt','wb').write(read)
+stream = mydropbox.get('archivodestino.txt')
+open('archivolocal.txt','wb').write(read)
``
y obtener el listado del directorio:
``
-contents = mydropbox.dir(path = '/')['contents']
+contenidos = mydropbox.dir(path = '/')['contents']
``
### Twitter API
-Aquí algunos ejemplos rápidos sobre como enviar y obtener tweets. No librerías de terceros son requeridas, desde que Twitter usa APIs RESTful.
+Aquí mostramos algunos ejemplos rápidos de cómo enviar y obtener tweets. No se requieren librerías de terceros, ya que Twitter ha creado una APIs RESTful.
-Aquí un ejemplo de como enviar un tweet:
+Aquí tenemos un ejemplo de cómo enviar un tweet:
``
-def post_tweet(username,password,message):
+def post_tweet(usuario, clave, mensaje):
import urllib, urllib2, base64
import gluon.contrib.simplejson as sj
- args= urllib.urlencode([('status',message)])
+ args= urllib.urlencode([('status', ,mensaje)])
headers={}
headers['Authorization'] = 'Basic '+base64.b64encode(
- username+':'+password)
+ usuario+':'+ clave)
req = urllib2.Request(
'http://twitter.com/statuses/update.json',
args, headers)
@@ -463,39 +464,40 @@ def post_tweet(username,password,message):
Aquí un ejemplo de cómo recibir tweets:
``
def get_tweets():
- user='web2py'
+ usuario='web2py'
import urllib
import gluon.contrib.simplejson as sj
- page = urllib.urlopen('http://twitter.com/%s?format=json' % user).read()
+ page = urllib.urlopen('http://twitter.com/%s?format=json' % usuario).read()
tweets=XML(sj.loads(page)['#timeline'])
return dict(tweets=tweets)
``:code
Para operaciones más complejas, revise la documentación de la API de Twitter.
-### Streaming virtual files
+### Streaming de archivos virtuales
``streaming``:inxx
-Es común para atacadores malisiosos escanear sitios web búscando vulnerabilidades. Ellos usan escaneres de seguridad como Nessus para explorar el sitio web objetivo, en búsqueda de scripts que son conocidos por tener vulnerabilidades. Un análisis de los logs del servidor web desde una máquina escaneadora o directamente en la base de datos Nessus revela que la mayoría de las vulnerabilidades conocidas están en scripts de PHP y ASP. Desde que estamos ejecutando web2py, no tenemos estas vulnerabilidades, pero somos escaneados por ellos. Esto es molesto, entonces nos gusta responder a estos escaneres de vulnerabilidades y hacer al atacante entender que está desperdiciando su tiempo.
+Es común en programadores maliciosos el escaneado de sitios web búscando vulnerabilidades. Ellos usan escáneres de seguridad como Nessus para explorar el sitio web de interés, en búsqueda de scripts que son conocidos por tener vulnerabilidades. Un análisis de los logs del servidor web desde una máquina escaneadora o directamente en la base de datos Nessus revela que la mayoría de las vulnerabilidades conocidas están en scripts de PHP y ASP. Desde que estamos ejecutando web2py, no tenemos estas vulnerabilidades, pero somos escaneados por ellos. Esto es molesto, entonces nos gustaría responder a estos escáneres de vulnerabilidades y hacer al atacante entender que está desperdiciando su tiempo.
-Una posibilidad es redireccionar todas las peticiones para .php, .asp, y todo sospechoso a una acción dummy que responderá al atacante manteniendo al atacante ocupado por una gran cantidad de tiempo. Eventualmente el atacante se rendirá y no nos escaneará de nuevo.
+Una posibilidad es redireccionar todas las peticiones para .php, .asp, y toda solicitud sospechosa a una acción ficticia o ''dummy'' que responderá al atacante manteniendolo ocupado por una gran cantidad de tiempo. Eventualmente el atacante se rendirá y no nos escaneará de nuevo.
Esta receta requiere de dos partes.
-Una aplicación dedicada llamada **jammer** con un controlador "default.py" como sigue:
+Una aplicación dedicada llamada **atascador** con un controlador "default.py" como sigue:
``
-class Jammer():
+class Atascador():
def read(self,n): return 'x'*n
-def jam(): return response.stream(Jammer(),40000)
+def atascar(): return response.stream(Atascador(),40000)
``:code
-Cuando esta acción es invocada, responderá con un infinito flujo de data de "x"-es. 40000 caracteres al mismo tiempo.
+Cuando esta acción es invocada, responderá con un infinito flujo de datos de "x"-es. 40000 caracteres al mismo tiempo.
El segundo ingrediente es un archivo "route.py" que redireccione cualquier petición terminada en .php, .asp, etc. (ambos en minúsculas y mayúsculas) a su controlador.
``
route_in=(
- ('.*\.(php|PHP|asp|ASP|jsp|JSP)','jammer/default/jam'),
+ ('.*\.(php|PHP|asp|ASP|jsp|JSP)','atascador/default/atascar'),
)
``:code
-La primera vez que has sido atacado puede ocurrir una pequeña sobreutilización de recursos, pero nuestra experiencia indica que el mismo atacante no lo intentará dos veces.
+La primera vez que has sido atacado puede ocurrir una pequeña sobreutilización de recursos, pero nuestra experiencia indica que el mismo atacante no lo intentará dos veces.
+
View
502 sources/36-web2py-spanish-translation-in-progress/14.markmin~
@@ -0,0 +1,502 @@
+## Otras Recetas
+
+### Upgrade
+``upgrades``:inxx
+
+En el "site" página de la interfaz administrativa existe un botón "upgrade now" (actualice la versión ahora). En caso que no esté disponible o no funcione (por ejemplo por problema de bloqueo de un archivo), actualizar web2py manualmente es muy fácil.
+
+-------
+Simplemente descomprime la última versión de web2py sobre la vieja instalación.
+-------
+
+Esto actualizará todas las librerías así como también las aplicaciones **admin**, **examples**, **welcome**. Además también creará un nuevo archivo vacío "NEWINSTALL". Al reiniciar, web2py eliminará los archivos vacíos y empaquetará la aplicación "welcome" en "welcome.w2p". Esta última será usada como la nueva estructura de la aplicación.
+web2py no actualiza cualquier otro archivo existente en otra aplicación.
+
+### Cómo distribuir tus aplicaciones como binarios
+
+Es posible empaquetar tus aplicaciones con la distribución binaria de web2py y distribuirlas juntas. La licencia lo permite, siempre y cuando dejes claro en la licencia de tu aplicación que tu estas agregando web2py y añadas un enlace a ``web2py.com``.
+
+Aquí explicamos como hacer esto para Windows:
+
+- Crea tu aplicación como usalmente lo haces.
+- Usando **admin**, compila tu aplicación(one click)
+- Usando **admin**, empaqueta la aplicación compilada(another click)
+- Descomprime esto en la carpeta "myapp" y comienza ahí (two clicks)
+- Carga usando **admin** el anterior paquete de la app compilada con el nombre "init" (one click)
+- Crea un archivo "myapp/start.bat" que contenga "cd web2py; web2py.exe"
+- comprime la carpeta miaplicacion en un archivo "myapp.zip"
+- distribuye y/o vende "myapp.zip"
+
+Cuando los usuarios descompriman "myapp.zip" y hagan click "run" ellos verán tu aplicación en lugar de la aplicación "welcome".
+No tiene requerimientos del lado del usuario, ni incluso tener python pre-instalado.
+
+Para binarios en Mac el proceso es el mismo pero no hay necesidad de crear el archivo "bat".
+
+### Construyendo un web2py minimalista
+
+A veces necesitamos implementar web2py en un servidor con muy poca memoria RAM. En este caso nosotros queremos disminuir web2py a su mínima expresión.
+
+Una sencilla manera de hacer esto es la siguiente:
+- En una máquina de producción, instala web2py desde las fuentes.
+- Desde adentro de la carpeta principal de web2py ejecuta
+``
+python scripts/make_min_web2py.py /path/to/minweb2py
+``
+- Ahora copia sobre "/path/to/minweb2py/applications" la aplicación que quieres implementar
+- Implementa "/path/to/minweb2py" a el pequeño servidor.
+
+El script "make_min_web2py.py" creará una distribución mínima de web2py que no incluye:
+- admin
+- examples
+- welcome
+- scripts
+- raramente usados modulos contrib
+
+Esto incluye una aplicación "welcome" que consiste de un archivo para permitir la implementación de pruebas.
+Mira este script. Al principio contiene una lista detallada de qué está incluido y qué es ignorado. Tu puedes fácilmente modificarlo y ajustar a tus necesidades.
+
+### Obteniendo una URL externa
+``fetch``:inxx
+
+Python incuye la librería ``urllib`` para descargar recursos desde un url:
+``
+import urllib
+page = urllib.urlopen('http://www.web2py.com').read()
+``:code
+
+``API``:inxx
+
+Esto es usualmente correcto, pero el modulo ``urllib`` no funciona sobre "Google App Engine". Google provee una diferente API para descargar URLs que solamente funciona en GAE. en orden de hacer tu código portable, web2py incluye una función ``fetch`` que funcióna en GAE así mismo en otras instalaciones de Python
+``
+from google.tools import fetch
+page = fetch('http://www.web2py.com')
+``:code
+
+### Pretty date
+``prettydate``:inxx
+
+Es usualmente útil para representar un datetime no como "2009-07-25 14:34:56" pero como "hace un año". web2py proporciona una función para esto:
+``
+import datetime
+d = datetime.datetime(2009,7,25,14,34,56)
+from gluon.tools import prettydate
+pretty_d = prettydate(d,T)
+``:code
+
+El segundo argumento (T) debe ser pasado a través de la internacionalización para la salida.
+
+### Geocoding
+``geocode``:inxx
+
+Si necesitas convertir una dirección (por ejemplo: "243 S Wabash Ave, Chicago, IL, USA") en coordenadas geográficas (latitud y longitud), web2py provee una función para realizar eso, entonces.
+``
+from gluon.tools import geocode
+address = '243 S Wabash Ave, Chicago, IL, USA'
+(latitude, longitude) = geocode(address)
+``:code
+
+La función ``geocode`` require una conexión a internet además se conecta al servicio de Google de geocodificación. La función retorna ``(0,0)`` en caso de fallar. Nota que el servicio de Google de geocodificación tiene un número máximo de peticiones, entonces debes verificar sus términos y condiciones. La función ``geocode`` es implementada al comienzo de la función ``fetch`` y por esto funcióna en GAE.
+
+### Paginación
+``pagination``:inxx
+
+Esta receta es un truco útil para minimizar el acceso a base de datos en el caso de la paginación, e.g., cuando necesitas mostrar una lista de filas desde una base de datos pero quieres distribuir las filas sobre múltiples páginas.
+
+Comienza creando una aplicación **primos** que almacene los primeros 1000 números primos en una base de datos.
+
+Acá está el modelo ``db.py``:
+``
+db = DAL('sqlite://primos.db')
+db.define_table('primos',Field('valor','integer'))
+def esprimo(p):
+ for i in range(2,p):
+ if p%i==0: return False
+ return True
+if len(db().select(db.prime.id))==0:
+ p=2
+ for i in range(1000):
+ while not esprimo(p): p+=1
+ db.primo.insert(value=p)
+ p+=1
+``:code
+
+Ahora crea una acción ``list_items`` in the "default.py" en el controlador que se lea de esta forma:
+``
+def listar_elementos():
+ if len(request.args): pagina=int(request.args[0])
+ else: pagina=0
+ elementos_por_pagina=20
+ limitby=(pagina*elementos_por_pagina,(pagina+1)*elementos_por_pagina+1)
+ registros=db().select(db.primo.ALL,limitby=limitby)
+ return dict(registros=registros,pagina=pagina,
+ elementos_por_pagina=elementos_por_pagina)
+``:code
+
+Nota que este código selecciona uno o más item de los que necesita, 20+1. el elemento extra dice a la vista si existe la siguiente página.
+
+Aquí es la vista "default/list_items.html":
+``
+{{extend 'layout.html'}}
+
+{{for i,registro in enumerate(registros):}}
+{{if i==elementos_por_pagina: break}}
+{{=registro.valor}}<br />
+{{pass}}
+
+{{if pagina:}}
+<a href="{{=URL(args=[pagina-1])}}">previa</a>
+{{pass}}
+
+{{if len(registros)>items_per_page:}}
+<a href="{{=URL(args=[pagina+1])}}">próxima</a>
+{{pass}}
+``:code
+
+En esta manera podemos obtener la paginación con un sólo "select" por acción,y que un "select" sólo obtenga una fila más de lo que necesita.
+
+### httpserver.log y el Formato del archivo de bitácora.
+``httpserver.log``:inxx
+
+El servidor de web2py registra todas las peticiones en un archivo llamado:
+``
+httpserver.log
+``:code
+
+en el directorio raíz de web2py. Un nombre alternativo y ubicación puede ser especificado a través de las opciones de la línea de comandos de web2py.
+
+Se añaden nuevas entradas al final del archivo cada vez que una peticón es realizada. Cada línea luce como esto:
+``
+127.0.0.1, 2008-01-12 10:41:20, GET, /admin/default/site, HTTP/1.1, 200, 0.270000
+``:code
+
+El formato es:
+``
+ip, timestamp, method, path, protocol, status, time_taken
+``:code
+
+Donde
+- ip es la dirección IP del cliente que hico la petición
+- timestamp es la fecha y la hora de la petición en el formato ISO 8601, YYYY-MM-DDT HH:MM:SS
+- method bien sea GET or POST
+- path es la ruta solicitada por el cliente
+- protocol es la versión del protocolo HTTP usado para enviar al cliente, usually HTTP/1.1
+- status es el código de estado del protocolo HTTP ``status``:cite
+- time_taken es la cantidad de tiempo que el servidor tarda en procesar la petición, en segundos, no incluye tiempos de upload/download.
+
+En el repositorio de aplicaciones ``appliances``:cite , podrás encontrar una aplicación para el análisis de logs (registros del sistema).
+
+Estos registros de logs estan deshabilitado por defecto cuando usas mod_wsgi a partir de esto podría ser igual como el log de Apache.
+
+### Llenando la Base de datos con dummy data.
+
+Para propósitos de pruebas es conveniente ser capaz de llenar la base de datos con información aleatoria. web2py incluye un clasificador bayesiano entrenado y listo para generar textos legibles para este propósito.
+
+Esta es la forma más simple de usar:
+``
+from gluon.contrib.populate import populate
+populate(db.mitabla,100)
+``:code
+
+Esto insertará 100 registros aleatorios en db.mitabla, e intentará hacer inteligentemente la generación de textos cortos para campos que sean cadenas, enteros, double, date, datetime, time, booleanos, etc. para el campo correspondiente. Intentará respetar los requerimientos impuestos por los validadores. Para campos que contienen la palabra "name" , intentará generar nombres dummy. Para campos reference se generarán referencias válidas.
+
+Si tienes dos tablas (A y B) donde B hace referencia a A, comprueba llenar primero A y luego B.
+
+Como las inserciones son hechas en una transacción, no intentes insertar muchísimos registros al mismo tiempo, particularmente si estan involucradas referencias. en su lugar, has un ciclo, insertando 100 cada vez, y luego un commit().
+``
+for i in range(10):
+ populate(db.mitabla,100)
+ db.commit()
+``:code
+
+También puedes usar el clasificador bayesiano para aprender características de algunos textos y generar textos aleatorios que sean similares, pero podría no tener sentido:
+``
+from gluon.contrib.populate import Learner, IUP
+ell=Learner()
+ell.learn('una entrada de texto realmente larga ...')
+print ell.generate(1000,prefix=None)
+``:code
+
+### Aceptando pagos con tarjetas de crédito
+
+``Google Wallet``:inxx ``Paypal``:inxx ``Stripe.com``:inxx
+``Authorize.net``:inxx ``DowCommerce``:inxx
+
+Existen múltiples maneras de aceptar pagos con tarjetas de crédito por internet. web2py proporciona una API especifica para algunos de los más populares y prácticos:
+
+- Google Wallet ``googlewallet``:cite
+- PayPal ``paypal``cite
+- Stripe.com ``stripe``:cite
+- Authorize.net ``authorizenet``:cite
+- DowCommerece ``dowcommerce``:cite
+
+
+Los primeros dos mecanismos delegan el proceso de autenticación del pago en un servicio de terceros. Mientras esta es la mejor solución de seguridad (tu aplicación no tiene que manejar ninguna información de tarjetas de crédito) esto hace el proceso incómodo (el usuario debe loguearse dos veces; por ejemplo, una vez para tu aplicación, y otra con Google) y no permite que tu aplicación maneje pagos sucesivos en una forma automatizada.
+
+Hay veces que necesitas más control y quieres generar el formulario de entrada para la información de las tarjetas de crédito y que programaticalmente pregunte a quién lo procesa cómo transferir el dinero desde la tarjeta de crédito a tu cuenta.
+
+Por esta razón web2py provee integración lista para usar con Stripe, Authorize.net (el modulo fue desarrollado por John Conde y ligeramente modificado) y DowCommerce. Stripe es la aplicación más simple de usar y también la más económica para bajo volumen de transacciones (No cobran un cargo fijo pero el costo por transacción está sobre el 3%). Authorize.net es mejor para altos volúmenes (tiene una tarifa fija anual más un bajo costo por transacción).
+
+Ten en cuenta que en el caso de Stripe y Authorize.net tu programa estará aceptando la información de las tarjetas de crédito. No tienes que almacenar esta información y nosotros te aconsejamos no hacerlo, por los requerimientos legales que involucra (verificar con Visa o Mastercard) pero hay ocasiones en las que tu puedes querer almacenar la información para pagos sucesivos o reproducir el botón de pago de un sólo click de Amazon.
+
+#### Google Wallet
+
+La manera más sencilla de usar Google Wallet (Level 1) consiste en integrar un botón a tu página y cuando hagan click, redirigir a tus visitantes a la página de pagos provista por Google.
+
+Primero que todo necesitas registrar una cuenta de Google Merchant en la siguiente url:
+
+``
+https://checkout.google.com/sell
+``
+
+Necesitarás indicarle a Google tu información bancaria. Google te asignará un identificador ``merchant_id`` y una clave ``merchant_key`` (no los confundas, mantenlos en secreto).
+
+Entonces simplemente necesitas crear el siguiente código en tu vista:
+
+``
+{{from gluon.contrib.google_wallet import button}}
+{{=button(merchant_id="123456789012345",
+ products=[dict(name="shoes",
+ quantity=1,
+ price=23.5,
+ currency='USD',
+ description="running shoes black")])}}
+``
+
+Cuando un visitante hace click en el botón, el visitante será redireccionado a la página de google donde ella o él pueden pagar por los artículos. Aquí productos son una lista de productos y cada producto es un diccionario de parámetros que quieres pasar describiendo tus artículos (nombre, cantidad, precio, moneda, descripción, y otros opcionales que puedes encontrar descriptos en la documentación de Google Wallet).
+
+Si eliges usar este mecanismo, debes generar los valores pasados al botón programado con información basada en tu inventario y del carrito de compra del visitante.
+
+Todas la información de tasas y tarifas será manejada del lado de Google. Lo mismo vale para la información de la cuenta. Por defecto tu aplicación no es informada si la transacción ha sido completada sin embargo podrías tener que visitar tu cuenta de Google Merchant para ver cuáles productos han sido vendidos y pagado por ellos, y cuáles productos necesitan ser enviados a sus compradores. también Google te enviará un email con la información.
+
+Si quieres una integración más estricta tienes que usar el nivel 2 de notificaciones de la API. En ese caso puedes pasar más información a Google y Google llamará a tu API para notificar las ventas. Esto permite mantener la información de la cuenta dentro de tu aplicación pero esto requiere que tengas servicios web que puedan comunicarse con Google Wallet.
+
+Esto último podría llegar a resultar complicado de programar para una app determinada, pero ya disponemos de un plugin que implementa una API para este propósito.
+
+``
+http://web2py.com/plugins/static/web2py.plugin.google_checkout.w2p
+``
+
+Puedes encontrar información sobre la documentación del plugin dentro del plugin.
+
+#### Paypal
+
+La integración con Paypal no es descrita aquí pero puedes encontrar más información en este enlace (recurso):
+
+``
+http://www.web2pyslices.com/main/slices/take_slice/9
+``
+
+#### Stripe.com
+
+Esta es probablemente uno de las más fáciles y flexibles maneras de aceptar pagos con tarjetas de crédito.
+
+Necesitas registrar con Stripe.com y eso es un proceso muy fácil, de hecho Stripe te asignará una llave de la API para pruebas antes de que crees cualquier credencial.
+
+Una vez que tienes tu llave de la API, puedes aceptar tarjetas de crédito, con el siquiente código:
+
+``
+from gluon.contrib.stripe import Stripe
+stripe = Stripe(api_key)
+d = stripe.charge(amount=100,
+ currency='usd',
+ card_number='4242424242424242',
+ card_exp_month='5',
+ card_exp_year='2012',
+ card_cvc_check='123',
+ description='the usual black shoes')
+if d.get('paid',False):
+ # payment accepted
+elif:
+ # error is in d.get('error','unknown')
+``
+
+La respuesta, ``d``, es un diccionario que puedes explorar tu mismo. El número de tarjeta usado en el ejemplo es un sandbox y siempre será exitoso. Cada transacción está asociada a un identificador almacenado en ``d['id']``.
+
+Stripe también permite verificar una transaccion tiempo después:
+
+``
+d = Stripe(key).check(d['id'])
+``
+
+y una transacción de reembolso:
+
+``
+r = Stripe(key).refund(d['id'])
+if r.get('refunded',False):
+ # el reembolso se realizó con éxito
+elif:
+ # error is in d.get('error','unkown')
+``
+
+Stripe hace sencillo mantener la contabilidad dentro de tu aplicación.
+
+todas las comunicaciones entre tu aplicación y Stripe se realizan sobre servicios web RESTful. Stripe actualmente expone aún más servicios y proporciona un conjunto más amplio en la API de Python. Puedes leer más sobre esto en su sitio web.
+
+#### Authorize.Net
+
+Otra simple manera de aceptar tarjetas de crédito es usar Authorize.Net. Como es usual, necesitas registrarte y obtener un ``login`` y una llave para las transacciones (``transkey``). Una vez que tengas esto, funciona muy similar en espíritu como lo hace Stripe:
+
+``
+from gluon.contrib.AuthorizeNet import process
+if process(creditcard='4427802641004797',
+ expiration="122012,
+ total=100.0,cvv='123',tax=None,invoice=None,
+ login='cnpdev4289', transkey='SR2P8g4jdEn7vFLQ',testmode=True):
+ # el pago se ha procesado
+else:
+ # el pago se ha rechazado
+``:code
+
+Si tienes una cuenta válida de Authorize.Net deberías reemplazar el sandbox ``login`` y ``transkey`` con estos de tu cuenta, configurar ``testmode=False`` para ejecutar en la plataforma real en lugar del sandbox, y usar la información de la tarjeta de crédito dada por el visitante.
+
+Si ``process`` devuelve ``True``, el dinero ha sido transferido desde la tarjeta de crédito del visitante a tu cuenta en Authorize.Net. ``invoice`` es sólo un string que puede ser configurado y será almacenado por Authorize.Net con esta transacción. Luego, tienes que conciliar la data con la información en tu aplicación.
+
+Aquí un ejemplo más complejo del workflow donde se exponen más variables:
+``
+from gluon.contrib.AuthorizeNet import AIM
+payment = AIM(login='cnpdev4289',
+ transkey='SR2P8g4jdEn7vFLQ',
+ testmod=True)
+payment.setTransaction(creditcard, expiration, total, cvv, tax, invoice)
+payment.setParameter('x_duplicate_window', 180) # duplicate_window de tres minutos
+payment.setParameter('x_cust_id', '1324') # ID del cliente
+payment.setParameter('x_first_name', 'Agent')
+payment.setParameter('x_last_name', 'Smith')
+payment.setParameter('x_company', 'Test Company')
+payment.setParameter('x_address', '1234 Main Street')
+payment.setParameter('x_city', 'Townsville')
+payment.setParameter('x_state', 'NJ')
+payment.setParameter('x_zip', '12345')
+payment.setParameter('x_country', 'US')
+payment.setParameter('x_phone', '800-555-1234')
+payment.setParameter('x_description', 'Test Transaction')
+payment.setParameter('x_customer_ip', socket.gethostbyname(socket.gethostname()))
+payment.setParameter('x_email', 'you@example.com')
+payment.setParameter('x_email_customer', False)
+
+payment.process()
+if payment.isApproved():
+ print 'Response Code: ', payment.response.ResponseCode
+ print 'Response Text: ', payment.response.ResponseText
+ print 'Response: ', payment.getResultResponseFull()
+ print 'Transaction ID: ', payment.response.TransactionID
+ print 'CVV Result: ', payment.response.CVVResponse
+ print 'Approval Code: ', payment.response.AuthCode
+ print 'AVS Result: ', payment.response.AVSResponse
+elif payment.isDeclined():
+ print 'Su tarjeta de crédito fue rechazada por el banco'
+elif payment.isError():
+ print 'No ha funcionado'
+print 'aprovada',payment.isApproved()
+print 'rechazada',payment.isDeclined()
+print 'error',payment.isError()
+``:code
+
+Nota el código de arriba usa una cuenta de pruebas. Necesitas registrarte con Authorize.Net (no es un servicio gratuito) y provee tu propio login, transkey, testmode=True or False para el constructor AIM.
+
+### Dropbox API
+
+``Dropbox.com``:inxx
+
+Dropbox es un servicio de almacenamiento muy popular. No es sólo de almacenamiento de tus archivos porque mantiene el almacenamiento en la nube sincronizado con todas tus máquinas (PCs or dispositivos). Esto permite crear grupos y dar permisos de lectura/escritura a varias carpetas hasta usuarios individuales o grupos. También mantiene historial de versiones de todos tus archivos. E incluye una carpeta llamada "Public" y cada archivo que coloques ahí tendrá su propia URL pública. Dropbox es una excelente manera de colaborar.
+
+Puedes accedes a dropbox fácilmente registrandote en
+
+``
+https://www.dropbox.com/developers
+``
+
+Y obtendrás una ``APP_KEY`` y un ``APP_SECRET``. Una vez que tu tengas esto puedes usar Dropbox para autenticar a tus usuarios.
+
+Crea un archivo llamado "tuapp/private/dropbox.key" y en él escribe
+``
+<APP_KEY>:<APP_SECERT>:app_folder
+``
+donde ``<APP_KEY>`` y ``APP_SECRET`` son tu llave (app_key) y la llave secreta (app_secret).
+
+Entonces en "models/db.py" coloca:
+
+``
+from gluon.contrib.login_methods.dropbox_account import use_dropbox
+use_janrain(auth,filename='private/dropbox.key')
+mydropbox = auth.settings.login_form
+``
+
+Esto permite a los usuarios autenticarse en tu aplicación usando sus credenciales dropbox, y tu programa será capaz de subir archivos en sus cuentas dropbox:
+
+``
+stream = open('archivolocal.txt','rb')
+mydropbox.put('archivodestino.txt',stream)
+``
+
+descargando archivos:
+
+``
+stream = mydropbox.get('archivodestino.txt')
+open('archivolocal.txt','wb').write(read)
+``
+
+y obtener el listado del directorio:
+
+``
+contenidos = mydropbox.dir(path = '/')['contents']
+``
+
+### Twitter API
+
+Aquí mostramos algunos ejemplos rápidos de cómo enviar y obtener tweets. No se requieren librerías de terceros, ya que Twitter ha creado una APIs RESTful.
+
+Aquí tenemos un ejemplo de cómo enviar un tweet:
+``
+def post_tweet(usuario, clave, mensaje):
+ import urllib, urllib2, base64
+ import gluon.contrib.simplejson as sj
+ args= urllib.urlencode([('status', ,mensaje)])
+ headers={}
+ headers['Authorization'] = 'Basic '+base64.b64encode(
+ usuario+':'+ clave)
+ req = urllib2.Request(
+ 'http://twitter.com/statuses/update.json',
+ args, headers)
+ return sj.loads(urllib2.urlopen(req).read())
+``:code
+
+Aquí un ejemplo de cómo recibir tweets:
+``
+def get_tweets():
+ usuario='web2py'
+ import urllib
+ import gluon.contrib.simplejson as sj
+ page = urllib.urlopen('http://twitter.com/%s?format=json' % usuario).read()
+ tweets=XML(sj.loads(page)['#timeline'])
+ return dict(tweets=tweets)
+``:code
+
+Para operaciones más complejas, revise la documentación de la API de Twitter.
+
+### Streaming virtual files
+``streaming``:inxx
+
+Es común para atacadores malisiosos escanear sitios web búscando vulnerabilidades. Ellos usan escaneres de seguridad como Nessus para explorar el sitio web objetivo, en búsqueda de scripts que son conocidos por tener vulnerabilidades. Un análisis de los logs del servidor web desde una máquina escaneadora o directamente en la base de datos Nessus revela que la mayoría de las vulnerabilidades conocidas están en scripts de PHP y ASP. Desde que estamos ejecutando web2py, no tenemos estas vulnerabilidades, pero somos escaneados por ellos. Esto es molesto, entonces nos gusta responder a estos escaneres de vulnerabilidades y hacer al atacante entender que está desperdiciando su tiempo.
+
+Una posibilidad es redireccionar todas las peticiones para .php, .asp, y todo sospechoso a una acción dummy que responderá al atacante manteniendo al atacante ocupado por una gran cantidad de tiempo. Eventualmente el atacante se rendirá y no nos escaneará de nuevo.
+
+Esta receta requiere de dos partes.
+
+Una aplicación dedicada llamada **jammer** con un controlador "default.py" como sigue:
+``
+class Jammer():
+ def read(self,n): return 'x'*n
+def jam(): return response.stream(Jammer(),40000)
+``:code
+
+Cuando esta acción es invocada, responderá con un infinito flujo de data de "x"-es. 40000 caracteres al mismo tiempo.
+
+El segundo ingrediente es un archivo "route.py" que redireccione cualquier petición terminada en .php, .asp, etc. (ambos en minúsculas y mayúsculas) a su controlador.
+``
+route_in=(
+ ('.*\.(php|PHP|asp|ASP|jsp|JSP)','jammer/default/jam'),
+)
+``:code
+
+La primera vez que has sido atacado puede ocurrir una pequeña sobreutilización de recursos, pero nuestra experiencia indica que el mismo atacante no lo intentará dos veces.

0 comments on commit 49b0804

Please sign in to comment.