5010d1d417ae54833860c8737d6b4a70f810f83c
[frenchie/icalparse.git] / icalparse.py
1 #!/usr/bin/python
2 #
3 # Copyright (c) 2010 James French <[email protected]>
4 #
5 # Permission is hereby granted, free of charge, to any person obtaining a copy
6 # of this software and associated documentation files (the "Software"), to deal
7 # in the Software without restriction, including without limitation the rights
8 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 # copies of the Software, and to permit persons to whom the Software is
10 # furnished to do so, subject to the following conditions:
11 #
12 # The above copyright notice and this permission notice shall be included in
13 # all copies or substantial portions of the Software.
14 #
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 # THE SOFTWARE.
22
23 import sys
24 import re
25 import urlparse
26 import os
27
28 class InvalidICS(Exception): pass
29 class notJoined(Exception): pass
30
31 icalEntry = re.compile('^[A-Z\-]+:.*')
32
33 def lineJoiner(oldcal):
34         '''Takes a string containing a calendar and returns an array of its lines'''
35
36         if list(oldcal) == oldcal:
37                 oldcal = '\r\n'.join(oldcal)
38
39         oldcal.replace('\r\n ', '')
40         return oldcal.split('\r\n')
41
42
43 def lineFolder(oldcal, length=75):
44         '''Folds content lines to a specified length, returns a list'''
45
46         if length > 75:
47                 sys.stderr.write('WARN: lines > 75 octets are not RFC compliant\n')
48
49         cal = []
50         sl = length - 1
51
52         for line in oldcal:
53                 # Line fits inside length, do nothing
54                 if len(line.rstrip()) <= length:
55                         cal.append(line)
56                 else:
57                         brokenline = [line[0:length] + '\r\n']
58                         ll = length
59                         while ll < len(line.rstrip('\r\n')) + 1:
60                                 brokenline.append(' ' + line[ll:sl+ll].rstrip('\r\n') + '\r\n')
61                                 ll += sl
62                         cal += brokenline
63
64         return cal
65
66 def getContent(url='',stdin=False):
67         pass
68
69
70 if __name__ == '__main__':
71         from optparse import OptionParser
72         # If the user passed us a 'stdin' argument, we'll go with that,
73         # otherwise we'll try for a url opener
74
75         parser = OptionParser('usage: %prog [options] url')
76         parser.add_option('-s', '--stdin', action='store_true', dest='stdin',
77                 default=False, help='Take a calendar from standard input')
78         parser.add_option('-o', '--output', dest='outfile', default='',
79                 help='Specify output file (defaults to standard output)')
80
81         (options, args) = parser.parse_args()
82
83         if not args and not options.stdin:
84                 parser.print_usage()
85                 sys.exit(0)
86         elif not options.stdin:
87                 url = args[0]
88         else:
89                 url = ''
90
91         # Work out what url parsers we're going to need based on what the user
92         # gave us on the command line - we do like files after all
93         parsedURL = urlparse.urlparse(url)
94         http = 'http' in parsedURL[0]
95
96         if not parsedURL[0]: u = False
97         else: u = True
98
99         if not options.stdin and http:
100                 try:
101                         import httplib2
102                 except ImportError:
103                         import urllib2
104
105         # Try and play nice with HTTP servers unless something goes wrong. We don't
106         # really care about this cache (A lot of ics files seem to be generated with
107         # php which hates caching with a passion).
108         h = False
109         if 'httplib2' in sys.modules:
110                 try: h = httplib2.Http('.httplib2-cache')
111                 except OSError: h = httplib2.Http()
112
113         # Load urllib2 if this is not a stdin
114         if not options.stdin and (not http or not 'httplib2' in sys.modules):
115                 import urllib2
116
117         try:
118                 content = u and (h and h.request(url)[1] or urllib2.urlopen(url).read())
119         except (ValueError, urllib2.URLError), e:
120                 sys.stderr.write('%s\n'%e)
121                 sys.exit(1)
122
123         if not u and not options.stdin:
124                 try: content = open(os.path.abspath(url),'r').read()
125                 except (IOError, OSError), e:
126                         sys.stderr.write('%s\n'%e)
127                         sys.exit(1)
128
129         if options.stdin:
130                 content = sys.stdin.read()

UCC git Repository :: git.ucc.asn.au