+class credentials(object):
+ def __init__(self, username, password):
+ self.username = username
+ self.password = password
+
+ @classmethod
+ def fromfile(cls, path):
+ username, password = None, None
+ with open(path) as fp:
+ for words in profile.splitlines(fp):
+ if words[0] == "username":
+ username = words[1]
+ elif words[0] == "password":
+ password = words[1]
+ elif words[0] == "pass64":
+ import binascii
+ password = binascii.a2b_base64(words[1]).decode("utf8")
+ if None in (username, password):
+ raise ValueError("Incomplete profile: " + path)
+ return cls(username, password)
+
+ @classmethod
+ def default(cls):
+ path = os.path.join(profile.confdir, "batoto")
+ if os.path.exists(path):
+ return cls.fromfile(path)
+ return None
+
+class session(object):
+ def __init__(self, base, credentials):
+ self.base = base
+ self.creds = credentials
+ self.jar = http.cookiejar.CookieJar()
+ self.web = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(self.jar))
+ self.lastlogin = 0
+
+ rlre = re.compile(r"Welcome, (.*) ")
+ def dologin(self, pre=None):
+ now = time.time()
+ if now - self.lastlogin < 60:
+ raise Exception("Too soon since last login attempt")
+ if pre is None:
+ with self.web.open(self.base) as hs:
+ page = soupify(hs.read())
+ else:
+ page = pre
+
+ cur = page.find("a", id="user_link")
+ if cur:
+ m = self.rlre.search(cur.text)
+ if not m or m.group(1) != self.creds.username:
+ outurl = None
+ nav = page.find("div", id="user_navigation")
+ if nav:
+ for li in nav.findAll("li"):
+ if li.a and "Sign Out" in li.a.string:
+ outurl = li.a["href"]
+ if not outurl:
+ raise pageerror("Could not find logout URL", page)
+ with self.wep.open(outurl) as hs:
+ hs.read()
+ with self.web.open(self.base) as hs:
+ page = soupify(hs.read())
+ else:
+ return
+ else:
+ pass
+
+ form = page.find("form", id="login")
+ if not form and pre:
+ return self.dologin()
+ values = {}
+ for el in form.findAll("input", type="hidden"):
+ values[el["name"]] = el["value"]
+ values["ips_username"] = self.creds.username
+ values["ips_password"] = self.creds.password
+ values["rememberMe"] = "1"
+ values["anonymous"] = "1"
+ req = urllib.request.Request(form["action"], urllib.parse.urlencode(values).encode("ascii"))
+ req.add_header("User-Agent", self.useragent)
+ with self.web.open(req) as hs:
+ page = soupify(hs.read())
+ for resp in page.findAll("p", attrs={"class": "message"}):
+ if resp.strong and "You are now signed in" in resp.strong.string:
+ break
+ else:
+ raise pageerror("Could not log in", page)
+ self.lastlogin = now
+
+ def open(self, url):
+ return self.web.open(url)
+
+ useragent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.160 Safari/537.22"
+ def fetch(self, url, headers=None):
+ req = urllib.request.Request(url)
+ req.add_header("User-Agent", self.useragent)
+ if headers is not None:
+ for k, v in headers.items():
+ req.add_header(k, v)
+ with self.open(req) as hs:
+ return hs.read()
+
+ def lfetch(self, url, ck):
+ page = soupify(self.fetch(url))
+ if not ck(page):
+ self.dologin(pre=page)
+ page = soupify(self.fetch(url))
+ if not ck(page):
+ raise pageerror("Could not verify login status despite having logged in", page)
+ return page
+