#!/usr/bin/env python

'''Tool to upload graphical overlays to an NCast Telepresenter.
Rewritten version by Matt Eastman
Updated by H. S. Magnuski

Usage: ncgo <options> <host>

 -d, --debug          Turn debug statements on (not used)
 -h, --help           Print usage information
 -p, --pswd=password  Use "password"
 -v, --version        Report program version
 -1, --g1             Overlay graphic 1
 -2, --g2             Overlay graphic 2
 -3, --g3             Overlay graphic 3
 -4, --g4             Overlay graphic 4
'''

__author__ = 'Matt Eastman <matt@meastman.org>'
__version__ = '2.1 (meastman rewrite, updated)'

import getopt
import mimetools
import mimetypes
import os
import sys
import urllib
import urllib2

def main():
  debug = False
  username = 'api'
  password = 'ncast'
  images = {}

  try:
    getopt_func = getopt.gnu_getopt
  except AttributeError:
    getopt_func = getopt.getopt
  shortopts = 'dhp:v1:2:3:4:'
  longopts = ('debug', 'help', 'pswd=', 'version', 'g1=', 'g2=', 'g3=', 'g4=')
  try:
    opts, args = getopt_func(sys.argv[1:], shortopts, longopts)
  except getopt.GetoptError, e:
    print >>sys.stderr, 'Error: %s' % str(e)
    print >>sys.stderr
    usage(sys.stderr)
    sys.exit(1)
  for optname, optvalue in opts:
    if optname in ('-d', '--debug'):
      debug = True
    elif optname in ('-h', '--help'):
      usage(sys.stdout)
      sys.exit(0)
    elif optname in ('-p', '--pswd'):
      password = optvalue
    elif optname in ('-v', '--version'):
      print __version__
      sys.exit(0)
    elif optname in ('-1', '-2', '-3', '-4', '--g1', '--g2', '--g3', '--g4'):
      imgnum = int(optname[-1])
      if not os.path.exists(optvalue):
        raise Exception('Invalid image file', optvalue)
      images[imgnum] = optvalue
    else:
      raise Exception('BUG: should have caught %s but didn\'t' % `optname`)

  if not images:
    print >>sys.stderr, 'Error: no images specified'
    print >>sys.stderr
    usage(sys.stderr)
    sys.exit(1)

  if not args:
    print >>sys.stderr, 'Error: no server specified'
    print >>sys.stderr
    usage(sys.stderr)
    sys.exit(1)
  server = args[0]

  upload(server, username, password, images)

def usage(stream):
  stream.write(__doc__)

def upload(server, username, password, filenames):

  # build payload
  print 'ncgo: building payload'
  fields = {}
  for key, filename in filenames.items():
    fields['overlay_%d_file' % key] = {
      'filename': os.path.basename(filename),
      'value': file(filename).read(),
      'content-type': get_content_type(filename),
    }
  content_type, data = encode_multipart_formdata(fields)

  # upload
  print 'ncgo: uploading image(s)'
  url = 'http://%s/api.cgi' % server
  # Create an OpenerDirector with support for Basic HTTP Authentication...
  auth_handler = urllib2.HTTPBasicAuthHandler()
  auth_handler.add_password(realm='NCast Telepresenter', uri=url, user=username, passwd=password)
  opener = urllib2.build_opener(auth_handler)
  # ...and install it globally so it can be used with urlopen.
  urllib2.install_opener(opener)
  request = urllib2.Request(url, data)
  request.add_header('Content-Type', content_type)

  try:
    response = urllib2.urlopen(request)
  except urllib2.HTTPError, msg:
    print "ncgo: Urllib2 HTTP Error (%s)" % msg
    sys.exit(1)
  except socket.error, (errno, strerror):
    print "ncgo: Socket error (%s) for host %s (%s)" % (errno, host, strerror)
    sys.exit(1)
  print 'ncgo: finished'
                            
def encode_multipart_formdata(fields):
  boundary = mimetools.choose_boundary()
  lines = []
  for key in fields:
    if isinstance(fields[key], dict):
      entry = fields[key]
    else:
      entry = {'value': fields[key]}
    lines.append('--' + boundary)
    if 'filename' in entry:
      lines.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, entry['filename']))
    else:
      lines.append('Content-Disposition: form-data; name="%s"' % key)
    if 'content-type' in entry:
      lines.append('Content-Type: %s' % entry['content-type'])
    lines.append('')
    lines.append(entry['value'])
  lines.append('--' + boundary + '--')
  lines.append('')
  body = '\r\n'.join(lines)
  content_type = 'multipart/form-data; boundary=%s' % boundary
  return (content_type, body)

def get_content_type(filename):
  type = mimetypes.guess_type(filename)[0]
  if type is None:
    type = 'application/octet-stream'
  return type

if __name__ == '__main__':
  main()

