Skip to content

Instantly share code, notes, and snippets.

@mattn
Created August 4, 2009 10:30
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mattn/161146 to your computer and use it in GitHub Desktop.
Save mattn/161146 to your computer and use it in GitHub Desktop.
"=============================================================================
" Title: VIMua (VIm Mail User Agent)
" File: vimua.vim
" Author: Yasuhiro Matsumoto <mattn_jp@hotmail.com>
" Version: 0.7
"=============================================================================
"-----------------------------------------------------------------------------
" Setting Environments
"-----------------------------------------------------------------------------
if exists("vimua_host")
let s:host = vimua_host
else
let s:host = ""
endif
if exists("vimua_user")
let s:user = vimua_user
else
let s:user = ""
endif
if exists("vimua_pass")
let s:pass = vimua_pass
else
let s:pass = ""
endif
if exists("vimua_name")
let s:name = vimua_name
else
let s:name = ""
endif
if exists("vimua_addr")
let s:addr = vimua_addr
else
let s:addr = ""
endif
if exists("vimua_menc")
let s:menc = vimua_menc
else
let s:menc = ""
endif
let s:tiltebar = ""
if has("win32")
let s:libn = "vimua.dll"
else
let s:libn = "vimua.so"
endif
let s:slst = 0
let s:nlst = 5
"-----------------------------------------------------------------------------
" FocusWin : set focus to window
"-----------------------------------------------------------------------------
function! s:FocusWin(name)
let num = bufwinnr(a:name)
if num >= 0 && num != winnr()
execute 'normal! ' . num . "\<C-W>\<C-W>"
endif
return num
endfunction
"-----------------------------------------------------------------------------
" CallBASE64E : base64 encode
"-----------------------------------------------------------------------------
function! s:CallBASE64E(parm)
return libcall(s:libn,"base64_encode",a:parm)
endfunction
"-----------------------------------------------------------------------------
" CallBASE64D : base64 decode
"-----------------------------------------------------------------------------
function! s:CallBASE64D(parm)
return libcall(s:libn,"base64_decode",a:parm)
endfunction
"-----------------------------------------------------------------------------
" CallQUOTEDD : quoted decode
"-----------------------------------------------------------------------------
function! s:CallQUOTEDD(parm)
return libcall(s:libn,"quoted_decode",a:parm)
endfunction
"-----------------------------------------------------------------------------
" MimeDec : mime decode
"-----------------------------------------------------------------------------
function! s:MimeDec(code)
let rcode = a:code
let mbase = '.*=?\([^=]*\)?\([A-Za-z]\)?[A-Za-z0-9+/=]\+?=.*'
while 1
if matchstr(rcode,mbase) == ""
break
endif
let schar = substitute(rcode, mbase, '\1', '')
let sencf = substitute(rcode, mbase, '\2', '')
if sencf == 'B'
let spatt = s:CallBASE64D(rcode)
elseif sencf == 'q'
let spatt = s:CallQUOTEDD(rcode)
endif
let rcode = iconv(spatt, schar, &encoding)
endwhile
return rcode
endfunction
"-----------------------------------------------------------------------------
" CallGETBODY : get body from mail
"-----------------------------------------------------------------------------
function! s:CallGETBODY(parm)
return libcall(s:libn,"get_body",a:parm)
endfunction
"-----------------------------------------------------------------------------
" CallGETHEAD : get header from mail
"-----------------------------------------------------------------------------
function! s:CallGETHEAD(head,parm)
return libcall(s:libn,"get_header",a:head.",".a:parm)
endfunction
"-----------------------------------------------------------------------------
" CallSMTPCMD : call smtp protocol command
"-----------------------------------------------------------------------------
function! s:CallSMTPCMD(mailf,mailt,mails,mailb)
return libcall(s:libn,"smtp_cmd",s:host.",".a:mailf.",".a:mailt.",".a:mails.",".a:mailb)
endfunction
"-----------------------------------------------------------------------------
" CallPOP3CMD : call pop3 protocol command
"-----------------------------------------------------------------------------
function! s:CallPOP3CMD(comd)
return libcall(s:libn,"pop3_cmd",s:host.",".s:user.",".s:pass.",".a:comd)
endfunction
"-----------------------------------------------------------------------------
" VIMua : main function
"-----------------------------------------------------------------------------
function! s:VIMua()
if &title
let s:titlebar = &titlestring
let &titlestring = "VIMua"
endif
silent edit! MailList
setlocal noswapfile
setlocal buftype=nowrite
setlocal bufhidden=delete
setlocal nonumber
setlocal nowrap
setlocal norightleft
setlocal foldcolumn=0
setlocal nomodifiable
syntax match Title display "^\(\d\+\s.*\)$"
nnoremap <silent> <buffer> <2-LeftMouse> :call <SID>MailShow()<CR>
nnoremap <silent> <buffer> <cr> :call <SID>MailShow()<CR>
nnoremap <silent> <buffer> q :call <SID>MailQuit()<CR>
nnoremap <silent> <buffer> <c-left> :call <SID>MailList("n")<CR>
nnoremap <silent> <buffer> <c-right> :call <SID>MailList("p")<CR>
nnoremap <silent> <buffer> <c-up> :call <SID>MailList("t")<CR>
nnoremap <silent> <buffer> <c-down> :call <SID>MailList("b")<CR>
nnoremap <silent> <buffer> <c-l> :call <SID>MailList("")<CR>
nnoremap <silent> <buffer> <c-r> :call <SID>MailComp("r")<CR>
nnoremap <silent> <buffer> <c-c> :call <SID>MailComp("")<CR>
nnoremap <silent> <buffer> <del> :call <SID>MailDele()<CR>
call s:CreateMailBody()
redraw!
if s:LoadUser() != 0
call s:MailList("")
else
call s:MailQuit()
endif
endfunction
"-----------------------------------------------------------------------------
" MailDele : delete mail of current line
"-----------------------------------------------------------------------------
function! s:MailDele()
let mlist = '^\(\d\+\)\s.*$'
let slist = getline(".")
if slist =~ mlist
let slist = substitute(slist, mlist, '\1', '')
else
if line(".") < 1
return
endif
let slist = getline(line(".")-1)
if slist !~ mlist
return
endif
let slist = substitute(slist, mlist, '\1', '')
endif
if confirm("Delete mail No.".slist."?", "&Yes\n&No",1) != 1
return
endif
let sdown = s:CallPOP3CMD("dele ".slist)
if sdown == ""
call s:MailList("")
return
endif
echo sdown
endfunction
"-----------------------------------------------------------------------------
" MailSend : send mail of current line
"-----------------------------------------------------------------------------
function! s:MailSend()
let mailf = getline(1)
let mailt = getline(2)
let mails = getline(3)
let sepa = getline(4)
if mailf !~ '^From:\s*' || mailt !~ '^To:\s*' || mails !~ '^Subject:\s*' || sepa != '------'
echoerr "hogehoge"
return
endif
let mailf = substitute(mailf, '^From:\s*\(.*\)\s*', '\1', '')
let mailt = substitute(mailt, '^To:\s*\(.*\)\s*', '\1', '')
let mails = substitute(mails, '^Subject:\s*\(.*\)\s*', '\1', '')
let curline = 5
let lastline = line('$')
let mailb = ""
while curline <= lastline
let mailb = mailb . getline(curline) . "\r\n"
let curline = curline + 1
endwhile
if s:menc != ""
let stemp = iconv(s:name,&encoding,s:menc)
if stemp != ""
let mailf = "=?".s:menc."?B?".s:CallBASE64E(stemp)."?= <".mailf.">"
endif
let stemp = iconv(mails,&encoding,s:menc)
if stemp != ""
let mails = "=?".s:menc."?B?".s:CallBASE64E(stemp)."?="
endif
let stemp = iconv(mailb,&encoding,s:menc)
if stemp != ""
let mailb = stemp
endif
endif
let sdown = s:CallSMTPCMD(mailf,mailt,mails,mailb)
if sdown == ""
call CreateMailBody()
return
endif
echo sdown
endfunction
function! s:CreateMailBody()
if s:FocusWin("MailBody") == -1
exec "rightbelow ".(&lines/6*3)."split MailBody"
setlocal noswapfile
setlocal buftype=nowrite
setlocal bufhidden=delete
setlocal nonumber
setlocal nowrap
setlocal norightleft
setlocal foldcolumn=0
setlocal nomodifiable
setlocal ft=mail
nnoremap <silent> <buffer> q :call <SID>MailQuit()<CR>
endif
endfunction
"-----------------------------------------------------------------------------
" MailComp : create mail compose window
"-----------------------------------------------------------------------------
function! s:MailComp(flag)
if a:flag == 'r'
let mlist = '^\(\d\+\)\s.*$'
let slist = getline(".")
if slist =~ mlist
let slist = substitute(slist, mlist, '\1', '')
else
if line(".") < 1
return
endif
let slist = getline(line(".")-1)
if slist !~ mlist
return
endif
let slist = substitute(slist, mlist, '\1', '')
endif
let sdown = s:CallPOP3CMD("+retr ".slist)
if sdown == ""
break
endif
let sbody = s:CallGETBODY(sdown)
let sfrom = s:MimeDec(s:CallGETHEAD("from",sdown))
let ssubj = s:MimeDec(s:CallGETHEAD("subject",sdown))
let shead = s:MimeDec(s:CallGETHEAD("content-type",sdown))
if shead == ""
let mbase = '.*=?\(.*\)?[A-Za-z0-9+/=]\+?='
let shead = sfrom
if matchstr(shead,mbase) == ""
let shead = ssubj
endif
if matchstr(shead,mbase) != ""
let shead = substitute(shead, mbase, '\1', '')
let shead = substitute(shead, '\([^?]\+\)?.*', '\1', '')
else
let shead = s:menc
endif
else
let mbase = '.*[;]*\s*[e]*charset=["]*\([a-zA-Z0-9_\-]\+\).*'
let shead = substitute(shead, mbase, '\1', '')
endif
if shead != ""
let stemp = iconv(sbody, shead, &encoding)
let g:temp = sbody
if stemp != ""
let sbody = stemp
endif
endif
let stemp = substitute(sbody, '\r', '', 'g')
if stemp != ""
let sbody = stemp
endif
else
let sbody = ""
let sfrom = ""
let ssubj = ""
endif
if s:FocusWin("MailBody") != -1
silent edit! MailComp
else
exec "rightbelow ".(&lines/3*2+1)."split MailComp"
endif
setlocal noswapfile
setlocal buftype=nowrite
setlocal bufhidden=delete
setlocal nonumber
setlocal nowrap
setlocal norightleft
setlocal foldcolumn=0
setlocal ft=mail
nnoremap <silent> <buffer> <c-c> :call <SID>MailSend()<CR>
nnoremap <silent> <buffer> q :call <SID>MailQuit()<CR>
let oldf = @f
let @f = ""
if s:addr != ""
let @f = @f."From: ".s:addr."\n"
else
let @f = @f."From: ".s:user."@".s:host."\n"
endif
if sfrom != ""
let @f = @f."To: ".sfrom."\n"
else
let @f = @f."To: \n"
endif
if ssubj != ""
let @f = @f."Subject: Re:".ssubj."\n"
else
let @f = @f."Subject: \n"
endif
let @f = @f."------\n"
if sbody != ""
let @f = @f.">".substitute(sbody,"\n", "\n>", 'g')
endif
silent put! f
let @f = oldf
normal G
startinsert
endfunction
"-----------------------------------------------------------------------------
" GetCount : get count of mails from server
"-----------------------------------------------------------------------------
function! s:GetCount()
let mlist = '.*\s\+\(\d\+\)\s\+\d\+.*'
let rlist = s:CallPOP3CMD("stat")
if rlist == ""
return 0
endif
if rlist =~ mlist
return substitute(rlist, mlist, '\1', '')
endif
return rlist
endfunction
"-----------------------------------------------------------------------------
" LoadUser : load user profile
"-----------------------------------------------------------------------------
function! s:LoadUser()
if s:host == ""
let s:host = input("MailServer:")
if s:host == ""
return 0
endif
endif
if s:user == ""
let s:user = input("Login:")
if s:user == ""
return 0
endif
endif
if s:pass == ""
let s:pass = inputsecret("Password:")
if s:pass == ""
return 0
endif
endif
return 1
endfunction
"-----------------------------------------------------------------------------
" MailList : list mail
"-----------------------------------------------------------------------------
function! s:MailList(nstart)
if s:FocusWin("MailList") == -1
return
endif
let ncount = s:GetCount()
if ncount !~ "^[0-9]\\+$"
echo ncount
return
endif
if ncount == 0
return
endif
if a:nstart == ""
let s:slst = ncount - s:nlst
elseif a:nstart == "n"
let s:slst = s:slst + s:nlst
elseif a:nstart == "p"
let s:slst = s:slst - s:nlst
elseif a:nstart == "t"
let s:slst = ncount - s:nlst
elseif a:nstart == "b"
let s:slst = 1
else
let s:slst = a:nstart
endif
if s:slst > ncount
let s:slst = ncount - s:nlst
endif
if s:slst <= 0
let s:slst = 1
endif
let nlist = s:slst
let mlist = '\(\d\+\)\s\+\(\d\+\)'
setlocal modifiable
silent %d _
setlocal nomodifiable
while 1
let sdown = s:CallPOP3CMD("+retr ".nlist)
if sdown =~ "^-"
echo sdown
break
endif
let sfrom = s:MimeDec(s:CallGETHEAD("from",sdown))
if nlist == 1381
let g:hoge1 = s:CallGETHEAD("from",sdown)
endif
let ssubj = s:MimeDec(s:CallGETHEAD("subject",sdown))
if nlist == 723
let g:hoge = s:CallGETHEAD("subject",sdown)
endif
let oldf = @f
let @f = nlist . " " . sfrom . "\n " . ssubj
setlocal modifiable
silent put! f
setlocal nomodifiable
let @f = oldf
redraw!
let nlist = nlist + 1
if nlist >= ncount || (nlist - s:slst) >= s:nlst
break
endif
endwhile
endfunction
"-----------------------------------------------------------------------------
" MailShow : show mail from given line
"-----------------------------------------------------------------------------
function! s:MailShow()
let mlist = '^\(\d\+\)\s.*$'
let slist = getline(".")
if slist =~ mlist
let slist = substitute(slist, mlist, '\1', '')
else
if line(".") < 1
return
endif
let slist = getline(line(".")-1)
if slist !~ mlist
return
endif
let slist = substitute(slist, mlist, '\1', '')
endif
let sdown = s:CallPOP3CMD("+retr ".slist)
if sdown == ""
break
endif
let sbody = s:CallGETBODY(sdown)
let sfrom = s:MimeDec(s:CallGETHEAD("from",sdown))
let ssubj = s:MimeDec(s:CallGETHEAD("subject",sdown))
let sdate = s:MimeDec(s:CallGETHEAD("date",sdown))
let shead = s:MimeDec(s:CallGETHEAD("content-type",sdown))
if shead == ""
let mbase = '.*=?\(.*\)?[A-Za-z0-9+/=]\+?='
let shead = sfrom
if matchstr(shead,mbase) == ""
let shead = ssubj
endif
if matchstr(shead,mbase) != ""
let shead = substitute(shead, mbase, '\1', '')
let shead = substitute(shead, '\([^?]\+\)?.*', '\1', '')
else
let shead = s:menc
endif
else
let mbase = '.*[;]*\s*[e]*charset=["]*\([a-zA-Z0-9_\-]\+\).*'
let shead = substitute(shead, mbase, '\1', '')
endif
if shead != ""
let stemp = iconv(sbody, shead, &encoding)
let g:temp = sbody
if stemp != ""
let sbody = stemp
endif
endif
let stemp = substitute(sbody, '\r', '', 'g')
if stemp != ""
let sbody = stemp
endif
call s:CreateMailBody()
let oldf = @f
let @f = ""
let @f = @f."From: ".sfrom."\n"
let @f = @f."Date: ".sdate."\n"
let @f = @f."Subject: ".ssubj."\n"
let @f = @f."------\n"
let @f = @f.sbody
setlocal modifiable
silent %d _
silent put! f
setlocal nomodifiable
let @f = oldf
redraw!
endfunction
"-----------------------------------------------------------------------------
" MailQuit : quit VIMua window
"-----------------------------------------------------------------------------
function! s:MailQuit()
silent! bw! MailList
silent! bw! MailBody
silent! bw! MailComp
new!
only!
redraw!
if &title
let &titlestring = s:titlebar
endif
endfunction
"-----------------------------------------------------------------------------
" VIMua : VIm Mail User Agent
"-----------------------------------------------------------------------------
command! VIMua call <SID>VIMua()
/*
* cl /DWIN32 /LD vimua.c ws2_32.lib
* gcc -shared -o vimua.so vimua.c
*/
#include <stdio.h>
#include <string.h>
#ifdef WIN32
#include <string.h>
#include <winsock.h>
#define WIN32EXPORT _declspec(dllexport)
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define WIN32EXPORT
#ifndef SOCKET
#define SOCKET int
#endif
#ifndef SOCKADDR
#define SOCKADDR struct sockaddr
#endif
#ifndef SOCKADDR_IN
#define SOCKADDR_IN struct sockaddr_in
#endif
#ifndef HOSTENT
#define HOSTENT struct hostent
#endif
#ifndef IN_ADDR
#define IN_ADDR struct in_addr
#endif
#ifndef closesocket
#define closesocket(fd) close(fd)
#endif
#ifndef strnicmp
#define strnicmp(s1,s2,n) strncasecmp(s1,s2,n)
#endif
#endif
#undef fputs
#define fputs my_puts
static char *my_puts_out = NULL;
static char *my_puts_buf = NULL;
static long my_puts_len = 0;
static void my_initbuf( void );
static char* my_buffer( void );
static int my_puts( const char *str, FILE *fst );
#ifndef stristr
static char* stristr( char *str1, char *str2 );
#endif
static char* recv_line( SOCKET sock );
static char* get_section( char *libcmds, char *line_str );
char WIN32EXPORT * get_header( char* libcmds );
char WIN32EXPORT * get_body( char* libcmds );
char WIN32EXPORT * pop3_cmd( char* libcmds );
char WIN32EXPORT * smtp_cmd( char* libcmds );
char WIN32EXPORT * get_file( char* libcmds );
char WIN32EXPORT * base64_decode( char* libcmds );
char WIN32EXPORT * base64_encode( char* libcmds );
char WIN32EXPORT * quoted_decode( char* libcmds );
#define SEND_LINE \
{ \
ret = send( sock, cmds, strlen(cmds), 0 ); \
if (ret < 0) \
{ \
fputs( "can't send data\r\n", stderr ); \
goto ErrHandler; \
} \
}
#define RECV_LINE \
{ \
line = recv_line( sock ); \
if (line == NULL) \
{ \
fputs( "can't recv data\r\n", stderr ); \
goto ErrHandler; \
} \
}
#define TOKE_POP3 \
if (line[0] != '+') \
{ \
fputs( line, stderr ); \
free( line ); \
strcpy( cmds, "QUIT\r\n" ); \
ret = send( sock, cmds, strlen(cmds), 0 ); \
free( recv_line( sock ) ); \
goto ErrHandler; \
}
#define TOKE_SMTP \
if (line[0] != '2') \
{ \
fputs( line, stderr ); \
free( line ); \
strcpy( cmds, "QUIT\r\n" ); \
ret = send( sock, cmds, strlen(cmds), 0 ); \
free( recv_line( sock ) ); \
goto ErrHandler; \
}
/***************************
* my_buffer
***************************/
static char* my_buffer( void )
{
char *ret;
if (my_puts_out)
{
FILE *pfile = fopen(my_puts_out, "w");
if (pfile)
{
fputs(my_puts_buf, pfile);
fclose(pfile);
}
ret = my_puts_out;
}
else
ret = my_puts_buf;
return ret;
}
/***************************
* my_puts
***************************/
static int my_puts( const char *str, FILE *fst )
{
if(my_puts_buf == NULL)
my_puts_buf = (char*)malloc( strlen(str)+2 );
else
my_puts_buf = (char*)realloc( my_puts_buf, my_puts_len+strlen(str)+1 );
if(my_puts_buf == NULL)
return 0;
strcpy( my_puts_buf+my_puts_len, str );
my_puts_len += strlen(str);
return strlen(str);
}
/***************************
* my_puts
***************************/
#ifndef stristr
static char* stristr( char *str1, char *str2 )
{
char *src;
long length;
src = str1;
length = strlen(str2);
while( *src )
{
if(!strnicmp( src, str2, length ))
return src;
src++;
}
return NULL;
}
#endif
/***************************
* recv_line
***************************/
static char* recv_line( SOCKET sock )
{
long leng = 0;
long ret = 0;
char recv_c;
char *pbuf = NULL;
for( ; ; )
{
ret = recv( sock, &recv_c, 1, 0 );
if(ret <= 0) break;
if((leng % 200) == 0)
{
if(pbuf == NULL)
pbuf = (char*)malloc( leng+200 );
else
pbuf = (char*)realloc( pbuf, leng+200 );
if(pbuf == NULL)
return NULL;
}
*(pbuf+leng) = recv_c;
leng++;
if(leng >= 2 && !strncmp( pbuf+leng-2, "\r\n", 2 ))
break;
}
if(pbuf)
*(pbuf+leng) = 0x00;
return pbuf;
}
/***************************
* get_section
***************************/
static char* get_section( char *libcmds, char *line_str )
{
char* line_next;
char* line_name;
char* line_end;
line_name = (char*)malloc(strlen(line_str)+4);
strcpy( line_name, "\r\n" );
strcat( line_name, line_str );
strcat( line_name, ":" );
line_next = stristr( libcmds, line_name );
line_end = strstr( libcmds, "\r\n\r\n" );
if(line_next && (!line_end || line_next < line_end))
{
libcmds = line_next + strlen(line_name);
for( ; ; )
{
char *pout;
while(*libcmds == '\t') libcmds++;
line_next = strstr( libcmds, "\r\n" ) + 2;
pout = malloc(line_next-libcmds-1);
memset(pout, 0x00, line_next-libcmds-1);
strncpy( pout, libcmds, line_next-libcmds-2 );
fputs( pout, stdout );
free( pout );
libcmds = line_next;
if(*libcmds != '\t' && *libcmds != ' ')
break;
}
libcmds = strstr( libcmds, "\r\n" );
}
free( line_name );
return my_buffer();
}
/***************************
* base64_encode
***************************/
char WIN32EXPORT * base64_encode( char *src )
{
static char* Base64EncMap = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
long sidx, didx;
long ssize;
long dsize;
char* dest;
if(src == NULL) return NULL;
ssize = strlen(src);
dsize = ((ssize+2)/3)*4;
dest = (char*)malloc(dsize+1);
memset( dest, 0x00, dsize+1 );
/* 3-byte to 4-byte conversion + 0-63 to ascii printable conversion */
for (sidx=0, didx=0; sidx < ssize-2; sidx += 3)
{
dest[didx++] = Base64EncMap[(src[sidx] >> 2) & 077];
dest[didx++] = Base64EncMap[(src[sidx+1] >> 4) & 017 |
(src[sidx] << 4) & 077];
dest[didx++] = Base64EncMap[(src[sidx+2] >> 6) & 003 |
(src[sidx+1] << 2) & 077];
dest[didx++] = Base64EncMap[src[sidx+2] & 077];
}
if (sidx < ssize)
{
dest[didx++] = Base64EncMap[(src[sidx] >> 2) & 077];
if (sidx < ssize-1)
{
dest[didx++] = Base64EncMap[(src[sidx+1] >> 4) & 017 |
(src[sidx] << 4) & 077];
dest[didx++] = Base64EncMap[(src[sidx+1] << 2) & 077];
}
else
dest[didx++] = Base64EncMap[(src[sidx] << 4) & 077];
}
/* add padding */
for ( ; didx < dsize; didx++)
dest[didx] = '=';
fputs( dest, stdout );
free( dest );
return my_buffer();
}
/***************************
* quoted_decode
***************************/
char WIN32EXPORT * quoted_decode( char* src )
{
int mode = 0;
if(src == NULL) return NULL;
while( *src )
{
if(*src != '=' && mode)
{
char c[2];
c[0] = *src;
c[1] = 0x00;
fputs( c, stdout );
src++;
}
else
{
char ch = 0;
char c[2];
char buf[7];
char *dest;
if (*(src+1) == '?')
{
if (*(src+2) == '=')
src += 3;
else
{
dest = stristr(src+2,"?");
if(dest == NULL)
{
char c[3];
c[0] = *src++;
c[1] = *src++;
c[2] = 0x00;
fputs( c, stdout );
continue;
}
src = dest + 3;
}
}
else
src++;
while(*src)
{
if (*src == '=')
{
ch = 0;
while(*src++)
if (isdigit(*src))
ch = ch * 10 + (*src - '0');
else
break;
sprintf(buf, "%02d",ch);
sscanf(buf, "%02x", &ch);
}
else
ch = *src++;
c[0] = ch;
c[1] = 0x00;
fputs( c, stdout );
if (*src == '?' && *(src+1) == '=')
{
src += 2;
break;
}
}
}
}
return my_buffer();
}
/***************************
* base64_decode
***************************/
char WIN32EXPORT * base64_decode( char* src )
{
if(src == NULL) return NULL;
while( *src )
{
if(*src != '=')
{
char c[2];
c[0] = *src;
c[1] = 0x00;
fputs( c, stdout );
src++;
}
else
{
static char index64[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 62, 0, 0, 0, 63, 52, 53,
54, 55, 56, 57, 58, 59, 60, 61, 0, 0,
0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0
};
long tail;
char *dest, *pdest;
long sidx, dsize;
long size;
if (*(src+1) != '?')
{
char c[2];
c[0] = *src;
c[1] = 0x00;
fputs( c, stdout );
src++;
continue;
}
if (*(src+2) == '=')
src += 3;
else
{
dest = stristr(src+2,"?");
if(dest == NULL)
{
char c[3];
c[0] = *src++;
c[1] = *src++;
c[2] = 0x00;
fputs( c, stdout );
continue;
}
src = dest + 3;
}
size = strlen( src );
if (size == 0)
break;
sidx = tail = size;
while(--sidx > 0)
if (src[sidx] == '=')
tail = sidx;
if (tail == size)
continue;
pdest = dest = (char*)malloc(tail+1);
memset(dest, 0, tail+1);
dsize = 0;
for(sidx = 0; sidx < tail; sidx += 4)
{
char c1, c2, c3;
int padcount = 0;
c1 = (char)( index64[src[sidx + 0]] << 2 & 0xfc | index64[src[sidx + 1]] >> 4);
c2 = (char)((index64[src[sidx + 1]] & 0xf) << 4 | index64[src[sidx + 2]] >> 2);
c3 = (char)((index64[src[sidx + 2]] & 0x3) << 6 | index64[src[sidx + 3]]);
if(src[sidx + 2] == '=')
padcount++;
if(src[sidx + 3] == '=')
padcount++;
if(padcount == 0)
{
*(pdest++) = c1;
*(pdest++) = c2;
*(pdest++) = c3;
dsize += 3;
}
else
if(padcount == 1)
{
*(pdest++) = c1;
*(pdest++) = c2;
dsize += 2;
}
else
{
*(pdest++) = c1;
dsize += 1;
}
}
fputs( dest, stdout );
free( dest );
dest = strstr( src, "=?=" );
if (dest)
{
if (src == dest)
break;
if (*(dest+3) == ' ')
src = dest + 3;
else if (*(dest+3) == '=')
src = dest + 3;
else
src = dest;
}
else
{
dest = strstr( src, "?=" );
if(dest)
src = dest + 2;
else
src += (tail + 1);
}
}
}
return my_buffer();
}
/***************************
* get_header
***************************/
char WIN32EXPORT * get_header( char* libcmds )
{
char* line_next;
char line_str[1000];
line_next = strstr( libcmds, "," );
if(!line_next)
return NULL;
memset( line_str, 0x00, sizeof(line_str) );
strncpy( line_str, libcmds, line_next-libcmds );
libcmds = line_next + 1;
return get_section( libcmds, line_str );
}
/***************************
* get_body
***************************/
char WIN32EXPORT * get_body( char* libcmds )
{
char* line_next;
char* line_body;
char multi_part;
char separator[1000];
if(libcmds)
{
line_next = get_section( libcmds, "content-type" );
if(!line_next)
multi_part = 0;
else
multi_part = (stristr( line_next, "multipart/" ) != NULL);
if(!multi_part)
{
libcmds = strstr( libcmds, "\r\n\r\n" );
libcmds += 4;
line_next = strstr( libcmds, "\r\n.\r\n" );
if(line_next)
line_next += 2;
else
line_next = libcmds + strlen( libcmds )-1;
}
else
{
libcmds = strstr( libcmds, "\r\n\r\n" );
line_next = stristr( line_next, "boundary=" );
if(!line_next)
return NULL;
line_next += 9;
memset( separator, 0x00, sizeof(separator) );
if(*line_next == '\"' || *line_next == '\'')
{
strcpy( separator, "--" );
strncat( separator, line_next+1, sizeof(separator) );
separator[strchr( line_next+1, *line_next )-line_next+1] = 0x00;
}
else
{
strcpy( separator, "--" );
strncat( separator, line_next, sizeof(separator) );
separator[strlen(separator)] = 0x00;
}
libcmds = strstr( libcmds, "\r\n\r\n" );
libcmds = strstr( libcmds, separator );
libcmds = strstr( libcmds, "\r\n\r\n" );
line_next = strstr( libcmds+1, separator );
libcmds += 4;
}
line_body = (char*)malloc(line_next-libcmds+1);
memset( line_body, 0x00, line_next-libcmds+1 );
strncpy( line_body, libcmds, line_next-libcmds );
my_initbuf();
fputs( line_body, stdout );
free( line_body );
}
return my_buffer();
}
/***************************
* pop3_cmd
***************************/
char WIN32EXPORT * pop3_cmd( char* libcmds )
{
#ifdef WIN32
WSADATA wsaData;
#endif
SOCKET sock;
SOCKADDR_IN addr;
HOSTENT* host;
short port = 0;
char cmds[1024];
char* line;
long ret;
char* pargs;
char* args;
int argc;
char* argv[256];
/* parse arguments */
argc = 0;
pargs = args = strdup(libcmds);
argv[argc++] = "pop3_cmd";
argv[argc++] = args;
for ( ; *pargs != 0x00 ; )
{
if ( *pargs == ',' )
{
*pargs = 0x00;
argv[argc++] = pargs+1;
}
pargs++;
}
if (argc == 6)
{
my_puts_out = strdup(argv[5]);
argc--;
}
if (argc != 5)
{
fputs( "usage : host user pass commands...\r\n", stderr );
return 0;
}
#ifdef WIN32
if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
{
fputs( "can't initialize winsock\r\n", stderr );
goto ErrHandler;
}
#endif
line = strchr((char*)argv[1], ':');
if (line)
{
port = (short)atol(line+1);
*line = 0;
}
if (port == 0)
port = 110;
host = gethostbyname( argv[1] );
if (!host)
{
fputs( "unknown host name\r\n", stderr );
goto ErrHandler;
}
sock = socket( AF_INET, SOCK_STREAM, 0 );
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr = *((IN_ADDR*)*host->h_addr_list);
if (connect( sock, (SOCKADDR*)&addr, sizeof(addr) ))
{
fputs( "can't connect host\r\n", stderr );
goto ErrHandler;
}
/* Login */
line = recv_line( sock );
if (line == NULL)
{
fputs( "can't recv data\r\n", stderr );
goto ErrHandler;
}
free( line );
/* User */
sprintf( cmds, "USER %s\r\n", argv[2] );
SEND_LINE;
RECV_LINE;
TOKE_POP3;
free( line );
/* Password */
sprintf( cmds, "PASS %s\r\n", argv[3] );
SEND_LINE;
RECV_LINE;
TOKE_POP3;
free( line );
/* Command */
if (argv[4][0] != '+')
strcpy( cmds, argv[4] );
else
strcpy( cmds, argv[4]+1 );
strcat( cmds, "\r\n" );
SEND_LINE;
RECV_LINE;
TOKE_POP3;
if (argv[4][0] != '+')
{
fputs( line, stderr );
free( line );
strcpy( cmds, "QUIT\r\n" );
ret = send( sock, cmds, strlen(cmds), 0 );
free( recv_line( sock ) );
goto ErrHandler;
}
free( line );
for( ; ; )
{
RECV_LINE;
fputs( line, stdout );
if (!strcmp( line, ".\r\n" ))
{
free( line );
break;
}
else
if (!strcmp( line, "..\r\n" ))
{
fputs( ".\r\n", stdout );
break;
}
free( line );
}
strcpy( cmds, "QUIT\r\n" );
send( sock, cmds, strlen(cmds), 0 );
free( recv_line( sock ) );
ErrHandler:
free( args );
if (sock != -1)
closesocket( sock );
#ifdef WIN32
WSACleanup();
#endif
return my_buffer();
}
/***************************
* get_file
***************************/
char WIN32EXPORT * get_file( char* libcmds )
{
FILE *pfile = fopen(libcmds, "r");
if (pfile)
{
char line[BUFSIZ];
while(fgets(line, BUFSIZ, pfile))
fputs(line, stdout);
fclose(pfile);
}
else
fputs("", stdout);
return my_buffer();
}
/***************************
* smtp_cmd
***************************/
char WIN32EXPORT * smtp_cmd( char* libcmds )
{
#ifdef WIN32
WSADATA wsaData;
#endif
SOCKET sock = -1;
SOCKADDR_IN addr;
HOSTENT* host;
short port = 0;
char helo[256];
char cmds[1024];
char* line;
long ret;
char* pargs;
char* args;
int argc;
char* argv[256];
/* parse arguments */
argc = 0;
pargs = args = strdup(libcmds);
argv[argc++] = "smtp_cmd";
argv[argc++] = args;
for ( ; *pargs != 0x00 ; )
{
if ( *pargs == ',' )
{
*pargs = 0x00;
argv[argc++] = pargs+1;
}
pargs++;
}
if (argc != 5 && argc != 6)
{
fputs( "usage : host from to subject body...\r\n", stderr );
goto ErrHandler;
}
#ifdef WIN32
if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
{
fputs( "can't initialize winsock\r\n", stderr );
goto ErrHandler;
}
#endif
line = strchr((char*)argv[1], ':');
if (line)
{
port = (short)atol(line+1);
*line = 0;
}
if (port == 0)
port = 25;
host = gethostbyname( argv[1] );
if (!host)
{
fputs( "unknown host name\r\n", stderr );
goto ErrHandler;
}
sock = socket( AF_INET, SOCK_STREAM, 0 );
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr = *((IN_ADDR*)*host->h_addr_list);
if (connect( sock, (SOCKADDR*)&addr, sizeof(addr) ))
{
fputs( "can't connect host\r\n", stderr );
goto ErrHandler;
}
/* Login */
line = recv_line( sock );
if (line == NULL)
{
fputs( "can't recv data\r\n", stderr );
goto ErrHandler;
}
free( line );
/* Helo */
if(gethostname( helo, sizeof(helo) ))
{
fputs( "can't resolve hostname\r\n", stderr );
goto ErrHandler;
}
sprintf( cmds, "HELO %s\r\n", helo );
SEND_LINE;
RECV_LINE;
TOKE_SMTP;
free( line );
/* Mail From */
if(strchr( argv[2], '<' ) < strchr( argv[2], '>' ))
sprintf( cmds, "mail from : %s\r\n", argv[2] );
else
sprintf( cmds, "mail from : <%s>\r\n", argv[2] );
SEND_LINE;
RECV_LINE;
TOKE_SMTP;
free( line );
/* Rcpt From */
if(strchr( argv[3], '<' ) < strchr( argv[3], '>' ))
sprintf( cmds, "rcpt to : %s\r\n", argv[3] );
else
sprintf( cmds, "rcpt to : <%s>\r\n", argv[3] );
SEND_LINE;
RECV_LINE;
TOKE_SMTP;
free( line );
/* Data */
strcpy( cmds, "data\r\n" );
SEND_LINE;
RECV_LINE;
free( line );
/* Header */
if (argc == 6)
{
sprintf( cmds, "From: %s\r\n", argv[2] );
SEND_LINE;
sprintf( cmds, "To: %s\r\n", argv[3] );
SEND_LINE;
sprintf( cmds, "Subject: %s\r\n", argv[4] );
SEND_LINE;
sprintf( cmds, "\r\n" );
SEND_LINE;
libcmds = argv[5];
}
else
libcmds = argv[4];
/* Body */
while( (line = strstr( libcmds, "\r\n" )) )
{
if (!strncmp(libcmds, ".\r\n", 3))
ret = send( sock, "..\r\n", 4, 0 );
else
ret = send( sock, libcmds, line-libcmds + 2, 0 );
if (ret < 0)
{
fputs( "can't send data\r\n", stderr );
goto ErrHandler;
}
libcmds = line + 2;
}
ret = send( sock, libcmds, strlen(libcmds), 0 );
if (ret < 0)
{
fputs( "can't send data\r\n", stderr );
goto ErrHandler;
}
strcpy( cmds, "\r\n.\r\n" );
SEND_LINE;
RECV_LINE;
TOKE_SMTP;
free( line );
strcpy( cmds, "QUIT\r\n" );
SEND_LINE;
RECV_LINE;
TOKE_SMTP;
free( line );
ErrHandler:
free( args );
if (sock != -1)
closesocket( sock );
#ifdef WIN32
WSACleanup();
#endif
return my_buffer();
}
static void my_initbuf( void )
{
if(my_puts_buf)
free( my_puts_buf );
if(my_puts_out)
free( my_puts_out );
my_puts_buf = NULL;
my_puts_out = NULL;
my_puts_len = 0;
}
/***************************
* DllMain
***************************/
#ifdef WIN32
BOOL WINAPI DllMain( HINSTANCE hInstDLL, DWORD fdReason, PVOID pvReserved )
{
switch( fdReason )
{
case DLL_PROCESS_ATTACH:
my_initbuf();
break;
case DLL_PROCESS_DETACH:
my_initbuf();
break;
}
return TRUE;
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment