/lurk.hws (d6eda6d26dcd117cbe3eeda270397ef72a592f83) (7305 bytes) (mode 100755) (type blob)


Const #LURK_LISTVIEW = "foundfeeds"

MIME_types = {}
MIME_types["application/rss+xml"] = 2
MIME_types["application/atom+xml"] = 2
MIME_types["application/rdf+xml"] = 1
MIME_types["application/xml"] = 1
MIME_types["text/rss+xml"] = 2
MIME_types["text/atom+xml"] = 2
MIME_types["text/xml"] = 1


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, 0, #ENCODING_RAW) <> -1},
			lurk_callback, url$)

	self:set_status(count .. " bytes from " .. url$ .. " transmitted") 

	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 
		self:set_status("\27b" .. GetErrorName(err_code)) 
		Return()
	EndIf
		
	
	;č Všechno odříznout můžeme i bez Unikódu 
	Local headpos = FindStr(html$, "<link", False, 0, #ENCODING_RAW)
	If headpos < 0
		self:set_status("Nothing found") ;č hlavně ta hlavička..
		Return()
	EndIf 
	
	Local headend = ReverseFindStr(html$, "</head>", False, 
							StrLen(html$, #ENCODING_RAW)-1, #ENCODING_RAW)
	Local len = headend-headpos
	If len < 0
		self:set_status("Something wrong on page")
		Return()
	EndIf 
	
	html$ = MidStr(html$, headpos, len, #ENCODING_RAW)
	;č Tak, zde začínáme řešit kódování
	Local ok, n = ValidateStr(html$, #ENCODING_UTF8)
	Local encoding = IIf(ok, #ENCODING_UTF8, #ENCODING_ISO8859_1)
	Local p_encoding = IIf(ok, "UTF-8", "ISO-8859-1")
	
	
	Local parsers_tired = 0
	Local total_links = 0
	Local p = XMLParser.New({StartElement = lurkStartElement})
	p:setbase(url$)
	p:setencoding(p_encoding)
	Local taxometr = 0
	For w$ In PatternFindStr(html$, "<link .->") 
		debugprint(w$)
		total_links = total_links + 1
		taxometr = taxometr + StrLen(w$, encoding)
		p:Parse(w$)
		Local lin, col, pos = p:pos()
		Local err_code = ?p:Close()
		If pos < taxometr Then parsers_tired = parsers_tired + 1
		p = XMLParser.New({StartElement = lurkStartElement})
		p:setbase(url$)
		p:setencoding(p_encoding)
		taxometr = 0
	Next
	;č html-ko nemůže nezpůsobit chybu.
	;č nemá cenu je hlídat
	Local err_code = ?p:Close()
	If parsers_tired 
		self:set_status(parsers_tired .." of total ".. 
										total_links .. " links unparsed")
	Else
		self:set_status(total_links .. " links parsed")
	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") And HaveItem(MIME_types, attrs.type)
			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 preparse = "\27i"
			If LowerStr(item.rel) = "alternate" And MIME_types[attrs.type] = 2
				preparse = ""
			EndIf
			Local url$ = p_reconstructURL(p:getbase(), item.href)
			mui.DoMethod(#LURK_LISTVIEW, "Insert", "Bottom", 
				lurk:CanHas(url$),
				preparse .. item.href,
				preparse .. item.title,
				preparse .. item.rel,
				preparse .. attrs.type,
				url$)
		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 6349 eeaf40384a6978792850e51646c94025c31c9263 AppWindow.xml
100755 blob 8882 af0ada41f32b55988a04e827ef3cabfe15e898bc IvoR.hws
100755 blob 9254 2952d46d403216b549fd61ef70e888b976bd7a08 IvoRSS.hws
100755 blob 7191 6291191cf3b1e9b7dd44493a09e26918f2c6e3d1 IvoRSS.png
100755 blob 1093 263306d87c51114b1320be2ee3277ea0bff99b1f LICENSE
100755 blob 1434 306dab5d612ce4698a6e2a74a879795ccdf1b7b2 ReadMe
100755 blob 4007 8956c1bb5d76b481d4e2458b16a64fbee8f6f9e6 feeds.hws
100755 blob 1694 83e47eb86860331dfe771f49029c00559a2f687e feedsdata.hws
100755 blob 13089 b20da94931f651264cb9ab0655fca95b0ac1a3f3 feedtree.hws
100755 blob 7305 d6eda6d26dcd117cbe3eeda270397ef72a592f83 lurk.hws
100755 blob 10842 5b70109781bedd7885042d29046cbd23f86e5672 textfield.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