--- freepops-0.2.9.orig/doc/RFCs.txt +++ freepops-0.2.9/doc/RFCs.txt @@ -7,3 +7,4 @@ http://www.ietf.org/rfc/rfc2822.txt http://www.ietf.org/rfc/rfc2965.txt http://www.ietf.org/rfc/rfc822.txt +http://www.ietf.org/rfc/rfc*.txt --- freepops-0.2.9.orig/src/lua/supereva.lua +++ freepops-0.2.9/src/lua/supereva.lua @@ -1,12 +1,12 @@ -- ************************************************************************** -- -- FreePOPs Supereva webmail interface -- --- $Id: supereva.lua,v 1.22 2008/12/15 12:20:12 gareuselesinge Exp $ +-- $Id: supereva.lua,v 1.7 2009/03/29 18:59:51 gareuselesinge Exp $ -- -- Released under the GNU/GPL license -- ************************************************************************** -- -PLUGIN_VERSION = "0.2.7b" +PLUGIN_VERSION = "0.2.7c" PLUGIN_NAME = "Supereva" PLUGIN_REQUIRE_VERSION = "0.2.0" PLUGIN_LICENSE = "GNU/GPL" @@ -36,11 +36,11 @@ -- ------------------------------------------------------------------------ -- -- Constants local supereva_strings = { - login_uri = "http://it.email.dada.net/cgi-bin/sso/login.cgi", -- "http://it.email.dada.net/cgi-bin/sn_my/login.chm", + login_uri = "http://sso.dada.it/cgi-bin/sso/login.cgi", --"http://it.email.dada.net/cgi-bin/sso/login.cgi", -- "http://it.email.dada.net/cgi-bin/sn_my/login.chm", login_data = "username=%s&password=%s", - inbox_uri = "http://it.email.dada.net/cgi-bin/main.chm?mlt_msgs=", - get_uri = "http://it.email.dada.net/cgi-bin/nrmail03.chm?msgnum=", + inbox_uri = "http://email.dada.it/cgi-bin/main.chm?mlt_msgs=", + get_uri = "http://email.dada.it/cgi-bin/nrmail03.chm?msgnum=", inbox_e = "" .. ".*" .. --- freepops-0.2.9.orig/src/lua/juno.lua +++ freepops-0.2.9/src/lua/juno.lua @@ -7,7 +7,7 @@ -- Globals -- -PLUGIN_VERSION = "0.1.20081222" +PLUGIN_VERSION = "0.1.20090411" PLUGIN_NAME = "juno.com" PLUGIN_REQUIRE_VERSION = "0.2.0" PLUGIN_LICENSE = "GNU/GPL" @@ -615,6 +615,7 @@ -- -------------------------------------------------------------------------- -- function getAttachmentTable(cbInfo, data) local attachments = {} + local lookup = {} local body = cbInfo.strBuffer -- find attachments @@ -630,7 +631,6 @@ filename = getFilename(url, filename) log.dbg("Found Attachment, File: " .. filename .. " - Url: " .. url) attachments[filename] = url - table.insert(attachments, table.maxn(attachments) + 1, url) end return attachments --- freepops-0.2.9.orig/src/lua/tin.lua +++ freepops-0.2.9/src/lua/tin.lua @@ -1,7 +1,7 @@ -- ************************************************************************** -- -- FreePOPs @virgilio.it, @tin.it webmail interface -- --- $Id: tin.lua,v 1.95 2008/04/03 22:34:35 gareuselesinge Exp $ +-- $Id: tin.lua,v 1.35 2009/03/25 21:23:30 nvhs Exp $ -- -- Released under the GNU/GPL license -- Written by Enrico Tassi @@ -9,7 +9,7 @@ -- these are used in the init function -PLUGIN_VERSION = "0.2.11h" +PLUGIN_VERSION = "0.2.21" PLUGIN_NAME = "Tin.IT" PLUGIN_REQUIRE_VERSION = "0.2.0" PLUGIN_LICENSE = "GNU/GPL" @@ -86,9 +86,9 @@ login2Ct="&t=([^&]+)", login2Cs="&s=([%d]+)", -- mesage list mlex - statE = ".*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*", + statE = ".*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*.*", statG = "OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXO", - + -- The uri for the first page with the list of messages -- parameters all %s except fi that is %d: -- wherearewe(), folder, domain, username, t, s, fi @@ -102,18 +102,18 @@ timeoutC = '(window.parent.location.*/mail/main?.*err=24)', -- The uri to save a message (read download the message) -- wherearewe(), mailbox, domain, username, username, uidl, t, s - save = "http://%s/cp/ps/Mail/Email".. + save = "http://%s/cp/ps/Mail/EmailSecure".. "?sh=&fp=%s&d=%s&sd=&sc=&an=%s&u=%s&".. "uid=%s&t=%s&style=&l=it&s=%s&sl=%d", - save_sl = "http://%s/cp/ps/Mail/Email".. + save_attach = "http://%s/cp/ps/Mail/Email".. "?sh=&fp=%s&d=%s&sd=&sc=&an=%s&u=%s&".. - "uid=&t=%s&style=&l=it&s=%s&sl=%d", - body_start = [[%s-%s-
%s-
%s-]], - body_end = [[%s*%s*%s*%s*%s*]], + "uid=%s&t=%s&style=&l=it&s=%s&sl=%d", + body_start = [[%s-%s-
%s-
%s-.-%s*]], + body_end = [[ %s*
%s*<.?.?.?.?DO NOT REMOVE THIS USED TO CALC LENGHT OF PAGE .->]], attachE = ".*.*.*", attachG = "OOX", -- by nvhs for html image - imageE = "", + imageE = "<.?.?[Ii][Mm][Gg].*cp/ps/Mail/SecureViewAttachment.*>", imageG = "", -- by nvhs for attach mail mailE = ".*.*.*", @@ -351,7 +351,7 @@ return url, post end -function tin_login() +function tin_http_login() if internal_state.login_done then return POPSERVER_ERR_OK end @@ -422,6 +422,116 @@ return POPSERVER_ERR_OK end + +function tin_https_login() + if internal_state.login_done then + return POPSERVER_ERR_OK + end + + -- build the uri + local password = internal_state.password + local domain = internal_state.domain + local user = internal_state.name + local pop_login = user .. "@" .. domain + + -- the browser must be preserved + internal_state.b = browser.new() + + local b = internal_state.b + --b:verbose_mode() + + local initial_uri = "http://pf.rossoalice.alice.it/Vpf.html?" + local body, err = b:get_uri(initial_uri) + + local post = +"usernameDisplay=" .. user .. "&password="..password.. +"&dominio="..domain.."&imageField.x=31&imageField.y=13&".. +"login="..pop_login.."&pwd="..password.."&channel=Vmail&".. +"URL_OK=https%3A%2F%2Fauthsrs.alice.it%2Faap%2Faap_redir.jsp%3Fentry%3DVmail&".. +"URL_KO=https%3A%2F%2Fauthsrs.alice.it%2Faap%2Faap_redir_ko.jsp%3Fentry%3DVmail&".. +"servizio=mail&msisdn="..user.."&username="..pop_login.."&user="..pop_login.. +"&a3afep=http%3A%2F%2Fportale.rossoalice.alice.it%2Fps%2FManageCodError.do%3Fcode%3D470%26channel%3DVmail&".. +"DOMAIN=&PASS="..password.."&self=true&a3si=none&a3st=VCOMM&totop=true¬otopa3ep=true&a3aid=lvmes&a3flag=0&".. +"a3ep=http%3A%2F%2Fdise.alice.it%2Fdest%2Fwebmail&".. +"a3se=http%3A%2F%2Fportale.rossoalice.alice.it%2Fps%2FManageCodError.do%3Fcode%3D470%26channel%3DVmail&".. +"a3dcep=http%3A%2F%2Fcommunicator.alice.it%2Fasp%2Fhomepage.asp%3Fs%3D005&".. +"a3l="..pop_login.."&a3p="..password.."&rememberUsernameChk=checkbox" + + local login_uri = "https://aaacsc.alice.it/piattaformaAAA/aapm/amI" + local body, err = b:post_uri(login_uri, post) + if body == nil then + log.error_print("Error getting "..login_uri.. ": "..err) + return POPSERVER_ERR_AUTH + end + + -- look for redirect + local newurl_match = "window%.[a-z%.]*%.href%s=%s\"([^\"]+)\"" + local newurl = string.match(body, newurl_match) + if newurl == nil then + log.error_print("Error matching "..newurl_match) + return POPSERVER_ERR_AUTH + end + + local body, err = b:get_uri(newurl) + if body == nil then + log.error_print("Error getting "..newurl..": "..err) + return POPSERVER_ERR_AUTH + end + local newurl = string.match(body, newurl_match) + if newurl == nil then + log.error_print("Error matching "..newurl_match) + return POPSERVER_ERR_AUTH + end + + local body, err = b:get_uri(newurl) + if body == nil then + log.error_print("Error getting "..newurl..": "..err) + return POPSERVER_ERR_AUTH + end + + -- step 2: get session id_s and id_t + local tincctoken = assert(b:get_cookie("tincctoken"), + "unable to find cookie tincctoken").value + local url = string.format(tin_string.login2, domain, + curl.escape(pop_login), curl.unescape(tincctoken)) + local body,err = b:get_uri(url) + if body == nil then + log.error_print("Error getting "..url..": "..err) + return POPSERVER_ERR_AUTH + end + local capt = string.match(body, tin_string.login2C) + local t = string.match(capt, tin_string.login2Ct) + local s = string.match(capt, tin_string.login2Cs) + + internal_state.session_id_s = s + internal_state.session_id_t = t + + if internal_state.session_id_s == nil or + internal_state.session_id_t == nil then + log.error_print("Login failed\n") + return POPSERVER_ERR_AUTH + end + + -- save all the computed data + internal_state.login_done = true + + -- log the creation of a session + log.say("Session started for " .. internal_state.name .. "@" .. + internal_state.domain .. + "(" .. internal_state.session_id_t .. ", " .. + internal_state.session_id_s .. ")\n") + + return POPSERVER_ERR_OK +end + +function tin_login() + local rc = tin_http_login() + if rc ~= POPSERVER_ERR_OK then + return tin_https_login() + else + return rc + end +end -- ************************************************************************** -- -- Tin functions @@ -528,7 +638,6 @@ local post = string.format(tin_string.delete_post, folder, uidl, user) local body, err = b:post_uri(uri, post) - print(uri, post)--, body) if body == nil then log.error_print("Error getting "..uri..":"..err) return POPSERVER_ERR_UNKNOWN @@ -578,6 +687,7 @@ -- The action for do_until -- -- uses mlex to extract all the messages uidl and size + local stop = false local function action_f (s) -- calls match on the page s, with the mlexpressions -- statE and statG @@ -587,6 +697,10 @@ -- the number of results local n = x:count() + if n < 10 then + stop = true + end + if n == 0 then return true,nil @@ -608,7 +722,7 @@ k = string.match(size,"([Kk][Bb])") m = string.match(size,"([Mm][Bb])") size = string.match(size,"([%.%d]+)") - uidl = string.match(uidl,'uid=([%d]+)') + uidl = string.match(uidl,"read%s*%(%s*'"..internal_state.folder.."'%s*,%s*'([%d]+)'") if not uidl or not size then return nil,"Unable to parse page" @@ -627,14 +741,12 @@ set_mailmessage_uidl(pstate,i+nmesg_old,uidl) internal_state.reverse_lookup[uidl] = i+nmesg_old end - + return true,nil end -- check must control if we are not in the last page and -- eventually change uri to tell retrive_f the next page to retrive - local count = 0 - local how_many_refs = 0 local function next_page() page = page + 10 uri = string.format(tin_string.first, @@ -647,32 +759,8 @@ -- if a limit was set, stop return true end - local tmp = string.find(s,tin_string.no_next) - if tmp ~= nil and count == 0 then - return next_page() - else - if count == 0 then - -- we are on the last page only if we have seen - -- this 3 times - for x in string.gfind(s,tin_string.list_href) do - how_many_refs = how_many_refs + 1 - end - -- there should be links before and after - -- the list - if math.fmod(how_many_refs, 2) ~= 0 then - log.error_print( - "Error in counting list_href") - return true - end - how_many_refs = how_many_refs / 2 - end - count = count + 1 - if count >= how_many_refs then - return true - else - return next_page() - end - end + if stop then return true end + return next_page() end -- this is simple and uri-dependent @@ -763,7 +851,8 @@ -- Get first lines message msg lines, must call -- popserver_callback to send the data -- -function tin_parse_webmessage(wherearewe, data) +-- +function tin_parse_webmessage(wherearewe, data, data_attach) local head, body, body_html, attach ,inlineids = nil, nil, nil, {} , {} -- extract headers @@ -800,6 +889,7 @@ "[Tt][Ee][Xx][Tt]/[Pp][Ll][Aa][Ii][Nn]") if found == nil then body_html = string.sub(data, begin_body + 1, end_body - 1) + -- body_html = string.gsub(data, "%s*%s-%s*", "") head = mimer.remove_lines_in_proper_mail_header(head, {"content%-type"}) else @@ -824,7 +914,7 @@ end -- extract attachments - local x = mlex.match(data, tin_string.attachE, tin_string.attachG) + local x = mlex.match(data_attach,tin_string.attachE,tin_string.attachG) --x:print() for i = 1, x:count() do local url = x:get(0,i-1) @@ -837,7 +927,7 @@ -- by nvhs extract attach mail - local x = mlex.match(data, tin_string.mailE, tin_string.mailG) + local x = mlex.match(data_attach, tin_string.mailE, tin_string.mailG) --x:print() for i = 1, x:count() do local url = x:get(0,i-1) @@ -856,8 +946,9 @@ -- y:print() for i = 1, y:count() do local url = y:get(0,i-1) + print(url) url = string.match(url, - "/cp/ps/Mail/ViewAttachment.-&id=%d*") + "/cp/ps/Mail/SecureViewAttachment?.-&id=%d*") if url ~= nil then attach[url] = "http://"..wherearewe..url inlineids[url]=url @@ -867,7 +958,7 @@ -- replace url with cid if body_html ~= nil then body_html = string.gsub(body_html, - "/cp/ps/Mail/ViewAttachment.-&id=%d*","cid:%1") + "src%s*=%s*\".-(/cp/ps/Mail/SecureViewAttachment.-&id=%d*).-\"",'src="cid:%1"') end return head, body, body_html, attach ,inlineids @@ -949,8 +1040,18 @@ return POPSERVER_ERR_UNKNOWN end + local uri = string.format(tin_string.save_attach,popserver, + folder, domain, user, user, uidl, session_id_t, session_id_s,sl) + + -- tell the browser to fetch + local f_attach, err = b:get_uri(uri) + if f_attach == nil then + log.error_print("Error fetching "..uri..": ".. (err or 'nil')) + return POPSERVER_ERR_UNKNOWN + end + local wherearewe = add_webmail_in_front(b:wherearewe()) - local head,body,body_html,attach,inlineids = tin_parse_webmessage(wherearewe, f) + local head,body,body_html,attach,inlineids = tin_parse_webmessage(wherearewe, f, f_attach) local cb = mimer.callback_mangler(common.retr_cb(data)) head = string.gsub(head,"([Cc][Hh][Aa][Rr][Ss][Ee][Tt]%s*=).-([;\n])","%1\""..ctype.."\"%2") mimer.pipe_msg(head,body,body_html,"http://"..wherearewe,attach,b,cb,inlineids,ctype) @@ -1014,8 +1115,18 @@ return POPSERVER_ERR_NETWORK end + local uri = string.format(tin_string.save_attach,popserver, + folder, domain, user, user, uidl, session_id_t, session_id_s,sl) + + -- tell the browser to fetch + local f_attach, err = b:get_uri(uri) + if f_attach == nil then + log.error_print("Error fetching "..uri..": ".. (err or 'nil')) + return POPSERVER_ERR_UNKNOWN + end + local wherearewe = add_webmail_in_front(b:wherearewe()) - local head,body,body_html,attach,inlineids = tin_parse_webmessage(wherearewe, f) + local head,body,body_html,attach,inlineids = tin_parse_webmessage(wherearewe, f, f_attach) local global = common.new_global_for_top(lines,nil) local cb = mimer.callback_mangler(common.top_cb(global,data,true)) head = string.gsub(head,"([Cc][Hh][Aa][Rr][Ss][Ee][Tt]%s*=).-([;\n])","%1\""..ctype.."\"%2") --- freepops-0.2.9.orig/src/lua/hotmail.lua +++ freepops-0.2.9/src/lua/hotmail.lua @@ -3,11 +3,12 @@ -- -- Released under the GNU/GPL license -- Written by Russell Schwager +-- contributions from D. Milne -- ************************************************************************** -- -- Globals -- -PLUGIN_VERSION = "0.2.20081219" +PLUGIN_VERSION = "0.2.20091013" PLUGIN_NAME = "hotmail.com" PLUGIN_REQUIRE_VERSION = "0.2.8" PLUGIN_LICENSE = "GNU/GPL" @@ -20,7 +21,7 @@ "@hotmail.de", "@hotmail.it", "@hotmail.co.uk", "@hotmail.co.jp", "@hotmail.fr", "@messengeruser.com", "@hotmail.com.ar", "@hotmail.co.th", "@hotmail.com.tr", - "@milanosemplice.it" + "@windowslive.com", "@milanosemplice.it" } PLUGIN_PARAMETERS = { {name="folder", description={ @@ -197,23 +198,11 @@ -- Pattern used by Stat to get the next page in the list of messages -- - - -- gboudreau fix (patched by doglan) - Part 1 (start) - --strMsgListNextPagePattern = '(nextpg%.gif" border=0>)', - --strMsgListNextPagePatLiveLight = ']*>=on strCmdDeleteLive = "http://%s/mail/mail.fpp?cnmn=Microsoft.Msn.Hotmail.Ui.Fpp.MailBox.MoveMessages&ptid=0&a=%s&au=%s", strCmdDeletePostLiveOld = 'cn=Microsoft.Msn.Hotmail.Ui.Fpp.MailBox&mn=MoveMessages&d="%s","%s",[%s],[{"%%5C%%7C%%5C%%7C%%5C%%7C0%%5C%%7C%%5C%%7C%%5C%%7C00000000-0000-0000-0000-000000000001%%5C%%7C632901424233870000",{2,"00000000-0000-0000-0000-000000000000",0}}],null,null,0,false,Date&v=1', - -- strCmdDeletePostLive = 'cn=Microsoft.Msn.Hotmail.Ui.Fpp.MailBox&mn=MoveMessages&d="%s","%s",[%s],[{"%%5C%%7C%%5C%%7C%%5C%%7C0%%5C%%7C%%5C%%7C%%5C%%7C%%5C%%7C00000000-0000-0000-0000-000000000001%%5C%%7C632750213035330000",null}],null,null,0,false,Date,false,true&v=1&mt=%s', strCmdDeletePostLive = 'cn=Microsoft.Msn.Hotmail.Ui.Fpp.MailBox&mn=MoveMessages&d="%s","%s",[%s],[{"0%%5C%%7C0%%5C%%7C8C9BDFF65883200%%5C%%7C00000000-0000-0000-0000-000000000001",null}],null,null,0,false,Date,false,true&v=1&mt=%s', - --strCmdDeleteLiveLight = "http://%s/mail/InboxLight.aspx?FolderID=%s&", - --strCmdDeletePostLiveLight = "__VIEWSTATE=&mt=%s&MoveMessageSelector=%s&ToolbarActionItem=MoveMessageSelector&", -- SelectedMessages=%s", - strCmdDeleteLiveLight = "http://%s/mail/mail.fpp?cnmn=Microsoft.Msn.Hotmail.Ui.Fpp.MailBox.MoveMessagesToFolder&ptid=0&a=%s&au=%s", + strCmdDeleteLiveLight = "http://%s/mail/mail.fpp?cnmn=Microsoft.Msn.Hotmail.Ui.Fpp.MailBox.MoveMessagesToFolder&ptid=0&a=%s&au=%s", strCmdDeletePostLiveLight = 'cn=Microsoft.Msn.Hotmail.Ui.Fpp.MailBox&mn=MoveMessagesToFolder&d="%s","%s",[%s],[%s],{"%s",25,FirstPage,0,Date,false,"00000000-0000-0000-0000-000000000000","",1,2,false,"",false,0},null&v=1&mt=%s', - strCmdDeletePostLiveLight2 = 'cn=Microsoft.Msn.Hotmail.Ui.Fpp.MailBox&mn=MoveMessagesToFolder&d="%s","%s",[%s],[%s],{"%s",FirstPage,0,Date,false,"00000000-0000-0000-0000-000000000000","",1,2,false,"",26,0,Bottom}&v=1&mt=%s', - + -- doglan @ 2009-10-10: Updated URL + strCmdDeletePostLiveLight2 = 'cn=Microsoft.Msn.Hotmail.Ui.Fpp.MailBox&mn=MoveMessagesToFolder&d="%s","%s",[%s],[%s],{"%s",FirstPage,0,Date,false,"00000000-0000-0000-0000-000000000000","",1,2,false,"",0,-1,Off}&v=1&mt=%s', strCmdMsgView = "http://%s/cgi-bin/getmsg?msg=%s&imgsafe=y&curmbox=%s&a=%s", strCmdMsgViewRaw = "&raw=0", strCmdMsgViewLive = "http://%s/mail/GetMessageSource.aspx?msgid=%s&gs=true", @@ -292,12 +275,11 @@ strCmdEmptyTrashLiveLightPost = 'cn=Microsoft.Msn.Hotmail.Ui.Fpp.MailBox&mn=ClearFolder&d="%s",{"%s",25,FirstPage,0,Date,false,"00000000-0000-0000-0000-000000000000","",1,2,false,"",false,0}&v=1&mt=%s', strCmdMsgReadLive = "http://%s/mail/mail.fpp?cnmn=Microsoft.Msn.Hotmail.Ui.Fpp.MailBox.MarkMessages&ptid=0&a=&au=%s", strCmdMsgReadLivePost = "cn=Microsoft.Msn.Hotmail.Ui.Fpp.MailBox&mn=MarkMessages&d=true,[%s]&v=1&mt=%s", - --strCmdMsgReadLiveLight = "http://%s/mail/ReadMessageLight.aspx?AllowUnsafe=True&Aux=&FolderID=%s&InboxSortAscending=False&InboxSortBy=Date&ReadMessageId=%s", strCmdMsgReadLiveLight = "http://%s/mail/mail.fpp?cnmn=Microsoft.Msn.Hotmail.Ui.Fpp.MailBox.MarkMessagesReadState&ptid=0&a=%s&au=%s", - --strCmdMsgReadLiveLightPost = 'cn=Microsoft.Msn.Hotmail.Ui.Fpp.MailBox&mn=MarkMessagesReadState&d=true,["%s"],{"%s",25,FirstPage,0,Date,false,"00000000-0000-0000-0000-000000000000","",1,2,false,"",false,0}&v=1&mt=%s', + -- Submitted by Barlad - -- - strCmdMsgReadLiveLightPost = 'cn=Microsoft.Msn.Hotmail.Ui.Fpp.MailBox&mn=MarkMessagesReadState&d=true,["%s"],{"%s",FirstPage,0,Date,false,"00000000-0000-0000-0000-000000000000","",1,2,false,"",1085,0,Right}&v=1&mt=%s', + -- doglan @ 2009-10-10: Updated URL (["%s"],) + strCmdMsgReadLiveLightPost = 'cn=Microsoft.Msn.Hotmail.Ui.Fpp.MailBox&mn=MarkMessagesReadState&d=true,["%s"],{"%s",FirstPage,0,Date,false,"00000000-0000-0000-0000-000000000000","",1,2,false,"",18,-1,Off}&v=1&mt=%s', } -- ************************************************************************** -- @@ -366,9 +348,9 @@ local try = 0 if post ~= nil then - --log.dbg("LOADING: " .. url .. "\nPOST: " .. post .. "\n") + log.dbg("LOADING: " .. url .. "\nPOST: " .. post .. "\n") else - --log.dbg("LOADING: " .. url .. "\n") + log.dbg("LOADING: " .. url .. "\n") end while (try < 3) do @@ -418,6 +400,35 @@ return body, err end + +function CheckForMessageAtLogin(browser, url, body) + local err + -- Let's look for a message at login + -- + local hasMsgAtLogin = false + url = string.match(body, '
1 then uidlsLight = uidlsLight .. ',"' .. uidl .. '"' - madsLight = madsLight .. ',{"' .. mad .. '",null}' + -- doglan @ 2009-10-10: ",null" no longer needed before "}" + madsLight = madsLight .. ',{"' .. mad .. '"}' else uidlsLight = '"' .. uidl .. '"' - madsLight = '{"' .. mad .. '",null}' + -- doglan @ 2009-10-10: ",null" no longer needed before "}" + madsLight = '{"' .. mad .. '"}' -- ,null end dcnt = dcnt + 1 elseif internalState.bLiveGUI == true and get_mailmessage_flag(pstate, i, MAILMESSAGE_DELETE) then @@ -1522,20 +1532,11 @@ end elseif dcnt > 0 and internalState.bLiveGUI and internalState.bLiveLightGUI == true then cmdUrl = string.format(globals.strCmdDeleteLiveLight, internalState.strMailServer, internalState.strCrumb, internalState.strUserId) - - -- This is the older interface's way to delete it. - -- local inboxid = string.gsub(internalState.strMBox, "&n=.*", "") - post = string.format(globals.strCmdDeletePostLiveLight, - inboxid, internalState.strTrashId, - uidlsLight, madsLight, - inboxid, internalState.strMT) - post = string.gsub(post, '"', "%%22") --- log.dbg("Sending Trash url: " .. cmdUrl .. " - " .. post) - local body, err = getPage(browser, cmdUrl, post, "Delete Messages - LiveLight") -- This is less than ideal and will need to be fixed soon. This is the newer way to delete. -- + madsLight = string.gsub(madsLight, "|", "%%5C%%7C") post = string.format(globals.strCmdDeletePostLiveLight2, inboxid, internalState.strTrashId, uidlsLight, madsLight, @@ -1543,7 +1544,7 @@ post = string.gsub(post, '"', "%%22") local body, err = getPage(browser, cmdUrl, post, "Delete Messages - LiveLight - Newer version") - elseif dcnt > 0 and internalState.bLiveGUI then + elseif dcnt > 0 and internalState.bLiveGUI then cmdUrl = string.format(globals.strCmdDeleteLive, internalState.strMailServer, internalState.strCrumb, internalState.strUserId) uidls = string.gsub(uidls, ",", '","') uidls = '"' .. uidls .. '"' @@ -1566,7 +1567,7 @@ log.dbg("Sending Empty Trash URL: " .. cmdUrl .."\n") local body, err = getPage(browser, cmdUrl, nil, "NonLive - Empty Trash") if not body or err then - log.error_print("Error when trying to empty the trash with url: ".. cmdUrl .."\n") + log.error_print("Error when trying to empty the trash with url: ".. cmdUrl .. "\n") end else log.error_print("Cannot empty trash - crumb not found\n") @@ -2356,3 +2357,4 @@ -- EOF -- ************************************************************************** -- + --- freepops-0.2.9.orig/src/lua/fastmail.lua +++ freepops-0.2.9/src/lua/fastmail.lua @@ -7,7 +7,7 @@ -- Globals -- -PLUGIN_VERSION = "0.0.3c" +PLUGIN_VERSION = "0.1.20091013a" PLUGIN_NAME = "fastmail.com" PLUGIN_REQUIRE_VERSION = "0.2.0" PLUGIN_LICENSE = "GNU/GPL" @@ -36,29 +36,30 @@ "@veryfast.biz", "@veryspeedy.net", "@warpmail.net", "@xsmail.com", "@yepmail.net", "@your-mail.com", } PLUGIN_PARAMETERS = { - {name="folder", description={ - it=[[La cartella che vuoi ispezionare. Quella di default è Inbox, gli altri valori possibili sono: Junk, Trash, Draft, Sent.]], - en=[[The folder you want to interact with. Default is Inbox, other values are: Junk, Trash, Draft, Sent.]]} + {name = "view", description = { + it = [[ Viene usato per determinare la lista di messaggi da scaricare. I valori possibili sono All (tutti), Unread (non letti) e Flag.]], + en = [[ Parameter is used when getting the list of messages to +pull. It determines what messages to be pulled. Possible values are All, Unread and Flag.]] + } }, - {name = "emptytrash", description = { - it = [[ Viene usato per forzare il plugin a svuotare il cestino quando ha finito di scaricare i messaggi. Se il valore è 1 questo comportamento viene attivato.]], + {name = "keepmsgstatus", description = { en = [[ -Parameter is used to force the plugin to empty the trash when it is done -pulling messages. Set the value to 1.]] +Parameter is used to maintain the status of the message in the state it was before being pulling. If the value is 1, the behavior is turned on +and will override the markunread flag. ]] } }, - + {name = "domain", description = { + en = [[ +Parameter is used to override the domain in the email address. This is used so that users don't +need to add a mapping to config.lua for a hosted hotmail account. ]] + } + }, } PLUGIN_DESCRIPTIONS = { - it=[[ -Questo plugin vi permette di scaricare la posta da mailbox con dominio della famiglia di @fastmail.com. -Per usare questo plugin dovrete usare il vostro indirizzo email completo come -nome utente e la vostra vera password come password.]], en=[[ -This plugin lets you download mail from fastmail. -To use this plugin you have to use your full email address as the username -and your real password as the password. For support, please post a question to -the forum instead of emailing the author(s).]] +This is the webmail support for @fastmail.fm, @fmailbox.com and similar mailboxes. +To use this plugin you have to use your full email address as the user +name and your real password as the password.]] } -- ************************************************************************** -- @@ -66,66 +67,19 @@ -- ************************************************************************** -- local globals = { - -- Server URL - -- - strLoginUrl = "http://www.fmailbox.com/", - - -- Login strings - -- - strLoginPostData = "MLS=LN-*&FLN-UserName=%s&FLN-Password=%s&MSignal_LN-Authenticate*=Login&FLN-ScreenSize=-1", - strLoginFailed = "Login Failed - Invalid User name and/or password", - - -- Regular expression to extract the mail server - -- - strFormActionPat = 'here') - if (url ~= nil) then - body, err = browser:get_uri(url) + + local rc, str = sendCmd("login " .. username .. "@" .. domain .. " " .. password, nil) + if (rc ~= POPSERVER_ERR_OK or string.match(str, "OK User logged in") == nil) then + log.error_print("Login failed") + return POPSERVER_ERR_AUTH end - - -- Save the mail server, and some other things - -- - internalState.strMailServer = browser:wherearewe() - if (internalState.strMBox == globals.strInbox) then - internalState.strStatBodyCache = body + + rc, str = sendCmd("examine " .. internalState.strMBox, nil) + if (rc ~= POPSERVER_ERR_OK or string.match(str, "NO EXAMINE failure") ~= nil) then + log.error_print("Folder: " .. internalState.strMBox .. " is invalid.") + return POPSERVER_ERR_AUTH end - - -- Get the folder ID + + -- Return Success -- - local strPat = string.format(globals.strMBoxIDPat, internalState.strMBox) - str = string.match(body, strPat) - if str ~= nil then - internalState.strMBoxID = str - log.dbg("Fastmail - Mailbox (" .. internalState.strMBox .. ") ID: " .. str) - else - log.error_print("Can't figure out the mailbox id for: " .. internalState.strMBox) - log.raw("Can't figure out the mailbox id for: " .. internalState.strMBox .. ", body: " .. body) - return POPSERVER_ERR_UNKNOWN - end + return POPSERVER_ERR_OK +end - -- Get the Trash ID - -- - if internalState.bEmptyTrash then - strPat = string.format(globals.strMBoxIDPat, globals.strTrash) - str = string.match(body, strPat) - if str ~= nil then - internalState.strTrashID = str - log.dbg("Fastmail - Mailbox (" .. globals.strTrash .. ") ID: " .. str) - else - log.error_print("Can't figure out the mailbox id for: " .. globals.strTrash) - log.raw("Can't figure out the mailbox id for: " .. globals.strTrash .. ", body: " .. body) +function sendCmd(cmd, f) + internalState.cnt = internalState.cnt + 1 + cmd = internalState.cnt .. " " .. cmd + local rc + if internalState.socket ~= nil then + rc = internalState.socket:send(cmd) + else + tc = -1 + end + + if rc < 0 then + log.error_print("Short send of "..rc.. + " instead of "..string.len(cmd).."\n") + return POPSERVER_ERR_NETWORK + end + + local str = "" + local done = false + while (not done) do + local newstr = internalState.socket:recv() + if f then + f(newstr) + if (string.match(newstr, internalState.cnt .. " OK")) then + done = true + end + else + if (newstr == nil) then + str = "-ERR network error" + done = true + end + + if (done == false) then + if (string.match(newstr, internalState.cnt .. " OK") or + string.match(newstr, internalState.cnt .. " NO") or + string.match(newstr, internalState.cnt .. " BAD")) then + done = true + end + if (str ~= nil) then + str = str .. "\n" .. newstr + else + str = newstr + end + end end end - -- Get the session ID and the udm values - -- - local url = browser:whathaveweread() - str = string.match(url, globals.strUstPat) - if str ~= nil then - internalState.strUst = str - log.dbg("Fastmail - Ust value: " .. str) - else - log.error_print("Can't figure out the udm value") - log.raw("Can't figure out the udm value, body: " .. body) - return POPSERVER_ERR_UNKNOWN - end - - str = string.match(url, globals.strUdmPat) - if str ~= nil then - internalState.strUdm = str - log.dbg("Fastmail - Udm Value: " .. str) + if f then + return POPSERVER_ERR_OK, "" else - log.error_print("Can't figure out the udm value") - log.raw("Can't figure out the ust value, body: " .. body) - return POPSERVER_ERR_UNKNOWN + return POPSERVER_ERR_OK, str end - - -- DEBUG Message - -- - log.dbg("Fastmail - Server: " .. internalState.strMailServer .. "\n") - - -- Note that we have logged in successfully - -- - internalState.bLoginDone = true - - -- Debug info - -- - log.dbg("Created session for " .. - internalState.strUser .. "@" .. internalState.strDomain .. "\n") - - -- Return Success - -- - log.raw("Successful login") - return POPSERVER_ERR_OK end -- Download a single message @@ -369,15 +223,12 @@ -- Local Variables -- - local browser = internalState.browser local uidl = get_mailmessage_uidl(pstate, msg) - - local url = string.format(globals.strCmdMsgView, internalState.strMailServer, - uidl, uidl, internalState.strUst, uidl, internalState.strMBoxID, internalState.strUdm); + local msgid = internalState.msgids[uidl] -- Debug Message -- - log.dbg("Getting message: " .. uidl .. ", URL: " .. url) + log.dbg("Getting message: " .. uidl) -- Define a structure to pass between the callback calls -- @@ -393,63 +244,63 @@ -- Lines Received - Not really used for anything -- nLinesReceived = 0, + + -- data + -- + dataptr = data, + + -- uidl + -- + uidlptr = uidl } - -- Define the callback - -- - local cb = downloadMsg_cb(cbInfo, data) - - -- Start the download on the body - -- - local f, _ = browser:pipe_uri(url, cb) - if not f then - -- An empty message. Throw an error - -- - return POPSERVER_ERR_NETWORK + internalState.cbInfo = cbInfo + + local f = function(line) + if (string.match(line, "OK FETCH completed") or string.match(line, "^%)$") + or string.match(line, " FETCH %(")) then + return POPSERVER_ERR_OK + end + + local cbInfo = internalState.cbInfo + if (line == "") then + line = "X-FREEPOPS-UIDL: " .. cbInfo.uidlptr .. "\r\n" + end + line = cbInfo.strHack:dothack(line) .. "\r\n\0" + popserver_callback(line, cbInfo.dataptr) + return POPSERVER_ERR_OK end - + local cmd = " BODY[HEADER]" + if (internalState.bKeepMsgStatus) then + cmd = " BODY.PEEK[HEADER]" + end + local rc, _ = sendCmd("fetch " .. msgid .. cmd, f) + + local f = function(line) + if (string.match(line, "OK FETCH completed") or string.match(line, "^%)$") + or string.match(line, " FETCH %(")) then + return POPSERVER_ERR_OK + end + + local cbInfo = internalState.cbInfo + cbInfo.nLinesReceived = cbInfo.nLinesReceived + 1 + line = cbInfo.strHack:dothack(line) .. "\r\n\0" + if (cbInfo.nLinesReceived <= cbInfo.nLinesRequested or cbInfo.nLinesRequested < 0) then + popserver_callback(line, cbInfo.dataptr) + end + return POPSERVER_ERR_OK + end + cmd = " BODY[TEXT]" + if (internalState.bKeepMsgStatus) then + cmd = " BODY.PEEK[TEXT]" + end + if (nLines ~= 0) then + local rc, _ = sendCmd("fetch " .. msgid .. cmd, f) + end + + internalState.cbInfo = nil return POPSERVER_ERR_OK -end - --- Callback for the retr function --- -function downloadMsg_cb(cbInfo, data) - - return function(body, len) - -- Are we done with Top and should just ignore the chunks - -- - if (cbInfo.nLinesRequested ~= -2 and cbInfo.nLinesReceived == -1) then - return 0, nil - end - - -- Perform our "TOP" actions - -- - if (cbInfo.nLinesRequested ~= -2) then - body = cbInfo.strHack:tophack(body, cbInfo.nLinesRequested) - - -- Check to see if we are done and if so, update things - -- - if cbInfo.strHack:check_stop(cbInfo.nLinesRequested) then - cbInfo.nLinesReceived = -1; - if (string.sub(body, -2, -1) ~= "\r\n") then - body = body .. "\r\n" - end - else - cbInfo.nLinesReceived = cbInfo.nLinesRequested - - cbInfo.strHack:current_lines() - end - end - - -- End the strings properly - -- - body = cbInfo.strHack:dothack(body) .. "\0" - -- Send the data up the stream - -- - popserver_callback(body, data) - - return len, nil - end end -- ************************************************************************** -- @@ -464,48 +315,48 @@ local domain = freepops.get_domain(username) local user = freepops.get_name(username) - internalState.strDomain = domain internalState.strUser = user - -- If the flag emptyTrash is set to 1 , - -- the trash will be emptied on 'quit' + -- Override the domain variable if it is set in the login parameter -- - local val = (freepops.MODULE_ARGS or {}).emptytrash or 0 - if val == "1" then - log.dbg("Fastmail: Trash folder will be emptied on exit.") - internalState.bEmptyTrash = true + local val = (freepops.MODULE_ARGS or {}).domain or nil + if val ~= nil then + log.dbg("Fastmail: Using overridden domain: " .. val) + internalState.strDomain = val + else + internalState.strDomain = domain end -- Get the folder -- - local mbox = (freepops.MODULE_ARGS or {}).folder - if mbox == nil then - internalState.strMBox = globals.strInbox - return POPSERVER_ERR_OK - end + local mbox = (freepops.MODULE_ARGS or {}).folder or globals.strInbox + mbox = string.gsub(mbox, " ", "+") + internalState.strMBox = "INBOX." .. mbox - local start = string.match(mbox, globals.strSentPat) - if start ~= nil then - internalState.strMBox = globals.strSent - return POPSERVER_ERR_OK - end - - start = string.match(mbox, globals.strTrashPat) - if start ~= nil then - internalState.strMBox = globals.strTrash - return POPSERVER_ERR_OK + -- Get the view to use in STAT (ALL, UNREAD or FLAG) + -- + local strView = (freepops.MODULE_ARGS or {}).view or "All" + local str = string.match(strView, globals.strViewAllPat) + if str ~= nil then + internalState.strView = globals.strViewAll + else + str = string.match(strView, globals.strViewUnreadPat) + if str ~= nil then + internalState.strView = globals.strViewUnread + else + internalState.strView = globals.strViewFlagged + end end - - start = string.match(mbox, globals.strDraftPat) - if start ~= nil then - internalState.strMBox = globals.strDraft - return POPSERVER_ERR_OK + + -- If the flag keepmsgstatus=1 is set, then we won't touch the status of + -- messages that we pull. + -- + val = (freepops.MODULE_ARGS or {}).keepmsgstatus or 0 + if val == "1" then + log.dbg("Fastmail: All messages pulled will have its status left alone.") + internalState.bKeepMsgStatus = true end - -- Defaulting to the inbox - -- - log.say("Fastmail: Custom folder selected: " .. mbox .. ".\n") - internalState.strMBox = mbox return POPSERVER_ERR_OK end @@ -515,56 +366,12 @@ -- Store the password -- internalState.strPassword = password - - -- Get a session - -- - local sessID = session.load_lock(hash()) - - -- See if we already have a session. We want to prevent - -- multiple sessions for a given account - -- - if sessID ~= nil then - -- Session exists - -- This code is copied from example. It doesn't make sense to me. - -- - - -- Check to see if it is locked - -- Why "\a"? - -- - if sessID == "\a" then - log.dbg("Error: Session locked - Account: " .. internalState.strUser .. - "@" .. internalState.strDomain .. "\n") - return POPSERVER_ERR_LOCKED - end - - -- Load the session which looks to be a function pointer - -- - local func, err = loadstring(sessID) - if not func then - log.error_print("Unable to load saved session (Account: " .. - internalState.strUser .. "@" .. internalState.strDomain .. "): ".. err) - return login() - end - - log.dbg("Session loaded - Account: " .. internalState.strUser .. - "@" .. internalState.strDomain .. "\n") - - -- Execute the function saved in the session - -- - func() - - return POPSERVER_ERR_OK - else - -- Create a new session by logging in - -- - return login() - end + return login() end -- Quit abruptly -- function quit(pstate) - session.unlock(hash()) return POPSERVER_ERR_OK end @@ -580,72 +387,34 @@ -- Local Variables -- - local browser = internalState.browser - local cmdUrl = string.format(globals.strCmdDelete, internalState.strMailServer, internalState.strUst, - internalState.strUdm) local cnt = get_popstate_nummesg(pstate) - local dcnt = 0 - local postBase = string.format(globals.strCmdDeletePost, internalState.strMBoxID, internalState.strMBoxID) - local post = postBase -- Cycle through the messages and see if we need to delete any of them -- for i = 1, cnt do if get_mailmessage_flag(pstate, i, MAILMESSAGE_DELETE) then - post = post .. "&" .. "FMB-MF-R-" .. get_mailmessage_uidl(pstate, i) .. "-Sel=on" - dcnt = dcnt + 1 - - -- Send out in a batch of 5 - -- - if math.fmod(dcnt, 5) == 0 then - log.dbg("Sending Delete URL: " .. cmdUrl .. "Post Data: " .. post .. "\n") - local body, err = browser:post_uri(cmdUrl, post) - if not body or err then - log.error_print("Unable to delete messages.\n") - end - - -- Reset the variables - -- - dcnt = 0 - post = postBase - end - end - end - - -- Send whatever is left over - -- - if dcnt > 0 and dcnt < 5 then - log.dbg("Sending Delete URL: " .. cmdUrl .. "Post Data: " .. post .. "\n") - local body, err = browser:post_uri(cmdUrl, post) - if not body or err then - log.error_print("Unable to delete messages.\n") - end - end - - -- Empty the trash - -- - if internalState.bEmptyTrash then - if internalState.strCrumb ~= '' then - cmdUrl = string.format(globals.strCmdEmptyTrash, internalState.strMailServer, internalState.strUst, - internalState.strMBoxID, internalState.strUdm, internalState.strTrashID) - log.dbg("Sending Empty Trash URL: " .. cmdUrl .."\n") - local body, err = browser:get_uri(cmdUrl) - if not body or err then - log.error_print("Error when trying to empty the trash with url: ".. cmdUrl .."\n") - end - else - log.error_print("Cannot empty trash - crumb not found\n") + local uidl = get_mailmessage_uidl(pstate, i) + local msgid = internalState.msgids[uidl] + -- Copy the message to the trash + -- + local rc, str = sendCmd("copy " .. msgid .. " " .. globals.strTrash, nil) + + if (string.match(str, "OK ")) then + -- Mark it as deleted + -- + local rc, str = sendCmd("store " .. msgid .. [[ +FLAGS \Deleted ]], nil) + log.dbg("Marking message: " .. uidl .. " as deleted") + else + log.error_print("Delete operation failed. Unknown trash folder name.") + return POPSERVER_ERR_UNKNOWN + end end end - -- Save and then Free up the session + -- Logout -- - session.save(hash(), serialize_state(), session.OVERWRITE) - session.unlock(hash()) - - log.dbg("Session saved - Account: " .. internalState.strUser .. - "@" .. internalState.strDomain .. "\n") - + local rc, str = sendCmd("logout", nil) + return POPSERVER_ERR_OK end @@ -658,197 +427,51 @@ if internalState.bStatDone then return POPSERVER_ERR_OK end - - -- Local variables - -- - local browser = internalState.browser - local nPage = 1 - local nMsgs = 0 - local nTotMsgs = 0; - local firstUrl = string.format(globals.strCmdMsgList, internalState.strMailServer, - internalState.strUst, internalState.strMBoxID, internalState.strUdm, internalState.strMBoxID); - local cmdUrl = firstUrl - local nextUrl = string.format(globals.strCmdMsgListNextPage, internalState.strMailServer, - internalState.strUst, internalState.strMBoxID, internalState.strUdm, internalState.strMBoxID); - - -- Debug Message + internalState.bStatDone = true + + -- Initialize the state -- - log.dbg("Stat URL: " .. cmdUrl .. "\n"); - - -- Initialize our state - -- - set_popstate_nummesg(pstate, nMsgs) - - -- Local function to process the list of messages, getting id's and sizes - -- - local function funcProcess(body) - -- Find out if there are any messages - -- - local nomesg = string.match(body, globals.strMsgListNoMsgPat) - if (nomesg ~= nil) then - return true, nil - end + set_popstate_nummesg(pstate, 0) - -- Tokenize out the message ID and size for each item in the list - -- - local items = mlex.match(body, globals.strMsgLineLitPattern, globals.strMsgLineAbsPattern) - log.dbg("Stat Count: " .. items:count()) - - -- Remember the count - -- - local cnt = items:count() - if cnt == 0 then - return true, nil - end - - -- Cycle through the items and store the msg id and size - -- - for i = 1, cnt do - local size = items:get(0, i - 1) - local uidl = items:get(1, i - 1) - - if not uidl or not size then - log.say("Fastmail Module needs to fix it's individual message list pattern matching.\n") - return nil, "Unable to parse the size and uidl from the html" - end - - -- Get the message id. It's in the format of "MSG[numbers].[number(s)]". - -- - uidl = string.match(uidl, 'MSignal=MR%-%*%*([^"]+)"') - - -- Convert the size from it's string (4KB or 2MB) to bytes - -- First figure out the unit (KB or just B) - -- - local kbUnit = string.match(size, "([Kk])") - size = string.match(size, "([%d]+)[KkMm]") - if not kbUnit then - size = math.max(tonumber(size), 0) * 1024 * 1024 - else - size = math.max(tonumber(size), 0) * 1024 - end - - -- Save the information - -- - nMsgs = nMsgs + 1 - log.dbg("Processed STAT - Msg: " .. nMsgs .. ", UIDL: " .. uidl .. ", Size: " .. size) - set_popstate_nummesg(pstate, nMsgs) - set_mailmessage_size(pstate, nMsgs, size) - set_mailmessage_uidl(pstate, nMsgs, uidl) - end - - -- We are done with this page, increment the counter - -- - nPage = nPage + 1 - - return true, nil - end - - -- Local Function to check for more pages of messages. If found, the - -- change the command url + -- Select the folder -- - local function funcCheckForMorePages(body) - -- See if there are messages remaining - -- - if nMsgs < nTotMsgs then - cmdUrl = firstUrl - if (nPage > 1) then - cmdUrl = nextUrl .. (nPage - 1) - end - return false - end - return true + local rc, str = sendCmd("select " .. internalState.strMBox, nil) + if (rc ~= POPSERVER_ERR_OK) then + log.error_print("Error Received selecting folder: " .. str .. "\n") + return POPSERVER_ERR_NETWORK end - -- Local Function to get the list of messages - -- - local function funcGetPage() - -- Debug Message - -- - log.dbg("Debug - Getting page: ".. cmdUrl) - - -- Get the page and check to see if we got results - -- - local body, err - if (internalState.strStatBodyCache ~= nil and internalState.strMBox == globals.strInbox) then - body = internalState.strStatBodyCache - internalState.strStatBodyCache = nil - else - body, err = browser:get_uri(cmdUrl) - if body == nil then - return body, err - end + local f = function(l) + internalState.nTotMsgs = internalState.nTotMsgs + 1 + if (string.match(l, "\Deleted")) then + log.dbg("Found a deleted message. Ignoring!") + return POPSERVER_ERR_OK + end + if (internalState.strView == globals.strViewUnread and + string.match(l, globals.strViewUnread) ~= nil) then + return POPSERVER_ERR_OK end - - -- Is the session expired - -- - local strSessExpr = string.match(body, globals.strRetLoginSessionExpired) - if strSessExpr == nil then - -- Invalidate the session - -- - internalState.bLoginDone = nil - session.remove(hash()) - log.raw("Session Expired - Last page loaded: " .. cmdUrl .. ", Body: " .. body) - - -- Try Logging back in - -- - local status = login() - if status ~= POPSERVER_ERR_OK then - return nil, "Session expired. Unable to recover" - end - - -- Reset the local variables - -- - browser = internalState.browser - cmdUrl = firstUrl - if nPage > 1 then - cmdUrl = nextUrl .. (nPage - 1) - end - - -- Retry to load the page - -- - browser:get_uri(cmdUrl) + if (internalState.strView == globals.strViewFlagged and + string.match(l, globals.strViewFlagged) == nil) then + return POPSERVER_ERR_OK end - - -- Get the total number of messages - -- - if nTotMsgs == 0 then - local strTotMsgs = string.match(body, globals.strMsgListCntPattern) - if strTotMsgs == nil then - nTotMsgs = 0 - else - nTotMsgs = tonumber(strTotMsgs) - end - log.dbg("Total messages in message list: " .. nTotMsgs) - end - - return body, err - end - - - -- Run through the pages and pull out all the message pieces from - -- all the message lists - -- - if not support.do_until(funcGetPage, funcCheckForMorePages, funcProcess) then - log.error_print("STAT Failed.\n") - session.remove(hash()) - log.raw("Session removed (STAT Failure) - Account: " .. internalState.strUser .. - "@" .. internalState.strDomain) - return POPSERVER_ERR_NETWORK - end - - -- Update our state - -- - internalState.bStatDone = true - -- Check to see that we completed successfully. If not, return a network - -- error. This is the safest way to let the email client now that there is - -- a problem but that it shouldn't drop the list of known uidls. - if (nMsgs < nTotMsgs) then - return POPSERVER_ERR_NETWORK + local nMsgs = internalState.nMsgs + local size, uidl = string.match(l, "UID (%d+) RFC822.SIZE (%d+)") + if (size ~= nil and uidl ~= nil) then + nMsgs = nMsgs + 1 + log.dbg("Processed STAT - Msg: " .. nMsgs .. ", UIDL: " .. uidl .. ", Size: " .. size) + set_popstate_nummesg(pstate, nMsgs) + set_mailmessage_size(pstate, nMsgs, size) + set_mailmessage_uidl(pstate, nMsgs, tostring(uidl)) + internalState.msgids[uidl] = internalState.nTotMsgs + end + internalState.nMsgs = nMsgs + return POPSERVER_ERR_OK end - - -- Return that we succeeded - -- + + local rc, _ = sendCmd("fetch 1:* (flags uid RFC822.SIZE)", f) + return POPSERVER_ERR_OK end @@ -921,14 +544,6 @@ -- Load dependencies -- - - -- Serialization - -- - require("serial") - - -- Browser - -- - require("browser") -- MIME Parser/Generator -- @@ -937,7 +552,11 @@ -- Common module -- require("common") - + + -- Common module + -- + require("psock") + -- Run a sanity check -- freepops.set_sanity_checks() --- freepops-0.2.9.orig/src/lua/yahoo.lua +++ freepops-0.2.9/src/lua/yahoo.lua @@ -1,30 +1,21 @@ -- ************************************************************************** -- --- FreePOPs @yahoo.com webmail interface +-- FreePOPs @yahoo webmail interface -- -- Released under the GNU/GPL license -- Written by Russell Schwager --- yahoo.it added by Nicola Cocchiaro --- yahoo.ie added by Bruce Williamson --- Contributions by Przemyslaw Wroblewski --- Contributions from Kevin Edwards -- ************************************************************************** -- -PLUGIN_VERSION = "0.2.20081116" -PLUGIN_NAME = "yahoo.com" -PLUGIN_REQUIRE_VERSION = "0.2.8" +-- Globals +-- +PLUGIN_VERSION = "0.3.20091013" +PLUGIN_NAME = "yahoo.lua" +PLUGIN_REQUIRE_VERSION = "0.2.0" PLUGIN_LICENSE = "GNU/GPL" -PLUGIN_URL = "http://www.freepops.org/download.php?module=yahoo.lua" -PLUGIN_HOMEPAGE = "http://www.freepops.org/" -PLUGIN_AUTHORS_NAMES = {"Russell Schwager","Nicola Cocchiaro"} -PLUGIN_AUTHORS_CONTACTS = - {"russell822 (at) yahoo (.) com", - "ncocchiaro (at) users (.) sourceforge (.) net"} -PLUGIN_DOMAINS = {"@yahoo.com", "@yahoo.ie", "@yahoo.it", "@yahoo.ca", "@rocketmail.com", "@yahoo.com.ar", - "@yahoo.co.in", "@yahoo.co.id", "@yahoo.com.tw", "@yahoo.co.uk", "@yahoo.com.cn", - "@yahoo.es", "@yahoo.de", "@talk21.com", "@btinternet.com", "@yahoo.com.au", "@yahoo.co.nz", - "@ymail.com", "@yahoo.in" -} - +PLUGIN_URL = "http://freepops.sourceforge.net/download.php?module=yahoo.lua" +PLUGIN_HOMEPAGE = "http://freepops.sourceforge.net/" +PLUGIN_AUTHORS_NAMES = {"Russell Schwager"} +PLUGIN_AUTHORS_CONTACTS = {"russell822 (at) yahoo (.) com"} +PLUGIN_DOMAINS = {"@yahoo.com"} PLUGIN_PARAMETERS = { {name = "folder", description = { it = [[ @@ -52,18 +43,6 @@ pull. It determines what messages to be pulled. Possible values are All, Unread and Flag.]] } }, - {name = "markunread", description = { - it = [[ Viene usato per far sì che il plugin segni come non letti i messaggi che scarica. Se il valore è 1 questo comportamento viene attivato.]], - en = [[ Parameter is used to have the plugin mark all messages that it -pulls as unread. If the value is 1, the behavior is turned on.]] - } - }, - {name = "nossl", description = { - it = [[ Viene usato per forzare il modulo a fare login con HTTP semplice e non HTTPS con SSL. Se il valore è 1 questo comportamento viene attivato.]], - en = [[ Parameter is used to force the module to login through plain -HTTP and not HTTPS with SSL. If the value is 1, the SSL is not used.]] - } - }, {name = "emptytrash", description = { it = [[ Viene usato per forzare il plugin a svuotare il cestino quando ha finito di scaricare i messaggi. Se il valore è 1 questo comportamento viene attivato.]], en = [[ @@ -78,31 +57,19 @@ pulling messages. Set the value to 1.]] } }, - {name = "maxmsgs", description = { - en = [[ -Parameter is used to force the plugin to only download a maximum number of messages. ]] - } - }, {name = "keepmsgstatus", description = { en = [[ Parameter is used to maintain the status of the message in the state it was before being pulling. If the value is 1, the behavior is turned on and will override the markunread flag. ]] } }, - {name = "useeventlib", description = { - en = [[ -Parameter is used to turn on windows event library logging. If the value is 1, -the behavior is turned on. ]] - } - }, {name = "domain", description = { en = [[ Parameter is used to override the domain in the email address. This is used so that users don't need to add a mapping to config.lua for a hosted hotmail account. ]] - } - }, + } + }, } - PLUGIN_DESCRIPTIONS = { it=[[ Questo plugin vi per mette di leggere le mail che avete in una @@ -120,179 +87,19 @@ -- ************************************************************************** -- local globals = { - -- Login strings - -- - strMailPage = "http://mail.yahoo.com", - strLoginPage = "http://login.yahoo.com", - strLoginHTTP = "http://login.yahoo.com/config/login", - strLoginHTTPs = "https://login.yahoo.com/config/login", - strLoginPostData = ".tries=1&.src=ym&.intl=%s&login=%s&passwd=%s&.persistent=y&.v=0&.chkP=Y&.u=%s", - strLoginPostDataMD5 = ".tries=1&.src=ym&.intl=%s&login=%s&passwd=%s&.hash=1".. - "&.md5=1&.js=1&.challenge=%s&.persistent=y&.v=0&.chkP=Y&.u=%s", - strLoginFailed = "Login Failed - Invalid User name and password", - strLoginChallenge = 'name="%.challenge" value="([^"]-)"', - strLoginU = 'name="%.u" value="([^"]-)"', - - -- Expressions to pull out of returned HTML from Yahoo corresponding to a problem - -- - strRetLoginBadPassword = "(login_form)", - strRetLoginSessionExpired = "(error code: Login)", - - -- Regular expression to extract the mail server - -- - - -- Get the mail server for Yahoo - -- - strRegExpMailServer = '(http://[^/]+/)([my][mc])/', - - -- Redirect site on login - -- - strRegExpMetarefresh = 'window.location.replace%("([^"]*)"', - - -- Get the html corresponding only to the message list - -- - strMsgListHTMLPattern = '(.*).*
', - - -- Get the crumb value that is needed for deleting messages and emptying the trash - -- - strRegExpCrumb = '', - - -- Delete Form hidden items - -- - strHiddenItems = '', - strDeletePostPat = '', - - -- Mark unread url - -- - strMsgMarkUnreadPat = '
', - - -- Pattern to determine if we have no messages. If this is found, we have messages. - -- - strMsgListNoMsgPat = "()", - - -- Pattern to determine if we have no messages with 'mc'. If found, there is no messages. - -- - strMsgListNoMsgPatMC = '(modulecontainer filled nomessages)', - - -- Used by Stat to pull out the message ID and the size - -- - strMsgLineLitPattern = ".*[.*]{div}[.*]{h2}.*.*[.*]{/h2}[.*]{/div}.*.*.*.*.*.*", - strMsgLineAbsPattern = "O[O]{O}[O]{O}OO[O]{O}[O]{O}OOOOXO", - - strMCUnreadPattern = '[^<]+]+>= 0) then -- and getmetatable(val) == nil then - local tmp = {} - table.foreach( t, - function (k,v) - table.insert(tmp, tostr(k, depth-1) .. "=" .. repr(v, depth-1)) - end - ) - result = "{" .. table.concat(tmp,", ") .. "}" - else - result = tostring(t) - end - return result -end - --- Create a literal string representation of the given object -local repr_map = { - ["table"] = table_to_string - ,["string"] = quote_string - ,["nil"] = get_nil_string - ,["number"] = tostring - ,["boolean"] = tostring - ,["default"] = tostring -} - -local repr_max_depth=2 -function repr( val, depth ) - local val_type = type(val) - local func - depth = depth or repr_max_depth - func = repr_map[val_type] or repr_map["default"] - return func(val, depth) -end - --- Convert any object to a string --- Unlike repr, tostr is idempotent and does not add double quotes to a string. -function tostr( val ) - if type(val) == "string" then - return val - end - return repr(val) -end - - - --- ************************************************************************** -- --- CRLF string functions --- ************************************************************************** -- - --- Returns "data" with "{LF}" prefixing all \n and "{CR}" prefixing all \r, --- so hex viewing for those bytes isn't necessary. --- -function showCRLF( data ) - local str = data - if str then - str = string.gsub(str, "\n", "{LF}\n") - str = string.gsub(str, "\r", "{CR}\r") - end - return str -end - --- Returns a new string with all single \r and \n replaced by \r\n -function fixCRLF( str ) - if str then - -- temporarily convert proper ending to \n - str = string.gsub(str, "\r\n", "\n") - str = string.gsub(str, "\r", "\n") -- should we worry about embedded \r? - str = string.gsub(str, "\n", "\r\n") - - -- this alternative is actually a bit slower: --- str = string.gsub(str, "([^\r]-)\n", "%1\r\n") - end - return str -end - - - --- ************************************************************************** -- --- smartlog functions --- ************************************************************************** -- - --- ************************************************************************** -- --- Helper functions --- ************************************************************************** -- - --- Serialize the state --- --- serial. serialize is not enough powerfull to correcly serialize the --- internal state. the problem is the field b. b is an object. this means --- that is a table (and no problem for this) that has some field that are --- pointers to functions. this is the problem. there is no easy way for the --- serial module to know how to serialize this. so we call b:serialize --- method by hand hacking a bit on names --- -function serialize_state() - internalState.bStatDone = false; - if (internalState.bUseWel) then - return serial.serialize("internalState", internalState) .. - internalState.browser:serialize("internalState.browser") .. - internalState.logger:serialize("internalState.logger") - end - return serial.serialize("internalState", internalState) .. - internalState.browser:serialize("internalState.browser") -end - --- Computes the hash of our state. Concate the user, domain, mailbox and password --- -function hash() - return (internalState.strUser or "") .. "~" .. - (internalState.strDomain or "") .. "~" .. - (internalState.strMBox or "") .. "~" .. - (internalState.strView or "") .. "~" .. - internalState.strPassword -- this asserts strPassword ~= nil -end - --- Check to see if the GUI is the new one --- -function checkForNewGUI(browser, body) - local server = string.match(browser:whathaveweread(), globals.strRegExpMailServerNew) - if (server ~= nil) then - log.dbg("Detected New Version of the Yahoo interface!", browser:whathaveweread()) - log.dbg("Yahoo Mail Server: " .. server) - - internalState.strMailServer = server - internalState.bNewGUI = true - return true - end - - return false -end - --- Issue the command to login to Yahoo --- -function loginYahoo() - -- Check to see if we've already logged in - -- - - log.dbg( "Entering loginYahoo()" ) - - if internalState.loginDone then - log.dbg( "internalState.loginDone" ) - return POPSERVER_ERR_OK - end - - -- Create a browser to do the dirty work (It must be set to IE 6.0) - -- - internalState.browser = browser.new("Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_2; en) AppleWebKit/525.9 (KHTML, like Gecko) Version/3.1 Safari/525.9") - --browser.new("Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; {02ABE9F9-C33D-95EA-0C84-0B70CD0AC3F8}; .NET CLR 1.1.4322)") --- internalState.browser = browser.new("Mozilla/4.0 (compatible; U; en)") --- internalState.browser = browser.new("Mozilla/3.0 (U; en)") --- internalState.browser = browser.new("FreePOPs/2.5 (U; en)") - local SSLEnabled = browser.ssl_enabled() - - -- Create the windows event logger - if (internalState.bUseWel) then - -- Windows event smartlog - -- - require("wel") - internalState.logger = wel.new('FreePOPs','yahoo') - end - - -- Define some local variables - -- - local username = internalState.strUser - local password = internalState.strPassword - local domain = internalState.strDomain - local intFlag = internalState.strIntFlag - local url = globals.strLoginHTTP - local browser = internalState.browser - local post - local challengeCode, uVal - - -- Add the domain always - -- - username = username .. "@" .. domain - - if internalState.bNoSSL == true then - log.dbg("Yahoo: SSL login will not be used.") - SSLEnabled = false - end - - if SSLEnabled then - url = globals.strLoginHTTPs - browser:ssl_init_stuff() - end - - -- Login to Yahoo - -- - log.dbg( "login get: " .. globals.strLoginPage ) - local body, err = browser:get_uri(globals.strLoginPage) - log.dbg( "login response: err=" .. tostr(err), smartlog.dbg_limit(body) ) - - if body ~= nil then - challengeCode = string.match(body, globals.strLoginChallenge) - uVal = string.match(body, globals.strLoginU) - end - - if (uVal == nil) then - uVal = "" - end - - if challengeCode ~= nil then - password = crypto.bin2hex(crypto.md5(password)) - password = crypto.bin2hex(crypto.md5(password .. challengeCode)) - post = string.format(globals.strLoginPostDataMD5, intFlag, username, - password, challengeCode, uVal) - else -- if we didn't get the challenge code, then login in cleartext - post = string.format(globals.strLoginPostData, intFlag, username, password, uVal) - end - - log.dbg( "login challenge post: \nurl=" .. url .. " \npost=" .. post ) - body, err = browser:post_uri(url, post) - log.dbg( "login challenge response: err=" .. tostr(err), smartlog.dbg_limit(body) ) - - -- Check for redirect - -- - local str = string.match(body, globals.strRedirectNew) - if (str ~= nil) then - log.dbg( "login redirect get: " .. str ) - body, err = browser:get_uri(str) - log.dbg( "login redirect response: err=" .. tostr(err), smartlog.dbg_limit(body) ) - end - - -- Check for interstitial page (advertisements) - -- - url = browser:whathaveweread() - log.dbg("browser:whathaveweread()=" .. url) - str = string.match( url, '(http://.-interstitial.-/)[^/]*' ) - if (str ~= nil) then - local str2 = string.match(body, '