/
utility.py
131 lines (108 loc) · 3.54 KB
/
utility.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# -*- coding: utf-8 -*-
#Canto - ncurses RSS reader
# Copyright (C) 2008 Jack Miller <jack@codezen.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
import tempfile
import urllib2
import signal
import curses
import locale
import sys
import re
import os
# The Cycle class has proved to be useful. It's used
# to encapsulate every cycle in canto, global filters,
# tag filters, global and tag sorts, tags. It's
# essentially a list with a current pointer and
# exception proof next/prev function and the ability
# to temporarily override a particular value.
class Cycle():
def __init__(self, list, idx = 0):
self.overridden = False
self.over = None
self.list = list
if 0 <= idx < len(self.list):
self.idx = idx
else:
self.idx = 0
def next(self):
self.overridden = False
if self.idx >= len(self.list) - 1:
return 0
self.idx += 1
return 1
def prev(self):
self.overridden = False
if self.idx <= 0:
return 0
self.idx -= 1
return 1
def override(self, cur):
if not self.overridden or self.over != cur:
self.overridden = True
self.over = cur
return 1
return 0
def cur(self):
if self.overridden:
return self.over
return self.list[self.idx]
def silentfork(path, href, text, fetch):
enc = locale.getpreferredencoding()
href = href.encode(enc, "ignore")
pid = os.fork()
if not pid :
# A lot of programs don't appreciate
# having their fds closed, so instead
# we dup them to /dev/null.
fd = os.open("/dev/null", os.O_RDWR)
os.dup2(fd, sys.stderr.fileno())
if not text:
os.setpgid(os.getpid(), os.getpid())
os.dup2(fd, sys.stdout.fileno())
if fetch:
response = urllib2.urlopen(href)
data = response.read()
fd, name = tempfile.mkstemp()
os.write(fd, data)
os.close(fd)
path = path.replace("%u", name)
else:
path = path.replace("%u", href)
os.execv("/bin/sh", ["/bin/sh", "-c", path])
sys.exit(0)
if text:
signal.signal(signal.SIGALRM, signal.SIG_IGN)
signal.signal(signal.SIGWINCH, signal.SIG_IGN)
return pid
def goto(link, cfg):
title,href,handler = link
if handler in cfg.handlers:
for k in [h for h in cfg.handlers[handler].keys() if h]:
if href.endswith(k):
binary, text, fetch = cfg.handlers[handler][k]
break
else:
if None in cfg.handlers[handler]:
binary, text, fetch = cfg.handlers[handler][None]
else:
cfg.log("No default %s handler defined!" % handler)
return
# Escape all "s in the URL, to avoid malicious use
# of crafted feeds. Thanks to Andreas.
href = href.replace("\"","%22")
if text:
cfg.wait_for_pid = silentfork(binary, href, 1, fetch)
else:
silentfork(binary, href, 0, fetch)
else:
cfg.log("No handler set for %s" % handler)
def stripchars(string):
string = string.replace("\\","\\\\")
string = string.replace("%", "\\%")
return string
def strip_escape_chars(strings):
return (re.sub("\\\\(.)", "\\1", string) for string in strings)