Created
August 4, 2009 10:30
-
-
Save mattn/161146 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"============================================================================= | |
" Title: VIMua (VIm Mail User Agent) | |
" File: vimua.vim | |
" Author: Yasuhiro Matsumoto <[email protected]> | |
" 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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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