LinuxParty
NUESTRO SITIO necesita la publicidad para costear hosting y el dominio. Por favor considera deshabilitar tu AdBlock en nuestro sitio. También puedes hacernos una donación entrando en linuxparty.es, en la columna de la derecha.
Este código fuente de Woof, contiene las modificaciones del artículo:
#!/usr/bin/env python3 ################################################################ # Para trabajar con varios archivos, meterlo en un bucle... # # for i in {1..10} ; do echo $i ; woof -U ; done # # o utilizar el script "multiples-woof.sh", abajo descrito. ############################################################### # -*- encoding: utf-8 -*- # # woof -- an ad-hoc single file webserver # Copyright (C) 2004-2009 Simon Budig <Esta dirección de correo electrónico está siendo protegida contra los robots de spam. Necesita tener JavaScript habilitado para poder verlo.> # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # A copy of the GNU General Public License is available at # http://www.fsf.org/licenses/gpl.txt, you can also write to the # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. # Darwin support with the help from Mat Caughron, <Esta dirección de correo electrónico está siendo protegida contra los robots de spam. Necesita tener JavaScript habilitado para poder verlo.> # Solaris support by Colin Marquardt, <Esta dirección de correo electrónico está siendo protegida contra los robots de spam. Necesita tener JavaScript habilitado para poder verlo.> # FreeBSD support with the help from Andy Gimblett, <Esta dirección de correo electrónico está siendo protegida contra los robots de spam. Necesita tener JavaScript habilitado para poder verlo.> # Cygwin support by Stefan Reichör <Esta dirección de correo electrónico está siendo protegida contra los robots de spam. Necesita tener JavaScript habilitado para poder verlo.> # tarfile usage suggested by Morgan Lefieux <Esta dirección de correo electrónico está siendo protegida contra los robots de spam. Necesita tener JavaScript habilitado para poder verlo.> # File upload support loosely based on code from Stephen English <Esta dirección de correo electrónico está siendo protegida contra los robots de spam. Necesita tener JavaScript habilitado para poder verlo.> import sys, os, errno, socket, getopt, subprocess, tempfile import cgi, urllib.request, urllib.parse, http.server import readline import configparser import shutil, tarfile, zipfile import struct maxdownloads = 1 TM = object cpid = -1 compressed = 'gz' upload = False class EvilZipStreamWrapper(TM): def __init__ (self, victim): self.victim_fd = victim self.position = 0 self.tells = [] self.in_file_data = 0 def tell (self): self.tells.append (self.position) return self.position def seek (self, offset, whence = 0): if offset != 0: if offset == self.tells[0] + 14: # the zipfile module tries to fix up the file header. # write Data descriptor header instead, # the next write from zipfile # is CRC, compressed_size and file_size (as required) self.write (b"PK\007\010") elif offset == self.tells[1]: # the zipfile module goes to the end of the file. The next # data written definitely is infrastructure (in_file_data = 0) self.tells = [] self.in_file_data = 0 else: raise IOError ("unexpected seek for EvilZipStreamWrapper") def write (self, data): # only test for headers if we know that we're not writing # (potentially compressed) data. if self.in_file_data == 0: if data[:4] == zipfile.stringFileHeader: # fix the file header for extra Data descriptor hdr = list (struct.unpack (zipfile.structFileHeader, data[:30])) hdr[3] |= (1 << 3) data = struct.pack (zipfile.structFileHeader, *hdr) + data[30:] self.in_file_data = 1 elif data[:4] == zipfile.stringCentralDir: # fix the directory entry to match file header. hdr = list (struct.unpack (zipfile.structCentralDir, data[:46])) hdr[5] |= (1 << 3) data = struct.pack (zipfile.structCentralDir, *hdr) + data[46:] self.position += len (data) self.victim_fd.write (data) def __getattr__ (self, name): return getattr (self.victim_fd, name) # Utility function to guess the IP (as a string) where the server can be # reached from the outside. Quite nasty problem actually. def find_ip (): # we get a UDP-socket for the TEST-networks reserved by IANA. # It is highly unlikely, that there is special routing used # for these networks, hence the socket later should give us # the ip address of the default route. # We're doing multiple tests, to guard against the computer being # part of a test installation. candidates = [] for test_ip in ["192.0.2.0", "198.51.100.0", "203.0.113.0"]: s = socket.socket (socket.AF_INET, socket.SOCK_DGRAM) s.connect ((test_ip, 80)) ip_addr = s.getsockname ()[0] s.close () if ip_addr in candidates: return ip_addr candidates.append (ip_addr) return candidates[0] # our own HTTP server class, fixing up a change in python 2.7 # since we do our fork() in the request handler # the server must not shutdown() the socket. class ForkingHTTPServer (http.server.HTTPServer): def process_request (self, request, client_address): self.finish_request (request, client_address) self.close_request (request) # Main class implementing an HTTP-Requesthandler, that serves just a single # file and redirects all other requests to this file (this passes the actual # filename to the client). # Currently it is impossible to serve different files with different # instances of this class. class FileServHTTPRequestHandler (http.server.BaseHTTPRequestHandler): server_version = "Simons FileServer" protocol_version = "HTTP/1.0" filename = "." def log_request (self, code='-', size='-'): if code == 200: http.server.BaseHTTPRequestHandler.log_request (self, code, size) def do_POST (self): global maxdownloads, upload if not upload: self.send_error (501, "Unsupported method (POST)") return # taken from # http://mail.python.org/pipermail/python-list/2006-September/402441.html ctype, pdict = cgi.parse_header (self.headers['Content-Type']) form = cgi.FieldStorage (fp = self.rfile, headers = self.headers, environ = {'REQUEST_METHOD' : 'POST'}, keep_blank_values = 1, strict_parsing = 1) if "upfile" not in form: self.send_error (403, "No upload provided") return upfile = form["upfile"] if not upfile.file or not upfile.filename: self.send_error (403, "No upload provided") return upfilename = upfile.filename if "\\" in upfilename: upfilename = upfilename.split ("\\")[-1] upfilename = os.path.basename (upfile.filename) destfile = None for suffix in ["", ".1", ".2", ".3", ".4", ".5", ".6", ".7", ".8", ".9"]: destfilename = os.path.join (".", upfilename + suffix) try: destfile = os.open (destfilename, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o644) break except OSError as e: if e.errno == errno.EEXIST: continue raise if not destfile: upfilename += "." destfile, destfilename = tempfile.mkstemp (prefix = upfilename, dir = ".") print ("accepting uploaded file: %s -> %s" % (upfilename, destfilename), file=sys.stderr) shutil.copyfileobj (upfile.file, os.fdopen (destfile, "wb")) if upfile.done == -1: self.send_error (408, "upload interrupted") txt = b"""\ <html> <head><title>Woof Upload</title></head> <body> <h1>Woof Upload complete</title></h1> <p>Thanks a lot!</p> <h1> <p> <br> </p> <p> <br> </p> <p> <br> </p> <p> <br> </p> <p> <br> </p> <p> <br> </p> <center> <p style="font-size:250%" ><a href="/"> INICIO </h1></a></p> </center> </body> </html> """ self.send_response (200) self.send_header ("Content-Type", "text/html") self.send_header ("Content-Length", str (len (txt))) self.end_headers () self.wfile.write (txt) maxdownloads -= 1 return def do_GET (self): global maxdownloads, cpid, compressed, upload # txt = b"""\ # <html> # <head><title>Woof Upload</title></head> # <body> # <h1>Woof Upload</title></h1> # <form name="upload" method="POST" enctype="multipart/form-data"> # <p><input type="file" name="upfile" /></p> # <p><input type="submit" value="Upload!" /></p> # </form> # </body> # </html> # """ # Form for uploading a file if upload: txt = b"""\ <html> <head><title>Woof Upload</title> </head> <body> <table border="1" cellpadding="1" cellspacing="1" style="height:100%; width:100%"> <tr> <td> <h1><span style="font-size:45px">Woof Upload</span></h1> </td> </tr> <tr> <td> <form class="formatoReporte" name="upload" method="POST" enctype="multipart/form-data"> <p><input style="font-size:250%" type="file" name="upfile" /></p> <p><input style="font-size:250%" type="submit" value="Enviar!" /></p> </form> </td> </tr> </table> </body> </html> """ self.send_response (200) self.send_header ("Content-Type", "text/html") self.send_header ("Content-Length", str (len (txt))) self.end_headers () self.wfile.write (txt) return # Redirect any request to the filename of the file to serve. # This hands over the filename to the client. self.path = urllib.parse.quote (urllib.parse.unquote (self.path)) location = "/" + urllib.parse.quote (os.path.basename (self.filename)) if os.path.isdir (self.filename): if compressed == 'gz': location += ".tar.gz" elif compressed == 'bz2': location += ".tar.bz2" elif compressed == 'zip': location += ".zip" else: location += ".tar" if self.path != location: txt = """\ <html> <head><title>302 Found</title></head> <body>302 Found <a href="/%s">here</a>.</body> </html>\n""" % location txt = txt.encode ('ascii') self.send_response (302) self.send_header ("Location", location) self.send_header ("Content-Type", "text/html") self.send_header ("Content-Length", str (len (txt))) self.end_headers () self.wfile.write (txt) return maxdownloads -= 1 # let a separate process handle the actual download, so that # multiple downloads can happen simultaneously. cpid = os.fork () if cpid == 0: # Child process child = None type = None if os.path.isfile (self.filename): type = "file" elif os.path.isdir (self.filename): type = "dir" if not type: print ("can only serve files or directories. Aborting.", file=sys.stderr) sys.exit (1) self.send_response (200) self.send_header ("Content-Type", "application/octet-stream") self.send_header ("Content-Disposition", "attachment;filename=%s" % urllib.parse.quote (os.path.basename (self.filename))) if os.path.isfile (self.filename): self.send_header ("Content-Length", os.path.getsize (self.filename)) self.end_headers () try: if type == "file": datafile = open (self.filename, "rb") shutil.copyfileobj (datafile, self.wfile) datafile.close () elif type == "dir": if compressed == 'zip': ezfile = EvilZipStreamWrapper (self.wfile) zfile = zipfile.ZipFile (ezfile, 'w', zipfile.ZIP_DEFLATED) stripoff = os.path.dirname (self.filename) + os.sep for root, dirs, files in os.walk (self.filename): for f in files: filename = os.path.join (root, f) if filename[:len (stripoff)] != stripoff: raise RuntimeException ("invalid filename assumptions, please report!") zfile.write (filename, filename[len (stripoff):]) zfile.close () else: tfile = tarfile.open (mode=('w|' + compressed), fileobj=self.wfile) tfile.add (self.filename, arcname=os.path.basename (self.filename)) tfile.close () except Exception as e: print (e) print ("Connection broke. Aborting", file=sys.stderr) def serve_files (filename, maxdown = 1, ip_addr = '', port = 8080): global maxdownloads maxdownloads = maxdown # We have to somehow push the filename of the file to serve to the # class handling the requests. This is an evil way to do this... FileServHTTPRequestHandler.filename = filename try: httpd = ForkingHTTPServer ((ip_addr, port), FileServHTTPRequestHandler) except socket.error: print ("cannot bind to IP address '%s' port %d" % (ip_addr, port), file=sys.stderr) sys.exit (1) if not ip_addr: ip_addr = find_ip () if ip_addr: if filename: location = "http://%s:%s/%s" % (ip_addr, httpd.server_port, urllib.parse.quote (os.path.basename (filename))) if os.path.isdir (filename): if compressed == 'gz': location += ".tar.gz" elif compressed == 'bz2': location += ".tar.bz2" elif compressed == 'zip': location += ".zip" else: location += ".tar" else: location = "http://%s:%s/" % (ip_addr, httpd.server_port) print ("Now serving on %s" % location) while cpid != 0 and maxdownloads > 0: httpd.handle_request () def usage (defport, defmaxdown, errmsg = None): name = os.path.basename (sys.argv[0]) print (""" Usage: %s [-i <ip_addr>] [-p <port>] [-c <count>] <file> %s [-i <ip_addr>] [-p <port>] [-c <count>] [-z|-j|-Z|-u] <dir> %s [-i <ip_addr>] [-p <port>] [-c <count>] -s %s [-i <ip_addr>] [-p <port>] [-c <count>] -U %s <url> Serves a single file <count> times via http on port <port> on IP address <ip_addr>. When a directory is specified, an tar archive gets served. By default it is gzip compressed. You can specify -z for gzip compression, -j for bzip2 compression, -Z for ZIP compression or -u for no compression. You can configure your default compression method in the configuration file described below. When -s is specified instead of a filename, %s distributes itself. When -U is specified, woof provides an upload form, allowing file uploads. defaults: count = %d, port = %d If started with an url as an argument, woof acts as a client, downloading the file and saving it in the current directory. You can specify different defaults in two locations: /etc/woofrc and ~/.woofrc can be INI-style config files containing the default port and the default count. The file in the home directory takes precedence. The compression methods are "off", "gz", "bz2" or "zip". Sample file: [main] port = 8008 count = 2 ip = 127.0.0.1 compressed = gz """ % (name, name, name, name, name, name, defmaxdown, defport), file=sys.stderr) if errmsg: print (errmsg, file=sys.stderr) print (file=sys.stderr) sys.exit (1) def woof_client (url): urlparts = urllib.parse.urlparse (url, "http") if urlparts[0] not in [ "http", "https" ] or urlparts[1] == '': return None fname = None f = urllib.request.urlopen (url) f_meta = f.info () disp = f_meta["Content-Disposition"] if disp: disp = disp.split (";") if disp and disp[0].lower () == 'attachment': fname = [x[9:] for x in disp[1:] if x[:9].lower () == "filename="] if len (fname): fname = fname[0] else: fname = None if fname == None: url = f.geturl () urlparts = urllib.parse.urlparse (url) fname = urlparts[2] if not fname: fname = "woof-out.bin" if fname: fname = urllib.parse.unquote (fname) fname = os.path.basename (fname) readline.set_startup_hook (lambda: readline.insert_text (fname)) fname = input ("Enter target filename: ") readline.set_startup_hook (None) override = False destfile = None destfilename = os.path.join (".", fname) try: destfile = os.open (destfilename, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o644) except OSError as e: if e.errno == errno.EEXIST: override = input ("File exists. Overwrite (y/n)? ") override = override.lower () in [ "y", "yes" ] else: raise if destfile == None: if override == True: destfile = os.open (destfilename, os.O_WRONLY | os.O_CREAT, 0o644) else: for suffix in [".1", ".2", ".3", ".4", ".5", ".6", ".7", ".8", ".9"]: destfilename = os.path.join (".", fname + suffix) try: destfile = os.open (destfilename, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o644) break except OSError as e: if e.errno == errno.EEXIST: continue raise if not destfile: destfile, destfilename = tempfile.mkstemp (prefix = fname + ".", dir = ".") print ("alternate filename is:", destfilename) print ("downloading file: %s -> %s" % (fname, destfilename)) shutil.copyfileobj (f, os.fdopen (destfile, "wb")) return 1; def main (): global cpid, upload, compressed maxdown = 1 port = 8080 ip_addr = '' config = configparser.ConfigParser () config.read (['/etc/woofrc', os.path.expanduser ('~/.woofrc')]) if config.has_option ('main', 'port'): port = config.getint ('main', 'port') if config.has_option ('main', 'count'): maxdown = config.getint ('main', 'count') if config.has_option ('main', 'ip'): ip_addr = config.get ('main', 'ip') if config.has_option ('main', 'compressed'): formats = { 'gz' : 'gz', 'true' : 'gz', 'bz' : 'bz2', 'bz2' : 'bz2', 'zip' : 'zip', 'off' : '', 'false' : '' } compressed = config.get ('main', 'compressed') compressed = formats.get (compressed, 'gz') defaultport = port defaultmaxdown = maxdown try: options, filenames = getopt.getopt (sys.argv[1:], "hUszjZui:c:p:") except getopt.GetoptError as desc: usage (defaultport, defaultmaxdown, desc) for option, val in options: if option == '-c': try: maxdown = int (val) if maxdown <= 0: raise ValueError except ValueError: usage (defaultport, defaultmaxdown, "invalid download count: %r. " "Please specify an integer >= 0." % val) elif option == '-i': ip_addr = val elif option == '-p': try: port = int (val) except ValueError: usage (defaultport, defaultmaxdown, "invalid port number: %r. Please specify an integer" % val) elif option == '-s': filenames.append (__file__) elif option == '-h': usage (defaultport, defaultmaxdown) elif option == '-U': upload = True elif option == '-z': compressed = 'gz' elif option == '-j': compressed = 'bz2' elif option == '-Z': compressed = 'zip' elif option == '-u': compressed = '' else: usage (defaultport, defaultmaxdown, "Unknown option: %r" % option) if upload: if len (filenames) > 0: usage (defaultport, defaultmaxdown, "Conflicting usage: simultaneous up- and download not supported.") filename = None else: if len (filenames) == 1: if woof_client (filenames[0]) != None: sys.exit (0) filename = os.path.abspath (filenames[0]) else: usage (defaultport, defaultmaxdown, "Can only serve single files/directories.") if not os.path.exists (filename): usage (defaultport, defaultmaxdown, "%s: No such file or directory" % filenames[0]) if not (os.path.isfile (filename) or os.path.isdir (filename)): usage (defaultport, defaultmaxdown, "%s: Neither file nor directory" % filenames[0]) serve_files (filename, maxdown, ip_addr, port) # wait for child processes to terminate if cpid != 0: try: while 1: os.wait () except OSError: pass if __name__=='__main__': try: main () except KeyboardInterrupt: print ()
Con el objetivo de poder meter "woof" en una iteración (un bucle) y poder sacar varios archivos del... por ejemplo móvil al portatil creamos este script, que lo puedes ejecutar desde consola o crear un acceso en el escritorio (recuerda hacerlo visible desde la consola, si quieres) para hacerte más fácil éste trabajo... si lo quieres mejorar tú... mejor.
#!/bin/bash # Nombre del script: multiples-woof.sh # Para enviar multiples archivos... # for i in {1..10} ; do echo $i ; woof -U ; done exit
-
Scripting
- Iniciar una aplicación o un programa automáticamente desde el Cron en Linux
- Operaciones matemáticas en Shell Scripts
- 30 formas de validar archivos de configuración o scripts en Linux
- Operaciones artiméticas en Shell Scripts
- Cómo intercambiar el contenido de dos archivos en Linux
- Buscar directorios vacíos en Linux y borrarlos si procede.
- Shell Script Linux: Renombra quitando espacios
- Usar con crontab - último sábado del mes
- Shell Script de Linux para analizar un Fichero Access.log
- Analizar ficheros log de Linux con Scripts
- woof Código fuente
- Como tener seguro, protegido y encriptado tu Navegador Web Firefox (versión mejorada - versión 3)
- Arrays en Bash y Loops: iterar a través de los valores de la matriz
- Pasar una variable a AWK mediante la Shell.
- System Tar and Restore: un versátil script de copia de seguridad del sistema para Linux