@ -33,6 +33,7 @@ local OTAManager = {
" stable " ,
" nightly " ,
} ,
link_template = " koreader-%s-latest-%s " ,
zsync_template = " koreader-%s-latest-%s.zsync " ,
installed_package = ota_dir .. " koreader.installed.tar " ,
package_indexfile = " ota/package.index " ,
@ -79,6 +80,8 @@ function OTAManager:getOTAModel()
return " android-x86 "
end
return " android "
elseif Device : isSDL ( ) then
return " appimage "
elseif Device : isCervantes ( ) then
return " cervantes "
elseif Device : isKindle ( ) then
@ -102,6 +105,18 @@ function OTAManager:getOTAModel()
end
end
function OTAManager : getOTAType ( )
local ota_model = self : getOTAModel ( )
if ota_model == " " then return end
if ota_model : find ( " android " ) or ota_model : find ( " appimage " ) then
return " link "
end
return " ota "
end
function OTAManager : getOTAServer ( )
return G_reader_settings : readSetting ( " ota_server " ) or self.ota_servers [ 1 ]
end
@ -120,6 +135,10 @@ function OTAManager:setOTAChannel(channel)
G_reader_settings : saveSetting ( " ota_channel " , channel )
end
function OTAManager : getLinkFilename ( )
return self.link_template : format ( self : getOTAModel ( ) , self : getOTAChannel ( ) )
end
function OTAManager : getZsyncFilename ( )
return self.zsync_template : format ( self : getOTAModel ( ) , self : getOTAChannel ( ) )
end
@ -128,27 +147,39 @@ function OTAManager:checkUpdate()
local http = require ( " socket.http " )
local ltn12 = require ( " ltn12 " )
local zsync_file = self : getZsyncFilename ( )
local ota_zsync_file = self : getOTAServer ( ) .. zsync_file
local local_zsync_file = ota_dir .. zsync_file
local update_file = ( self : getOTAType ( ) == " link " ) and self : getLinkFilename ( ) or self : getZsyncFilename ( )
local ota_update_file = self : getOTAServer ( ) .. update_file
local local_update_file = ota_dir .. update_file
-- download zsync file from OTA server
logger.dbg ( " downloading zsync file" , ota_zsync _file)
logger.dbg ( " downloading update file" , ota_update _file)
local _ , c , _ = http.request {
url = ota_ zsync _file,
sink = ltn12.sink . file ( io.open ( local_ zsync _file, " w " ) ) }
url = ota_ update _file,
sink = ltn12.sink . file ( io.open ( local_ update _file, " w " ) ) }
if c ~= 200 then
logger.warn ( " cannot find zsync file" , c )
logger.warn ( " cannot find update file" , c )
return
end
-- parse OTA package version
local ota_package = nil
local zsync = io.open ( local_zsync_file , " r " )
if zsync then
for line in zsync : lines ( ) do
local link , ota_package
local update_info = io.open ( local_update_file , " r " )
if update_info then
if OTAManager : getOTAType ( ) == " link " then
local i = 0
for line in update_info : lines ( ) do
i = i + 1
if i == 1 then
ota_package = line
link = self : getOTAServer ( ) .. ota_package
end
end
else
for line in update_info : lines ( ) do
ota_package = line : match ( " ^Filename:%s*(.-)%s*$ " )
if ota_package then break end
end
zsync : close ( )
end
update_info : close ( )
end
local local_ok , local_version = pcall ( function ( )
local rev = Version : getCurrentRevision ( )
@ -161,14 +192,15 @@ function OTAManager:checkUpdate()
-- larger than the local package version
if local_ok and ota_ok and ota_version and local_version and
ota_version ~= local_version then
return ota_version , local_version
return ota_version , local_version , link
elseif ota_version and ota_version == local_version then
return 0
end
end
function OTAManager : fetchAndProcessUpdate ( )
local ota_version , local_version = OTAManager : checkUpdate ( )
local ota_version , local_version , link = OTAManager : checkUpdate ( )
if ota_version == 0 then
UIManager : show ( InfoMessage : new {
text = _ ( " KOReader is up to date. " ) ,
@ -176,9 +208,24 @@ function OTAManager:fetchAndProcessUpdate()
elseif ota_version == nil then
local channel = ota_channels [ OTAManager : getOTAChannel ( ) ]
UIManager : show ( InfoMessage : new {
text = T ( _ ( " OTA package is not available on %1 channel." ) , channel ) ,
text = T ( _ ( " Update information not available on %1 channel." ) , channel ) ,
} )
elseif ota_version then
if OTAManager : getOTAType ( ) == " link " then
UIManager : show ( ConfirmBox : new {
text = T (
_ ( " Do you want to update? \n Installed version: %1 \n Available version: %2 " ) ,
local_version ,
ota_version
) ,
ok_text = _ ( " Update " ) ,
ok_callback = function ( )
if Device : isSDL ( ) then
os.execute ( " xdg-open ' " .. link .. " ' " )
end
end
} )
else
UIManager : show ( ConfirmBox : new {
text = T (
_ ( " Do you want to update? \n Installed version: %1 \n Available version: %2 " ) ,
@ -251,6 +298,7 @@ function OTAManager:fetchAndProcessUpdate()
} )
end
end
end
function OTAManager : _buildLocalPackage ( )
-- TODO: validate the installed package?
@ -262,20 +310,16 @@ function OTAManager:_buildLocalPackage()
logger.err ( " Missing ota metadata: " , self.package_indexfile )
return nil
end
if Device : isAndroid ( ) then
return os.execute ( string.format (
" ./tar --no-recursion -cf %s -T %s " ,
self.installed_package , self.package_indexfile ) )
else
-- With visual feedback if supported...
if self.can_pretty_print then
os.execute ( " ./fbink -q -y -7 -pmh 'Preparing local OTA package' " )
-- We need a vague idea of how much space the tarball we're creating will take to compute a proper percentage...
-- Get the size from the latest zsync package, which'll be a closer match than anything else we might come up with.
local zsync _file = self : getZsyncFilename ( )
local local_zsync_file = ota_dir .. zsync _file
local update _file = self : getZsyncFilename ( )
local local_update_file = ota_dir .. update _file
local tarball_size = nil
local zsync = io.open ( local_ zsync _file, " r " )
local zsync = io.open ( local_ update _file, " r " )
if zsync then
for line in zsync : lines ( ) do
tarball_size = line : match ( " ^Length: (%d*)$ " )
@ -301,7 +345,6 @@ function OTAManager:_buildLocalPackage()
self.installed_package , self.package_indexfile ) )
end
end
end
function OTAManager : zsync ( full_dl )
if full_dl or self : _buildLocalPackage ( ) == 0 then
@ -362,7 +405,14 @@ end
function OTAManager : getOTAMenuTable ( )
return {
text = _ ( " OTA update " ) ,
text = _ ( " Update " ) ,
hold_callback = function ( )
if not NetworkMgr : isOnline ( ) then
NetworkMgr : promptWifiOn ( )
else
OTAManager : fetchAndProcessUpdate ( )
end
end ,
sub_item_table = {
{
text = _ ( " Check for update " ) ,
@ -378,11 +428,11 @@ function OTAManager:getOTAMenuTable()
text = _ ( " Settings " ) ,
sub_item_table = {
{
text = _ ( " OTA server" ) ,
text = _ ( " Update server" ) ,
sub_item_table = self : genServerList ( )
} ,
{
text = _ ( " OTA channel" ) ,
text = _ ( " Update channel" ) ,
sub_item_table = self : genChannelList ( )
} ,
}