aboutsummaryrefslogtreecommitdiffstats
path: root/lib/misc.h
blob: 55dabfc4ff3aa13e2356d6b569f6978aaf3fc70e (plain)
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
  /********************************************************************\
  * BitlBee -- An IRC to other IM-networks gateway                     *
  *                                                                    *
  * Copyright 2002-2004 Wilmer van der Gaast and others                *
  \********************************************************************/

/* Misc. functions                                                      */

/*
  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License with
  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
  Suite 330, Boston, MA  02111-1307  USA
*/

#ifndef _MISC_H
#define _MISC_H

#include <gmodule.h>
#include <time.h>

struct ns_srv_reply
{
	int prio;
	int weight;
	int port;
	char name[];
};

G_MODULE_EXPORT void strip_linefeed( gchar *text );
G_MODULE_EXPORT char *add_cr( char *text );
G_MODULE_EXPORT char *strip_newlines(char *source);
G_MODULE_EXPORT char *normalize( const char *s );
G_MODULE_EXPORT void info_string_append( GString *str, char *newline, char *name, char *value );

G_MODULE_EXPORT time_t get_time( int year, int month, int day, int hour, int min, int sec );
double gettime( void );

G_MODULE_EXPORT void strip_html( char *msg );
G_MODULE_EXPORT char *escape_html( const char *html );
G_MODULE_EXPORT void http_decode( char *s );
G_MODULE_EXPORT void http_encode( char *s );

G_MODULE_EXPORT char *ipv6_wrap( char *src );
G_MODULE_EXPORT char *ipv6_unwrap( char *src );

G_MODULE_EXPORT signed int do_iconv( char *from_cs, char *to_cs, char *src, char *dst, size_t size, size_t maxbuf );

G_MODULE_EXPORT void random_bytes( unsigned char *buf, int count );

G_MODULE_EXPORT int is_bool( char *value );
G_MODULE_EXPORT int bool2int( char *value );

G_MODULE_EXPORT struct ns_srv_reply *srv_lookup( char *service, char *protocol, char *domain );

#endif
.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
= Introduction

Generally, the goal of the project is to enable the conversion of
msg and pst files into standards based formats, without reliance on
outlook, or any platform dependencies. In fact its currently <em>pure
ruby</em>, so it should be easy to get running.

It is targeted at people who want to migrate their PIM data from outlook,
converting msg and pst files into rfc2822 emails, vCard contacts,
iCalendar appointments etc. However, it also aims to be a fairly complete
mapi message store manipulation library, providing a sane model for
(currently read-only) access to msg and pst files (message stores).

I am happy to accept patches, give commit bits etc.

Please let me know how it works for you, any feedback would be welcomed.

= Features

Broad features of the project:

* Can be used as a general mapi library, where conversion to and working
  on a standard format doesn't make sense.

* Supports conversion of messages to standard formats, like rfc2822
  emails, vCard, etc.

* Well commented, and easily extended.

* Basic RTF converter, for providing a readable body when only RTF
  exists (needs work)

* RTF decompression support included, as well as HTML extraction from
  RTF where appropriate (both in pure ruby, see <tt>lib/mapi/rtf.rb</tt>)

* Support for mapping property codes to symbolic names, with many
  included.

Features of the msg format message store:

* Most key .msg structures are understood, and the only the parsing
  code should require minor tweaks. Most of remaining work is in achieving
  high-fidelity conversion to standards formats (see [TODO]).

* Supports both types of property storage (large ones in +substg+
  files, and small ones in the +properties+ file.

* Complete support for named properties in different GUID namespaces.

* Initial support for handling embedded ole files, converting nested
  .msg files to message/rfc822 attachments, and serializing others
  as ole file attachments (allows you to view embedded excel for example).

Features of the pst format message store:

* Handles both Outlook 1997 & 2003 format pst files, both with no-
  and "compressible-" encryption.

* Understanding of the file format is still very superficial.

= Usage

At the command line, it is simple to convert individual msg or pst
files to .eml, or to convert a batch to an mbox format file. See mapitool
help for details:

  mapitool -si some_email.msg > some_email.eml
  mapitool -s *.msg > mbox

There is also a fairly complete and easy to use high level library
access:

  require 'mapi/msg'
  
  msg = Mapi::Msg.open filename
  
  # access to the 3 main data stores, if you want to poke with the msg
  # internals
  msg.recipients
  # => [#<Recipient:'\'Marley, Bob\' <bob.marley@gmail.com>'>]
  msg.attachments
  # => [#<Attachment filename='blah1.tif'>, #<Attachment filename='blah2.tif'>]
  msg.properties
  # => #<Properties ... normalized_subject='Testing' ... 
  # creation_time=#<DateTime: 2454042.45074714,0,2299161> ...>

To completely abstract away all msg peculiarities, convert the msg
to a mime object. The message as a whole, and some of its main parts
support conversion to mime objects.

  msg.attachments.first.to_mime
  # => #<Mime content_type='application/octet-stream'>
  mime = msg.to_mime
  puts mime.to_tree
  # =>
  - #<Mime content_type='multipart/mixed'>
    |- #<Mime content_type='multipart/alternative'>
    |  |- #<Mime content_type='text/plain'>
    |  \- #<Mime content_type='text/html'>
    |- #<Mime content_type='application/octet-stream'>
    \- #<Mime content_type='application/octet-stream'>
  
  # convert mime object to serialised form,
  # inclusive of attachments etc. (not ideal in memory, but its wip).
  puts mime.to_s

= Thanks

* The initial implementation of parsing msg files was based primarily
  on msgconvert.pl[http://www.matijs.net/software/msgconv/].

* The basis for the outlook 97 pst file was the source to +libpst+.

* The code for rtf decompression was implemented by inspecting the
  algorithm used in the +JTNEF+ project.

= Other

For more information, see

* TODO

* MsgDetails[http://code.google.com/p/ruby-msg/wiki/MsgDetails]

* PstDetails[http://code.google.com/p/ruby-msg/wiki/PstDetails]

* OleDetails[http://code.google.com/p/ruby-ole/wiki/OleDetails]