Last active
August 29, 2015 14:22
-
-
Save Ke-/54b5ba95b9490070e7a6 to your computer and use it in GitHub Desktop.
pop type for Lasso 9 — converted from a L8.x type floating around.
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
<?lasso | |
define pop => type { | |
data | |
public pop_net = null, | |
public pop_mode = '', | |
public pop_timeout = 15, | |
public pop_token = '', | |
public pop_index = 0, | |
public pop_err = array, | |
public pop_res = array, | |
public pop_log = false, | |
public pop_debug = false, | |
public pop_get = 'retr', | |
public pop_ids = map, | |
public pop_capa = null, | |
public pop_server = '' | |
public oncreate => {} | |
public oncreate( | |
server::string, | |
-host::string = '', | |
-port::integer = 110, | |
-username::string ='', | |
-password::string = '', | |
-timeout::integer = 15, | |
-get::string = 'uidl', | |
-apop = false, | |
-log = false, | |
-debug = false, | |
-ssl = false | |
) => { | |
local( | |
net = net_tcpssl, | |
server = #server || #host , | |
capa | |
) | |
.pop_net = #net | |
.pop_get = #get | |
.pop_log = #log | |
.pop_debug = #debug | |
.pop_timeout = #timeout | |
.pop_server = #server | |
debug('server' = #server) | |
debug('port' = #port) | |
if(#net->connect(#server,#port,#timeout)) => { | |
debug('b' = 'connected') | |
debug('c' = #net->type) | |
debug('->listmethods' =#net->listmethods) | |
debug('->beginTLS' =#net->beginTLS(1)) | |
#net->writebytes('USER '+#username +'\r\n'->asbytes) | |
debug('readsomebytes' = #net->readsomebytes(1000,1)) | |
return self | |
// #net->beginTLS | |
.pop_capa = map | |
/* | |
#capa = .capabilities | |
if(#ssl) => { | |
if(#capa >> 'STLS') => { | |
.stls | |
else | |
.pop_err('Could not open SSL communications',-cmd='STLS') | |
} | |
} | |
*/ | |
if(#username) => { | |
debug('authorize') | |
.authorize( | |
-username = #username, | |
-password = #password, | |
-apop = #apop | |
) | |
} | |
} | |
} | |
public pop_cmd( | |
command::string, | |
-timeout::integer = .pop_timeout, | |
-multi = false, | |
-until = '' | |
) => { | |
! #command->endswith('\r\n') | |
? #command->append('\r\n') | |
debug->open('pop_cmd') | |
handle => {debug->close} | |
debug(params) | |
local( | |
net = .pop_net, | |
result = '', | |
tmp = true, | |
write, | |
i = 0 | |
) | |
debug('command'= #command) | |
debug('command->endswith' = #command->endswith('\r\n')) | |
if(#net->isanyof(::net_tcp,::net_tcpssl)) => { | |
#write = #net->writeBytes(#command->asbytes,1) | |
debug('write' = #write) | |
if(#until) => { | |
while(#result !>> #until && #i++ < 32768) => { | |
#result->append(#net->readSomeBytes(1,1)) | |
} | |
.pop_log(#result->split('\r\n')->get(1)->asstring,-cmd=#command) | |
else | |
debug('#net->readSomeBytes(1)' = #net->readSomeBytes(1)) | |
while(#result !>> '\r\n' && #i++ < 32768) => { | |
#result->append( | |
#net->readSomeBytes(1) | |
) | |
} | |
debug(#i) | |
#i = 0 | |
#multi ? while(#result !>> '\r\n.\r\n' && #i++ < 1000 && #tmp) => { | |
#result->append( | |
#tmp := #net->readSomeBytes(32768) | |
) | |
.pop_log('... reading (' + #tmp->size + ' bytes)',-cmd=#command) | |
} | |
debug('result' = #result) | |
} | |
else | |
.pop_err('The remote server timed out on read.', -cmd=#command) | |
} | |
return #result | |
} | |
public user(username::string='') => { | |
if(#username) => { | |
return .pop_cmd('USER '+#username) | |
else | |
return .pop_err('No username specified.',-cmd='USER') | |
} | |
} | |
public pass(password::string='') => { | |
if(#password) => { | |
return .pop_cmd('PASS '+#password) | |
else | |
return .pop_err('No password specified.',-cmd='PASS') | |
} | |
} | |
public apop(username::string,password::string) => { | |
if(.pop_token >> '<') => { | |
return .pop_cmd('APOP ' + #username + ' ' + encrypt_md5(.pop_token+#password)) | |
else | |
return .pop_err('No password specified.',-cmd='PASS') | |
} | |
} | |
public quit => { | |
.pop_mode = 'done' | |
return .pop_cmd('QUIT')->trim &; | |
} | |
public rset => { | |
return .pop_cmd('RSET')->trim &; | |
} | |
public stat => { | |
return.pop_cmd('STAT')->trim &; | |
} | |
public list(msg::integer) => { | |
if(#msg) => { | |
return .pop_cmd('LIST ' + #msg)->trim &; | |
else | |
return .pop_cmd('LIST', -multi=true)->trim &; | |
} | |
} | |
public uidl(msg::integer) => { | |
if(#msg) => { | |
return .pop_cmd('UIDL ' + #msg)->trim &; | |
else | |
return .pop_cmd('UIDL', -multi=true)->trim &; | |
} | |
} | |
public retr(msg::integer) => { | |
return .pop_cmd('RETR ' + #msg, -multi=true)->trim &; | |
} | |
public top(msg::integer,size::integer=0) => { | |
return .pop_cmd('TOP ' + #msg + ' ' + #size, -multi=true)->trim &; | |
} | |
public dele(msg::integer) => { | |
return .pop_cmd('DELE ' + #msg)->trim &; | |
} | |
public noop => { | |
return .pop_cmd('NOOP')->trim &; | |
} | |
public capa() => { | |
return .pop_cmd('CAPA', -multi=true)->trim &; | |
} | |
public stls() => { | |
return .pop_cmd('STLS', -until='\r\n')->trim &; | |
} | |
public size => { | |
protect => { | |
return string_findregexp(.pop_cmd('STAT'),-find='[0-9]+')->first->asinteger | |
} | |
return 0 | |
} | |
public close => { | |
.pop_ids = map | |
.pop_index = 0 | |
.quit | |
} | |
public cancel => { | |
.rset | |
.close | |
} | |
public results => .pop_res | |
public errors => .pop_err | |
public lasterror => .pop_err->last | |
public data => .pop_token | |
public pop_err( | |
msg::string, | |
-code::integer=0, | |
-cmd::string='' | |
) => { | |
.pop_res->insert(#cmd=#msg) | |
fail(#code,#msg) | |
} | |
public pop_log( | |
msg::string, | |
-code::string='', | |
-cmd::string='' | |
) => { | |
.pop_res->insert(#cmd=#msg) | |
error_seterrormessage(error_noerror) | |
error_seterrorcode(error_noerror(-errorcode)) | |
} | |
public pop_last => { | |
protect => { | |
return .pop_res->last->second->asstring | |
} | |
return '' | |
} | |
/* Gmail Specific */ | |
public authorize( | |
-username::string, | |
-password::string, | |
-apop = false | |
) => { | |
local( | |
methods, | |
done | |
) | |
if(.pop_capa >> 'sasl') => { | |
#methods = .pop_capa->find('sasl') | |
else | |
#methods = array('LOGIN','PLAIN') | |
} | |
if(!#done && #methods >> 'DIGEST-MD5') => { | |
.auth(-username=#username, -password=#password, -method='DIGEST-MD5') | |
#done = .pop_res->last->second >> '+ ' | |
} | |
if(!#done && #methods >> 'CRAM-MD5') => { | |
.auth(-username=#username, -password=#password, -method='CRAM-MD5') | |
#done = .pop_res->last->second >> '+OK' | |
} | |
if(!#done && #apop && .pop_token >> '<') => { | |
.apop(-username=#username, -password=#password) | |
#done = .pop_res->last->second >> '+OK' | |
} | |
if(!#done) => { | |
.capa | |
.user(#username) | |
.pass(#password) | |
#done = .pop_res->last->second >> '+OK' | |
} | |
if(!#done) => { | |
.pop_err('Could not authenticate user.',-cmd='PASS') | |
else | |
.pop_mode = 'ready' | |
} | |
.pop_ids = map | |
.pop_index = 0 | |
} | |
public auth( | |
-username::string, | |
-password::string, | |
-method::string | |
) => { | |
local( | |
result,digest | |
) | |
match(#method) => { | |
case('CRAM-MD5') | |
#result = .pop_cmd('AUTH CRAM-MD5') | |
if(#result->beginswith('+ ')) => { | |
return .pop_cmd( | |
encode_base64(#username+' '+encrypt_crammd5(#password,#result)) | |
) | |
else | |
.pop_err('Invalid response for ' + #method + ' method.',-cmd='AUTH') | |
} | |
case('DIGEST-MD5') | |
#result = .pop_cmd('AUTH DIGEST-MD5') | |
if(#result->beginswith('+ ')) => { | |
#result->remove(3) | |
#digest = email_digestchallenge(decode_base64(#result)) | |
#digest->insert('username' = #username) | |
#digest->insert('password' = #password) | |
#digest->insert('digest-uri' = 'pop/' + self->'pop_server') | |
#digest->insert('cnonce' = (encrypt_md5: lasso_uniqueid)) | |
#digest->insert('nc' = '00000001') | |
return .pop_cmd( | |
encode_base64(email_digestresponse(#digest)) | |
) | |
else | |
.pop_err('Invalid response for ' + #method + ' method.',-cmd='AUTH') | |
} | |
case | |
.pop_err('Method ' + #method + ' not found.',-cmd='AUTH') | |
} | |
#digest = encrypt_md5(.pop_token + #password) | |
return .pop_cmd('APOP ' + #username + ' ' + #digest) | |
} | |
public get(msg::string) => { | |
local( | |
msg = .pop_ids->find(#msg) | |
) | |
fail_if(!#msg, -9956, '[pop->' + method_name + '] invalid msg index') | |
return .get(#msg) | |
} | |
public get(msg::integer) => { | |
! #msg | |
? #msg = .pop_index | |
if(#msg) => { | |
match(.pop_get) => { | |
case('retr') | |
return .retrieve(#msg) | |
case('dele') | |
return .delete(#msg) | |
case('head') | |
return .headers(#msg) | |
case('top') | |
return .retrieve(#msg,string_replaceregexp(.pop_get, -find='.*(\\d+).*',-replace='\\1')->asinteger) | |
case | |
return .uniqueid(#msg) | |
} | |
} | |
return '' | |
fail(-9956, '[pop->' + method_name + '] invalid msg index.') | |
} | |
public retrieve(msg::integer,size::integer=0) => { | |
local(result) | |
if(#msg) => { | |
if(#size) => { | |
#result = .top(#msg,#size) | |
else | |
#result = .retr(#msg) | |
} | |
fail_if( | |
#result->beginswith('-ERR'), -9956, | |
'The tag [Email_POP->' + tag_name + '] did not find a message at provided position (' + #msg ').' | |
) | |
#result = #result->substring(1,#result->find('\r\n')+2) | |
#result->trim | |
#result->removetrailing('\r\n.') | |
return #result | |
else | |
return '' | |
} | |
} | |
public headers(msg::integer) => { | |
local(result) | |
if(#msg) => { | |
#result = .top(#msg,0) | |
fail_if( | |
#result->beginswith('-ERR'), -9956, | |
'The tag [Email_POP->' + tag_name + '] did not find a message at provided position (' + #msg ').' | |
) | |
#result = #result->substring(1,#result->find('\r\n')+2) | |
#result->trim | |
#result->removetrailing('\r\n.') | |
return #result | |
else | |
return '' | |
} | |
} | |
public delete(msg::integer) => { | |
local(result) | |
if(#msg) => { | |
#result = .dele(#msg) | |
fail_if( | |
#result->beginswith('-ERR'), -9956, | |
'The tag [Email_POP->' + tag_name + '] did not find a message at provided position (' + #msg ').' | |
) | |
} | |
} | |
public uniqueid(msg::integer) => { | |
local(result) | |
if(#msg) => { | |
#result = .uidl(#msg) | |
fail_if( | |
#result->beginswith('-ERR'), -9956, | |
'The tag [Email_POP->' + tag_name + '] did not find a message at provided position (' + #msg ').' | |
) | |
#result = #result->split(' ') | |
if(#result->size > 2) => { | |
#result = #result->get(3)->asinteger | |
if(#result) => { | |
.pop_ids->insert( | |
#result = #msg | |
) | |
return #result | |
} | |
} | |
else | |
return 0 | |
} | |
} | |
public capabilities => { | |
if(.pop_capa->isa(::null)) => { | |
debug('get capabilities') | |
local( | |
capa = map, | |
result = .capa | |
) | |
#result->replace('\r\n','\n') | |
#result->replace('\r','\n') | |
with tmp in #result->split('\n') do { | |
if(#tmp && !#tmp->beginswith('+') && !#tmp->beginswith('.')) => { | |
if(#tmp >> ' ') => { | |
#tmp = #tmp->split(' ') | |
#capa->insert( | |
#tmp->first = #tmp->remove(1) & | |
) | |
else | |
#capa->insert( | |
#tmp = '' | |
) | |
} | |
} | |
} | |
debug('#capa'=#capa ) | |
return .pop_capa := #capa | |
} | |
return .pop_capa | |
} | |
} | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment