reorx
7/18/2011 - 3:13 PM

demo of cross-site request to v2ex (reply to a topic)

demo of cross-site request to v2ex (reply to a topic)

#coding=utf-8
import sys
import time
import gzip
import logging
import urllib
from urllib import urlencode
import httplib
from Cookie import BaseCookie
from StringIO import StringIO

USER = {
    'name': '', # username
    'password': '' # password
}
BASIC_HEADERS = {
    'Content-Type': 'application/x-www-form-urlencoded'
}
REPLY_HEADERS = {
    'Host':'www.v2ex.com',
    'User-Agent':'Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.17) Gecko/20110422 Ubuntu/10.10 (maverick) Firefox/3.6.17',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Accept-Language':'zh-cn,zh;q=0.5',
    #'Accept-Encoding':'gzip,deflate',
    # if set 'gzip', gzip will be received..
    'Accept-Charset':'GB2312,utf-8;q=0.7,*;q=0.7',
    #'Keep-Alive':'115',
    'Connection':'keep-alive',
    'Content-Type':'application/x-www-form-urlencoded'
}
DIVIDE_LINE = '\n--------------------%s----------------------' % time.strftime('%Y-%m-%d', time.localtime())


def init_logger():
    logger = logging.getLogger()
    hdr = logging.FileHandler('v2ex_reply.log.txt')
    formatter = logging.Formatter('%(asctime)s    %(levelname)s    %(message)s')
    hdr.setFormatter(formatter)
    logger.addHandler(hdr)
    logger.setLevel(logging.NOTSET)
    return logger

class V2EX(object):
    DOMAIN = 'www.v2ex.com'
    def __init__(self, USER):
        print 'initializing..'
        self.user = USER
        self.login_form = {
            'u': self.user['name'],
            'p': self.user['password'],
        }
        self.cookie = None
        self.logger = init_logger()

    def _log(self, msg, error=False):
        if error:
            self.logger.error(msg)
        else:
            self.logger.info(msg)
    def _get_conn(self):
        return httplib.HTTPConnection(self.DOMAIN)
    def _read(self, resp):
        if not 'httplib' == resp.__module__:
            raise TypeError
        raw_body = resp.read()
        if 'gzip' == resp.getheader('Content-Encoding'):
            self._log('*uncompressing gzip data')
            buff = StringIO(raw_body)
            gzipf = gzip.GzipFile(fileobj=buff)
            data = gzipf.read()
            return data
        return raw_body
    def login(self):
        self._log('login..')
        conn = self._get_conn()
        headers = BASIC_HEADERS
        conn.request('POST',
            '/signin',
            urlencode(self.login_form),
            headers)
        resp = conn.getresponse()
        _cookie = resp.getheader('Set-Cookie')
        self._log('get cookie:%s' % _cookie)
        if not _cookie:
            raise ValueError
        self.cookie = BaseCookie(_cookie)
    def reply(self):
        self._log(DIVIDE_LINE)
        self._log('replying..')
        if not self.cookie:
            self.login()
        ##
        print 'enter topic id'
        topic_id = raw_input()
        print 'enter reply content'
        reply_content = raw_input()
        ##
        conn = self._get_conn()
        reply_form = {
            'content': reply_content
        }
        headers = REPLY_HEADERS
        headers['Cookie'] = 'auth=%s' % self.cookie['auth'].value # only need this
        headers['Referer'] = 'http://%s/t/%s' % (self.DOMAIN, topic_id)
        conn.request('POST',
            '/t/%s' % topic_id,
            urllib.urlencode(reply_form),
            headers)
        resp = conn.getresponse()
        self._log('response headers:%s' % resp.getheaders())
        body = self._read(resp)
        self._log('response body:%s' % body)
        print 'end'
        

if '__main__' == __name__:
    v2ex = V2EX(USER)
    v2ex.reply()