#!/usr/bin/python

# httppost.py
#       --copyright--                   Copyright 2007 (C) Tranzoa, Co. All rights reserved.    Warranty: You're free and on your own here. This code is not necessarily up-to-date or of public quality.
#       --url--                         http://www.tranzoa.net/tzpython/
#       --email--                       pycode is the name to send to. tranzoa.com is the place to send to.
#       --bodstamps--
#       August 31, 2005         bar
#       November 18, 2007       bar     turn on doxygen
#       November 27, 2007       bar     insert boilerplate copyright
#       May 15, 2008            bar     --show_response
#                                       change to FF 2
#       May 17, 2008            bar     email adr
#       April 11, 2011          bar     add the multipart code snagged from the net
#       --eodstamps--
##      \file
#
#
#       Do a POST for a given URL.
#
#           e.g. http://wap.melodeo.com/verdi/tmestore/download/songnotify?r=25792&t=43162a7b&a=S3EE5HaFY3qauivb74If
#
#

import  itertools
import  mimetools
import  mimetypes
import  urllib2



opener            = urllib2.build_opener()
opener.addheaders = []                  # get rid of 'User-agent' the only way that seems to work (yes, I tried lower-casing 'Agent')
urllib2.install_opener(opener)


#
#
#   Code from http://uthcode.sarovar.org/pythonsnippets.html
#   urllib2-binary-upload.py - On 19 Dec,2010.
#
#
class   a_multipart_form(object):
    """Accumulate the data to be used when posting a form."""

    def __init__(me)    :
        me.form_fields  = []
        me.files        = []
        me.boundary     = mimetools.choose_boundary()

    def get_content_type(me) :
        return('multipart/form-data; boundary=%s' % me.boundary)

    def add_field(me, name, value) :
        """Add a simple field to the form data."""
        me.form_fields.append((name, value))

    def add_file_data(me, fieldname, filename, file_data, mimetype = None) :
        """Add file data to be uploaded."""
        mimetype        = mimetype or 'application/octet-stream'
        me.files.append((fieldname, filename, mimetype, file_data))

    def add_file(me, fieldname, filename, fileHandle, mimetype = None) :
        """Add a file to be uploaded."""
        body            = fileHandle.read()
        if  mimetype   is None :
            mimetype    = mimetypes.guess_type(filename)[0] or 'application/octet-stream'
        me.add_file_data(fieldname, filename, body, mimetype)

    def __str__(me) :
        """Return a string representing the form data, including attached files."""
        # Build a list of lists, each containing "lines" of the
        # request.  Each part is separated by a boundary string.
        # Once the list is built, return a string where each
        # line is separated by '\r\n'.
        parts           = []
        part_boundary   = '--' + me.boundary

        # Add the form fields
        parts.extend(
                        [
                            part_boundary,
                            'Content-Disposition: form-data; name="%s"' % name,
                            '',
                            value,
                        ]
                        for name, value in me.form_fields
                    )
        # Add the files to upload
        parts.extend(
                        [
                            part_boundary,
                            'Content-Disposition: file; name="%s"; filename="%s"' % \
                               (field_name, filename),
                            'Content-Type: %s' % content_type,
                            '',
                            body,
                        ]
                        for field_name, filename, content_type, body in me.files
                    )

        # Flatten the list and add closing boundary marker,
        # then return CR+LF separated data
        flattened   = list(itertools.chain(*parts))
        flattened.append('--' + me.boundary + '--')
        flattened.append('')
        return('\r\n'.join(flattened))

    #   a_multipart_form

if  False   :
    import  cStringIO
    import  sys
    import  time

    #       Create the form with simple fields
    form    = a_multipart_form()

    #       Add a fake file
    #       note: upload.pl expects to see this 'mode: upload' field and the field name for the file must be 'upload_file'
    form.add_field('mode', 'upload')
    form.add_file('upload_file', 'bio.txt', fileHandle = cStringIO.StringIO('Python developer and blogger. %s' % time.asctime(time.localtime())))

    # Build the request
    request = urllib2.Request('https://www.tranzoa.net/~alex/cgi-bin/upload.pl')
    request.add_header('User-agent', 'tzlib.httppost.a_multipart_form')
    body    = str(form)
    request.add_header('Content-type', form.get_content_type())
    request.add_header('Content-length', len(body))
    request.add_data(body)

    print
    print 'OUTGOING DATA:'
    print request.get_data()

    print
    print 'SERVER RESPONSE:'
    r   = urllib2.urlopen(request)
    print r.geturl(), "headers", r.headers.keys(), "code:", r.getcode()

    sys.exit(0)



#
#
#
if  __name__ == '__main__' :
    """

        Get some URLs to a directory named for the current Unix time.
        Put the time in the output file names, too.

    """


    import  re
    import  sys
    import  urlparse

    import  tzlib
    import  TZCommandLineAtFile
    import  url_getter


    del(sys.argv[0])

    TZCommandLineAtFile.expand_at_sign_command_line_files(sys.argv)


    cookies         = {}
    show_response   = False

    while True :
        oi  = tzlib.array_find(sys.argv, "--cookie")
        if  oi < 0 :    break
        del sys.argv[oi]
        ck_name = sys.argv.pop(oi)
        ck_val  = sys.argv.pop(oi)
        cookies[ck_name] = ck_val


    while True :
        oi  = tzlib.array_find(sys.argv, "--show_response")
        if  oi < 0 :    break
        del sys.argv[oi]
        show_response   = True



    cks = ""
    for c in cookies.keys() :
        v = cookies[c]
        cks += " " + c + "=" + v + ";"

    # print "adding cookie", cks


    while   len(sys.argv) > 0 :

        url     = sys.argv.pop(0)

        t       = []
        t      += urlparse.urlsplit(url)

        v       = t[3]
        t[3]    = ""

        if  not v :
            g   = re.match(r"(.+?)\?(.+)", t[1])
            if  g :
                v       = g.group(2)
                t[1]    = g.group(1)
            pass

        url     = urlparse.urlunsplit(t)

        req     = urllib2.Request(url)

        req.add_data(v)

        if  len(cks) > 0 :
            req.add_header('Cookie', cks)

        req.add_header('User-Agent',       'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.14) Gecko/20080404 Firefox/2.0.0.14')
        req.add_header('Accept',           'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,image/jpeg,image/gif;q=0.2,*/*;q=0.1')
        req.add_header('Accept-Language',  'en-us,en;q=0.5')
        # req.add_header('Accept-Encoding',  'gzip,deflate')
        req.add_header('Accept-Charset',   'ISO-8859-1,utf-8;q=0.7,*;q=0.7')
        req.add_header('Keep-Alive',       '300')
        req.add_header('Connection',       'keep-alive')

        r       = url_getter.url_open_read_with_timeout(req)
        if  r  == None :
            print "Failed to POST", url
            sys.exit(101)

        if  show_response :
            print r

        pass

    pass

#
#
#
# eof

