/lurk.hws (c90b6de510cd88c3e449aa3bbfe05bc255ec017a) (6136 bytes) (mode 100755) (type blob)


Const #LURK_LISTVIEW = "foundfeeds"

lurk = {PleaseStop=True}
;č jako v celé té appce i zde se pevně zavážeme 
;č na struktury grafického rozhraní a jejich metody,
;č na MUI Royale. 
;č předělávání nás tedy bude bolet... 


Function lurk:set_status(s$)
	mui.Set("lurkstatus", "Contents", s$)
EndFunction

Function lurk:Replay(err_code, msg$) 
	self:set_status(
			IIf(err_code = #ERR_NONE, msg$, "\27b" .. GetErrorName(err_code)))
EndFunction 

;č tohle nejde udělat jako method - 
;č volající kód by asi musel ho i správně volat
Function lurk_callback(t)
	If t.Action = #DOWNLOADFILE_STATUS
		lurk:set_status(t.Count .. "/" .. t.Total .. " read from " .. t.UserData)
		CheckEvents() ; keep MUI responsive
		Return(lurk.PleaseStop)
	EndIf
EndFunction


;č stáhnout soubor
Function lurk:Explore(url$)
	self:Clear()
	url$ = StripStr(url$)
	self.PleaseStop = False
	;č zjednodušená kontrola, pokud řetězec obsahuje procenta,
	;č považujeme ho za "eskejpnutý".
	;č Na případ, kdy uživatel strčí do URLu osamělý znak procenta vysereme 
	;FindStr(s$, "%") <> -1
	Local err_code, html$, count = ?DownloadFile(url$, 
			{Adapter="hurl", Fail404=True, Encoded=FindStr(url$, "%", True) <> -1},
			lurk_callback, url$)
	If self.PleaseStop
		self:set_status("interrupted")
		Return()
	EndIf
	
	;č zde nepředpokládám, že by někdo jiný mohl spustit parser znovu.
	;č O to je to jednodušší. 
	If err_code = #ERR_NONE 
		
		Local ok, n = ValidateStr(html$)
		Local encoding = IIf(ok, #ENCODING_UTF8, #ENCODING_ISO8859_1)
		Local headpos = FindStr(html$, "<head", False, 0, encoding)
		If headpos < 0
			self:set_status("\27bNothing found") ;č hlavně ta hlavička..
			Return()
		Else
			self:set_status(count .. " bytes from " .. url$ .. " transmitted") 
		
			Local p = XMLParser.New({StartElement = lurkStartElement})
			p:setbase(url$)
			
			p:setencoding(IIf(ok, "UTF-8", "ISO-8859-1"))
			;č ten parser trefí šlak, uvidí-li CO má zpracovat 
			p:Parse(UnrightStr(html$, headpos, encoding))
			
			;č html-ko nemůže nezpůsobit chybu.
			;č nemá cenu je hlídat
			Local err_code = ?p:Close()
			;Local err_code, status, msg, line, col, pos = ?p:Close()
			;self:Replay(err_code, "Done.") 
		EndIf 
	Else
		self:set_status("\27b" .. GetErrorName(err_code)) 
	EndIf 
EndFunction




Function lurk:Clear()
	mui.DoMethod(#LURK_LISTVIEW, "Clear")
EndFunction 

;č zoufalý pokus rekonstituce adresy
;č nikdy nemůže být 100% funkční
;č kvůli případným přesměrováním 
Function p_reconstructURL(base$, href$)
	;č Pro jistotu. Přece i webmaster může nahodit mezer do atributů!
	href$ = StripStr(href$) 
	;č baseUrl je jíž dříve oříznuty 

	;č pokud href zdá být celou adresou, tak není co řešit
	If StartsWith(href$, "http") Then Return(href$)
	;č pokud href začína lomitkem, tak se vztahuje ke kořenu serveru
	If StartsWith(href$, "/")
		;č uživatel může zadat normální adresu na http://, 
		;č nebo bůhvíco, co může začínat jménem serveru...
		Local hostpos = FindStr(base$, "//", True) + 2
		Local hostend = FindStr(base$, "/", True, hostpos)
		If hostend = -1
			;č bez lomítka na konci.
			Return(base$ .. href$)
		Else
			;č s dostatkem lomítek.
			Return(LeftStr(base$, hostend) .. href$)
		EndIf
	EndIf 
	
	;č bez lomítka, pokud vůbec něčemu rozumím, vztahuje k aktuální složce?
	;č Jenomže ani čert se nevyzná, co je to složka v moderním webu
	;č (víz. poznámku ohledně přesměrování)  
	Local parampos = FindStr(base$, "?", True)
	If parampos > 0
		;č pokud ovšem adresa obsahuje otazník, nebo ampersand
		;č tak část za nim můžeme zajistě vyhodit
		Local drawerpos = ReverseFindStr(base$, "/", True, parampos)		
		Return(LeftStr(base$, drawerpos + 1) .. href$) 
	EndIf
	
	;č Je to jedno. Nechť si to uživatel řeší sám!
	Return(TrimStr(base$, "/", True) .. "/" .. href$) 
EndFunction 

Function _test_reconstruction() 
	Local testcases = {}
	testcases["aninet.no"] = "feed"
	testcases["gemini://aninet.no"] = "feed"
	testcases["gemini://aninet.no/"] = "feed"
	testcases["gemini://aninet.no/dfg/"] = "feed"
	testcases["gemini://aninet.no/dfg/tgb"] = "feed"
	testcases["gemini://aninet.no/dfg/tgb?"] = "feed"
	testcases["gemini://aninet.no/dfg/tgb?atari=0&amiga=1"] = "feed"
	testcases["gemini://aninet.no/dfg/?atari=0&amiga=1"] = "feed"
	testcases["aninet.no/%34%20/?atari=0&amiga=1"] = "feed"
	For i,v In Pairs(testcases) 
		DebugPrint(i, v, p_reconstructURL(i, v))
	Next 
EndFunction 



Function lurkStartElement(p, name$, attrs) 
	CheckEvents()	
	If lurk.PleaseStop 
		p:Stop()
	EndIf
	
	Switch LowerStr(name$)
	Case "body":
		p:Stop()
		Return()
	Case "link":
		If HaveItem(attrs, "type")
			Switch LowerStr(attrs.type)
			Case "application/atom+xml":
				FallThrough
			Case "application/rss+xml":		
				Local item = {href="", title="", rel=""}
				For i,v In Pairs(item) 
					If HaveItem(attrs, i) Then item[i] = attrs[i]
				Next 
				/*
				<column title="CanHas"/>
				<column title="Address"/>
				<column title="Title"/>
				<column title="Relationship"/>
				<column title="Type"/>
				<column title="URL constructed"/>
				*/
				Local url$ = p_reconstructURL(p:getbase(), item.href)
				mui.DoMethod(#LURK_LISTVIEW, "Insert", "Bottom", 
					lurk:CanHas(url$),
					item.href,
					item.title,
					item.rel,
					attrs.type,
					url$)
			EndSwitch
		EndIf
	EndSwitch
	
EndFunction 

Function lurk:CanHas(url$)
	Return(IIf(p_HasItem(url$, "Root"), "added" , ""))
EndFunction 

Function lurk:AddByDoubleClick()
	self:AddFromlist(pos)
	p_SaveFeeds() 
EndFunction 



Function lurk:AddSelected()
	Local t = mui.DoMethod(#LURK_LISTVIEW, "GetSelection")
	For i,v In IPairs(t) ;č tam jsou pouze číselné indexy. Možno. 
		lurk:AddFromlist(v)
	Next 
	p_SaveFeeds() 
EndFunction 

Function lurk:AddFromlist(pos)
	Local has$, href$, title$, rel$, type$, url$ = mui.DoMethod(
										#LURK_LISTVIEW, "GetEntry", pos)
	If Not has$
		p_AddFeed(url$)
	EndIf 
	mui.DoMethod(#LURK_LISTVIEW, "Rename", pos, 
					self:CanHas(url$), href$, title$, rel$, type$, url$)
EndFunction 

Mode Type Size Ref File
100755 blob 7473 1ab45355102d3c454b8d83e05e4af10b0447dee3 128px-Feed-icon.png
100755 blob 5490 12b52e34bfc98a045a9a92554d9ec08298543f4e AppWindow.xml
100755 blob 3296 87f34b200c7e6abd9235c437a1927c745832e729 IvoR.hws
100755 blob 8478 9ee3bec9fe9a2b110bf488d69aa134ba85afb7c7 IvoRSS.hws
100755 blob 7191 6291191cf3b1e9b7dd44493a09e26918f2c6e3d1 IvoRSS.png
100755 blob 4405 6f1fc460afb31e6e38cd78dd01c0debaae6f5343 feeds.hws
100755 blob 5736 cfd48d2e43a2e0a9b7b4da56bb989e227337ae26 feedtree.hws
100755 blob 6136 c90b6de510cd88c3e449aa3bbfe05bc255ec017a lurk.hws
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/iam-git/IvoRSS

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/iam-git/IvoRSS

Clone this repository using git:
git clone git://git.rocketgit.com/user/iam-git/IvoRSS

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main