#!/usr/bin/env python
#
# Copyright (C) 2012 KLab Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# -*- coding: utf-8 -*-

import cgi
import webapp2
import binascii
from Crypto.Cipher import AES
from google.appengine.api import urlfetch

HCTYPE    = 'Content-Type'
TYPEPLAIN = 'text/plain'
TYPEHTML  = 'text/html; charset=utf-8'
APIKEY    = '**API_KEY**'

class MyMain(webapp2.RequestHandler):
	def get(self):
		self.response.headers[HCTYPE] = TYPEPLAIN

class MySend(webapp2.RequestHandler):
	def get(self):
		self.response.headers[HCTYPE] = TYPEPLAIN
		self.response.out.write('???');

	def post(self):
		id = cgi.escape(self.request.get('id'))
		pw = cgi.escape(self.request.get('pass'))
		if len(id) <= 0 or len(pw) <= 0:
			self.get()
			return
		key = fix_key(pw)
		iv = key[::-1]
		id_plain = decrypt_id(key, iv, id)
		if len(id_plain) <= 0:
			self.get()
			return
		target = ""
		max = 100
		i = 0
		while max > i:
			var = 'Entry%02d' % i
			i += 1
			val = cgi.escape(self.request.get(var))
			if len(val) > 0:
				target += val + ","
		self.response.headers[HCTYPE] = TYPEHTML
		self.response.out.write('<html><head><title>WOLRemote</title></head><body>')
		if len(target) > 0:
			#self.response.out.write(target)
			self.response.out.write(send_msg(id_plain, target))
		else:
			self.response.out.write("No target is specified!")
		self.response.out.write('</body></html>')

app = webapp2.WSGIApplication([('/', MyMain), ('/push01', MySend)], debug=True)

def fix_key(keyraw):
	key = keyraw;
	keylen = len(key)
	if keylen < 16:
		num = 0;
		for var in range(keylen, 16):
			key += str(num);
			num += 1;
			if num >= 10:
				num = 0
	else:
		key = key[0:16]
	return key

def decrypt_id(key, iv, id):
	dec = AES.new(key, AES.MODE_CBC, iv)
	try:
		id_bin = binascii.unhexlify(id);
	except TypeError:
		return ""
	id_plain = dec.decrypt(id_bin)
	p = len(id_plain)
	while p > 0:
		c = ord(id_plain[p-1])
		if c >= 0x20 and c <= 0x7e:
			break;
		p -= 1
	id_plain = id_plain[0:p]
	while p > 0:
		c = ord(id_plain[p-1])
		if c < 0x20 or c > 0x7e:
			id_plain = ""
			break;
		p -= 1
	return id_plain

def send_msg(regid, target):
	url = 'https://android.googleapis.com/gcm/send'
	body = 'registration_id=' + regid + \
			'&collapse_key=wolremote_msg' + \
			'&data.action=boot&data.target=' + target + \
			'&time_to_live=3600&delay_while_idle=0'
	try:
		result = urlfetch.fetch(url=url,
				payload=body,
				method=urlfetch.POST,
				headers={'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
						'Authorization': 'key=' + APIKEY})
	except:
		return 'failed to fetch [' + url + ']'
	if result.content.startswith('id='):
		return str(result.status_code) + ' SUCCESS'
	else:
		return str(result.status_code) + ' ' + result.content

