Web Programming

For discussions about programming, programming questions/advice, and projects that don't really have anything to do with Puppy.
Message
Author
User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

Re: Web Programming

#21 Post by technosaurus »

L18L wrote:function UrlExists(url){ var http=new XMLHttpRequest()
needs a web server, ?
nope, but then again I am using seamonkey on my windows box

... but I had a cut paste error when removing some dummy tags

the de-de.js should be like this:

Code: Select all

setLang({"items":[{"id":"intro","value":"..."},
{"items":[{"id":"legal","value":"..."},
]});
and the legal was supposed to wrap the legal disclaimer at the bottom with

Code: Select all

<div id="legal">
...
</div>
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

User avatar
L18L
Posts: 3479
Joined: Sat 19 Jun 2010, 18:56
Location: www.eussenheim.de/

Re: Web Programming

#22 Post by L18L »

technosaurus wrote:...the de-de.js should be like this:

Code: Select all

setLang({"items":[{"id":"intro","value":"..."},
{"items":[{"id":"legal","value":"..."},
]});
With a little help from seamonkey's "lang=de: Fehlerkonsole" (JavaScript Debugger was no help) I made it work now.
Congrats, it is fantastic. 8)
my de-de.js wrote:setLang({"items":[

{"id":"intro","value":"<br>Hi, ich bin Barry Kauler, der original developer of the Puppy Operating System, and you can find a completeintroduction to Puppy on the web at: <a href="http://www.puppylinux.com/">http://www. ... ux.com/</a> and <a href="http://www.puppylinux.org/">http://www. ... br><br>You are going to be amazed at the quantity and quality ofapplications in such a tiny Linux 'distro', as well as blown away bythe speed and stunned by the ease-of-use.<br><br>My aim is for Puppy to become a no-brainer to use (ie, no need to readthemanual!). Just turn on the PC, and off you go... we're not there yet,as someconfiguration files may have to be edited, plus various apps have to be"tweaked". Maybe some of your PC hardware doesn't work --in that case, first browse through the online documentation, thensearch the Puppy Discussion Forum -- as a last resort, post a question.<br><br>I would like to very briefly acknowledge all the guys whose programs I haveused in Puppy. Truly, I am standing on the shoulders of many others to reachthis new pinnacle that is the achievement of Puppy Linux. I have acknowledgedpeople throughout the documentation and on the web, and my profuse gratitudegoes out to all you guys who code just because you love doing it. I wouldalso like to send out a special thank-you for the help received from the guyson the Puppy Discussion Forum.<br><br>In fact, if you look at the release notes linked-to above, what is immediately apparentis that Puppy is now a team effort, a change that has been incrementally increasing so over the last couple ofyears. Any acknowledgement now needs to go to our entire "Puppy Team" rather than just me.<h2>Puppy help</h2>All Puppy's local documentation is in HTML or plain text format and located in/usr/share/doc. This page is the master index.<br>"},

{"id":"legal","value":"<br><small><b>Rechtlicher Hinweis:</b><br>Ich, Barry Kauler, etablierte das 'Puppy Linux Projekt' im Januar 2003, first website and productrelease 18-June-2003, and I have trademark claim to the name and typeddrawing of 'Puppy Linux', 'PuppyOS' and 'Puppy' as it relates to"computer operating system software to facilitate computer use andoperation", under Federal and International Common Law and TrademarkLaws as appropriate.<br>Programsin Puppy are open source (except where noted above), and licences ofindividual products are duly acknowledged. The name Puppy Linux", alsoknown as "Puppy" and "PuppyOS", and all artisitic creations thereof,are copyright (c) 2003,2004,2005,2006,2007 Barry Kauler -- furtherdetails in the online <a href="http://www.puppylinux.com/faq.htm">FAQ< ... b><br>Very simple, use entirely at your own risk. Barry Kauler accepts no liabilityor responsibility whatsoever, and you use Puppy with this understanding.<br></small><br>"}

]});
Note,
- it is just the green text that I have translated for testing
- The blank lines have been helpful for debugging
- One warning (not wellformed) remains:
Zeitstempel: 22.11.2012 11:25:32
Fehler: nicht wohlgeformt
Quelldatei: file:///root/my-documents/techno/doc/de-de.js
Zeile: 1, Spalte: 8
Quelltext:
setLang({"items":[

_________________________________
edit
PS
not well-formed
This is because the javascript is placed after </body>
For well-formedness is ought to be between <head> and </head>
But then it does not work because body is not yet loaded.
TypeError: document.body is null
Attachments
tweb_OK_now.png
see this file name
(13.48 KiB) Downloaded 1080 times

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#23 Post by technosaurus »

The "not well formed" warning was something I chose to live with while I find a better fix. The translation format won't change and none of the "fixes" I found so far were suitable. I already tried using straight json (no callback function) with document.write and xmlhttprequest as well as putting it in a header script tag + a few more, but couldnt figure out how to access it.

The header method could work if the script tag had async a some way to wait for body to load
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

User avatar
L18L
Posts: 3479
Joined: Sat 19 Jun 2010, 18:56
Location: www.eussenheim.de/

Web Programming

#24 Post by L18L »

technosaurus wrote:The "not well formed" warning was something I chose to live with while I find a better fix.
I have found not a total fix but better than now
between <head> and </head> something like wrote:<script type="text/javascript">
<!-- Begin
function UrlExists(url)
{
var http=new XMLHttpRequest()
try
{
http.open('head',url,false);http.send();return http.status!=404
}
catch(e)
{
return false
}
}
function setLang(data)
{
var term
for (var i=0;i<data.items.length;i++)
{
term=document.getElementById(data.items.id);
if (term) term.innerHTML=data.items.value;
}
}
// End -->
</script>
that is : just the functions
and
the rest in body onload: wrote:<body onload='var lang=navigator.userLanguage || navigator.language.toLowerCase(); if(UrlExists(lang+".js")){ var s=document.createElement("script"); s.src=lang+".js?callback=setLang"; document.body.appendChild(s)}'>


The not well-formed is in the de-de.js file.

http://validator.w3.org/check validates if
- div not inside of small
- form gets an action="./"

(I like validated markup)
(and html5 is not that difficult)

User avatar
Moose On The Loose
Posts: 965
Joined: Thu 24 Feb 2011, 14:54

#25 Post by Moose On The Loose »

Code: Select all

#!/bin/sh
[....]
echo "<!DOCTYPE HTML PUBLIC\ "-//W3C//DTD HTML 4.0 Transitional//EN\">
<html>
    <head>
        <title>Index Of: "$@"</title>
    </head>
    <body LANG="en-US">
Declaring the language and the DOCTYPE seems to make browsers more consistent about what they display for the HTML input.

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#26 Post by technosaurus »

I could put all of that onload stuff into a separate function to clean it up. I am still looking for a way to use straight json without the callback function (json-p) this would make the LANG packs much more portable (you could share translations with any language that supports json, like php, java, nodejs,...). I just wanted to be able to access the object from the javascript, but I must have missed something obvious. I will figure it out though.
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#27 Post by technosaurus »

finally... was looking for eval and needed to change the mimetype, so now it is a single function that gets called onload

Code: Select all

<html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<head>
<script>
function setLang(){
var lang=navigator.userLanguage || navigator.language.toLowerCase(),req;
	if (window.XMLHttpRequest){		//IE7+,Firefox,Chrome,Opera,Safari
		req=new XMLHttpRequest();
	}else{													//IE6,IE5
		req=new ActiveXObject("Microsoft.XMLHTTP");
	}
	req.open("GET",lang+".json",true);
	req.overrideMimeType("application/json");
	req.send();
	req.onreadystatechange=function(){
		if (req.readyState==4 && req.status!=404){
			var term,data=eval('(' + req.responseText + ')')
			for (var i=0;i<data.items.length;i++){
				term=document.getElementById(data.items[i].id)
				if (term) term.innerHTML=data.items[i].value
			}
		}
	}
}
</script>
<style>
.txt{float:left;margin-left:10px}
</style>
</head>
<body onload='setLang()'>
<div id="string1" class="txt" >  This is the default text of string 1.  </div> 
<div id="string2" class="txt" >  This is the default text of string 2.  </div>
</body></html>
and simple json format for value pairs

Code: Select all

{"items":[{"id":"string1","value":" Localized text of string1. "},{"id":"string2","value":" Localized text of string2. "}]}
now to write a tutorial
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#28 Post by technosaurus »

crap, that only works for gecko/mozilla browsers for local files, back to the drawing board ... again
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#29 Post by technosaurus »

this works in everything but opera, but I think that may be an opera bug
turns out there is no need for the urlexist function (its xmlhttprequest was the cause of the not well formed warning)
the script tag can go anywhere in the file this way

Code: Select all

<html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<head>
<style>
.txt{float:left;margin-left:10px}
</style>
</head>
<body onload='setLang()'>
<div id="string1" class="txt" >  This is the default text of string 1.  </div> 
<div id="string2" class="txt" >  This is the default text of string 2.  </div>
</body></html>
<script>
	var lang=navigator.userLanguage || navigator.language.toLowerCase();
	var script=document.createElement("script");
	script.src=lang+".jsonp"
	var head = document.getElementsByTagName('head')[0]
	head.insertBefore(script,head.firstChild)
	alert(head.innerHTML)
	function setLang(){
		for (var i=0;i<items.length;i++){
			term=document.getElementById(items[i].id)
			if (term) term.innerHTML=items[i].value
		}
	}
</script>
and the lang.jsonp file:

Code: Select all

items=[
{"id":"string1","value":" Localized text of string1. "},
{"id":"string2", "value":" Localized text of string2. "}
];
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#30 Post by technosaurus »

I am moving the localization discussion to the localization sub forum here:
http://www.murga-linux.com/puppy/viewtopic.php?t=82502

may as well post the useful functions I came up with while working on it here though

Code: Select all

/* remove ...dir/ and .extension */
function basename(s){s=s.substring(s.lastIndexOf('/')+1);var i=s.indexOf('.');return s.substring(0,i!=-1?i:s.length)}
/* set class to c for the id of i */
function setClassForId(c,i){document.getElementById(i).className=c}
/* changes the innerHTML value for all ids in array a where a=[{"id":"the_id","value":"some innerHTML string"},...]; */
function changeItems(a){for(var i=0;i<a.length;i++){term=document.getElementById(a[i].id);if(term)term.innerHTML=a[i].value}}
/* return the parent directory/ of s */
function dirname(s){return s.substring(0,s.lastIndexOf('/')+1)}
/* returns string for language and country in the form en-US */
function getLangCountry(){return(navigator.userLanguage||navigator.language)}
/* returns the 2 letter language code */
function getLang(){return(navigator.userLanguage||navigator.language).substring(0,2)}
/* put script tag with source "s" right after <head> */
function prependScriptFromUrl(s){var a=document.createElement("script"),b=document.getElementsByTagName('head')[0];a.src=s;b.insertBefore(a,b.firstChild)}
/* put style tag with source "s" right after <head> */
function prependStyleFromUrl(s){var a=document.createElement("style"),b=document.getElementsByTagName('head')[0];a.src=s;b.insertBefore(a,b.firstChild)}
/* put style tag with contents "s" right after <head> */
function prependStyleFromString(s){var a=document.createElement("style"),b=document.getElementsByTagName('head')[0];a.innerHTML=s;b.insertBefore(a,b.firstChild)}
/* returns true if url "u" exists, otherwise false */
function UrlExists(u){var h=XMLHttpRequest();try{h.open('HEAD',u,false);h.send();return h.status!=404}catch(e){return false}}
/* returns an array of all elements with id */
function getElementsById(id){var t=document.getElementsByTagName("*"),a=[];for(var i=0;i<t.length;i++)if(t[i].id==id)a[a.length]=t[i];return a}
/* format number string with commas */
function addCommas(s){var a=s.split('.')[1];(a)?a="."+a:a="";s=s.split('.')[0];while(s.length>3){a=","+s.substr(s.length-3,3)+a;s=s.substr(0,s.length-3)}return s+a}
/* remove class s from array a of elements */
function removeClassFromElements(s,a){for(i=0;i<a.length;i++){var p=a[i].className.indexOf(s);if(p!=-1)a[i].setAttribute("class",((p==0)?"":a[i].className.substring(0,p))+a[i].className.substring(p+s.length,a[i].className.length))}}
/* add class s to array a of elements */
function addClassToElements(s,a){for(i=0;i<a.length;i++)if(a[i].className.indexOf(s)==-1)a[i].setAttribute("class", a[i].className+" "+s)}
/* returns true if font f is available false otherwise */
function hasFont(f){var s=document.createElement("span");s.style.fontSize="72px";s.innerHTML="MWMWM";s.style.visibility="hidden";s.style.fontFamily=[(f=="monospace")?'':'monospace','sans-serif','serif'];document.body.appendChild(s);var w=s.offsetWidth;s.style.fontFamily=[f,'monospace','sans-serif','serif'];document.body.lastChild=s;return s.offsetWidth!=w}
fontlist=["cursive","monospace","serif","sans-serif","fantasy","default","Arial","Arial Black","Arial Narrow","Arial Rounded MT Bold","Bookman Old Style","Bradley Hand ITC","Century","Century Gothic","Comic Sans MS","Courier","Courier New","Georgia","Gentium","Impact","King","Lucida Console","Lalit","Modena","Monotype Corsiva","Papyrus","Tahoma","TeX","Times","Times New Roman","Trebuchet MS","Verdana","Verona"]
function secondaryWindows(n,u){if(typeof w=="undefined")w=[];if(typeof(w[n])=="undefined" || w[n].closed){w[n]=window.open(u)}else{alert(u);w[n].location=u}}
Last edited by technosaurus on Sat 01 Dec 2012, 04:34, edited 1 time in total.
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#31 Post by technosaurus »

an example using the (now deprecated) twitter search api

Code: Select all

<html><head><title>Twitter Search</title>
<style>
.box{width:25%;top:65px;height:75%;overflow:auto}.sbox,.box{position:absolute;border:5px solid gray;padding:5px}.sbox,#l{left:5%}#c{left:35%}#r{left:65%}
</style>
<script>
var termsl,termsc,termsr
function foo(data){var term=document.getElementById("term").value
var l=document.getElementById("l"),c=document.getElementById("c"),r=document.getElementById("r")
if((termsc != term)&&(termsl != term)){termsr=termsc
r.innerHTML=c.innerHTML}if(termsl != term){termsc=termsl
c.innerHTML=l.innerHTML}termsl=term
l.innerHTML=term+"<br><hr>"
for (var i=0;i<data.results.length;i++){var result=data.results[i]
l.innerHTML+='<span><a href="http://twitter.com/#!/'+result.from_user+'/status/'+result.id_str+'"> <img width="24" height="24" src="'+result.profile_image_url+'"> '+result.from_user+'<a>: '+result.text+'</span><br>'}}
srch=function(){var term=document.getElementById("term").value,script=document.createElement("script");
script.src="http://search.twitter.com/search.json?q="+term+"&callback=foo"
document.body.appendChild(script)}
</script>
</head>
<body><form class="sbox" action="javascript:srch()">
<input id="term" name="term" type="textbox"/><input type="submit" value="Twitter Search"/></form>
<div id="l" class="box"></div><div id="c" class="box"></div><div id="r" class="box"></div>
</body></html>
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

User avatar
L18L
Posts: 3479
Joined: Sat 19 Jun 2010, 18:56
Location: www.eussenheim.de/

#32 Post by L18L »

technosaurus wrote:an example using the (now deprecated) twitter search api
technosaurus out now :?:
Attachments
twitter.png
(49.58 KiB) Downloaded 1990 times

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#33 Post by technosaurus »

Here is a drag and drop example:

(tested on IE 5.5, 6, 8 & 9 using IETester and Seamonkey-2.14 - so should verify for Firefox too, as well as Chrome and Opera, but drag/drop is broken in safari-5.1.7 for windows/wine, so use 5.0.6 - I think apple intentionally broke things for the windows client)

here are functions

Code: Select all

function drag(ev){ //we will just store the inner html of our drag tag - it could be id, class or something else
	ev.dataTransfer.setData("Text",ev.target?ev.target.innerHTML:event.srcElement.innerHTML) //IE needs "Text" and others are fine with it
}
function drop(ev){
	if(ev.preventDefault){ev.preventDefault();  //or mozilla will navigate to the url.com of the text
		ev.target.innerHTML=ev.dataTransfer.getData("Text") //we are replacing the inner html of our drop with our drag
	}else{event.returnValue=false //ie workaround does not have preventDefault or target
		event.srcElement.style.backgroundColor=ev.dataTransfer.getData("Text")
	}
}
Notes on the html:
older versions of _some_ browsers only support dragging "a" or link tags, so use it with a blank href
we need to set draggable to true for the items we want to be able to drag
we also need to get the draggable, so we set ondragstart to our drag function and pass it the event
we also need to override the default function of ondragover - return false will do this nicely (or you _could_ use a function to preventDefault, but it is not browser independent)
and finally we need to do something with our drop event, so we set ondrop to pass the drop event to our drop function

Code: Select all

<a href="#" id="dragme" draggable="true" ondragstart="drag(event)">content to drag</a>
<div id="drophere" ondrop="drop(event)" ondragover="return false">a place to drop</div>
but since we used <a> tags, it will look like a link, so we need to add some css to fix that

Code: Select all

#dragme,#drophere{text-decoration:none;color:black}
note the link is href="#", a non-existent nav point, so that clicking on it instead of dragging doesn't cause a page reload (as href="" would)

All of the above css and html can be created dynamically in your script, but I split out as much as possible to show the basic principals


and the example:

Code: Select all

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

<head><title>dragable colors</title><meta http-equiv="content-type" content="text/html;charset=utf-8" />
<style>
#drop{left:15%;width:70%;top:65px;height:75%;overflow:auto}
#drop,#y,#r,#b{position:absolute;border:5px solid gray;padding:5px}
#r{left:35%;color:red}#b{left:45%;color:blue}#y{left:55%;color:yellow}
#r,#y,#b{width:5%;text-align:center;background:lightgray;text-decoration:none}
</style>

<script>
function allowDrag(event){
	if(event.preventDefault){
		event.preventDefault();
	}else{
		event.returnValue=false;
	}
	return false
}
function drag(ev){
	ev.dataTransfer.setData("Text",ev.target?ev.target.innerHTML:event.srcElement.innerHTML)
}
function drop(ev){alert;
	if(ev.preventDefault){ev.preventDefault();
		ev.target.style.backgroundColor=ev.dataTransfer.getData("Text")
	}else{event.returnValue=false //ie workaround
		event.srcElement.style.backgroundColor=ev.dataTransfer.getData("Text")
	}
}
</script>

</head>

<body>
<a href="#" id="y" draggable="true" ondragstart="drag(event)">yellow</a>
<a href="#" id="r" draggable="true" ondragstart="drag(event)">red</a>
<a href="#" id="b" draggable="true" ondragstart="drag(event)">blue</a>
<div id="drop" ondrop="drop(event)" ondragover="allowDrag(event)">drag a color to this box</div>
</body>

</html>
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#34 Post by technosaurus »

I've been thinking about writing my own javascript library designed for "static" compiles, but though I was pretty certain it is needed, I figured I would scope out the top libraries and see how they compared with fully optimized compiles.

I did my little bloat comparison of javascript libraries to see how well they "statically" compile using the closure compiler service at http://closure-compiler.appspot.com/home

My method:
include 1 and only 1 javascript library and a simple hello world alert function that doesn't use any code from the library and build with full optimization

turns out they really are horrible for dead code elimination, except google's base.js (which is horrible for other reasons)

The library that I am working on (a.js... a reference to static archives) compiles down to zero if the code isn't used. The idea is to only add functions that aren't so complex that they prevent optimization (for example no functions that take a function as an argument)
Attachments
comparison.png
(5.7 KiB) Downloaded 1460 times
Book1.html.gz
(771 Bytes) Downloaded 728 times
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#35 Post by technosaurus »

for debugging:

Code: Select all

/*@const*/
DEBUG=2
if(DEBUG){

/*@const @constructor*/
Object.defineProperty(window,'__stack__',{get:function(){
	try{_ფ_()}catch(e){return e.stack.split(":")}
}})

/*@const @constructor*/
Object.defineProperty(window,'__file__',{get:function(){
	var s=__stack__,l=s.length
	return (isNaN(s[l-2]))?s[l-2]:s[l-3]
}})

/*@const @constructor*/
Object.defineProperty(window,'__line__',{get:function(){
	var s=__stack__,l=s.length
	return (isNaN(s[l-2]))?s[l-1]:s[l-2]
}})

/*@const @constructor*/
Object.defineProperty(window,'__col__',{get:function(){
	var s=__stack__,l=s.length
	return (isNaN(s[l-2]))?"NA":s[l-1]
}})

/*@const @constructor*/
Object.defineProperty(window,'LOG',{
	get:function(){return out},
	set:function(msg){if(DEBUG>1)out=msg+"\t-\t"+__stack__
		else out=msg+" in file:"+__file__+" @ Line:"+__line__+", Column:"+__col__
		console.log(out)}
})
}//end if(DEBUG)
usage:
LOG="hello world"

or:
alert("my message at line:"+__line__)
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#36 Post by technosaurus »

this is some server side javascript for node.js, it takes any url and wraps the response in a callback. In other words it is a helper that converts JSON to JSONP for cross site scripting.

example that will get imdb json and wrap it in a callback called hello
localhost:8080/?callback=hello&host=www.imdb.com&path=/xml/find?json=1&nr=1&nm=on&q=jackson

Code: Select all

var http = require('http');
http.createServer(function (req, res) {
	res.writeHead(200, {'Content-Type': 'application/javascript'});
	var q=req.url.split('?'),p,i,h,f
	if(q.length>1)p=q[1].split('&'),i=p.length;else return;
	
	while(i--){
		if(p[i].split('=')[0]=="callback"){res.write(p[i].split('=')[1]+'(')}
		if(p[i].split('=')[0]=="host"){h=p[i].split('=')[1]}
		if(p[i].split('=')[0]=="path"){f=p[i].split('=')[1]}
	}
	if(h&&f&&q[2])http.get({host:h,port:80,path:f+'?'+q[2]},function(r){
		r.on('data', function(d){res.write(d.toString())})
		r.on('end', function(){res.write(')');res.end()})
	}).on('error',function(e){console.log(e.stack)})
}).listen(8080, '127.0.0.1');
console.log('Server running at http://127.0.0.1:8080/');
Oh, what the hell, here is a simple puppy-ish alternative that can run with only busybox.

Code: Select all

#!/bin/sh
CB="${QUERY_STRING%%&*}"
case "$CB" in
	callback=*)
		printf "Content-type: application/javascript

${CB##*=}("
		wget -O - ${QUERY_STRING#*&}
		printf ")"
	;;
	*)
		exit
	;;
esac
Note: busybox would need to be configured to enable httpd with cgi support, wget and either ash or hush (should be ~100kb binary)

Edit: I made the shell version output gzipped data

Code: Select all

#!/bin/sh
CB="${QUERY_STRING%%&*}"
case "$CB" in
	callback=*)
		printf "Content-Encoding: gzip
Content-type: application/javascript

" #todo clean up this while loop hack
		while ([ ! "$ONCE" ]);	do
			printf "${CB##*=}("
			wget -O - ${QUERY_STRING#*&}
			printf ")"
			ONCE=1
		done | gzip -9c
	;;
	*)
		exit
	;;
esac
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

accessing web services with busybox ash shell + nc (netcat)

#37 Post by technosaurus »

accessing web services with busybox ash shell and nc (aka netcat)

Code: Select all

#!/bin/ash

# line to get the wsdl, but instead use:
# http://soapclient.com/soaptest.html instead
# you can use it to get the proper requests - hint: view source
#echo -e "GET /hosps?wsdl HTTP/1.1\r\n\r\n" | nc 192.168.0.102 8888
newline="
"

#you'll need your outside IP address if the web service is on your PC
get_ip(){
IP=`echo -e "GET / HTTP/1.1\r
host: myip.dnsd.me

" | nc myip.dnsd.me 80`
echo ${IP##*$newline}
}
# get_ip(){ #bash only version no nc dep, but /dev/tcp may not be compiled in
# exec 3<>/dev/tcp/myip.dnsdynamic.org/80
# echo -e "GET / HTTP/1.1\r\nhost: myip.dnsd.me\r\n\r\n" >&3
# IP=`cat <&3`
# echo ${IP##*
# }


SOAP(){ # $1=url $2=port $3=namespace $4=endpoint $5=action $6=parameter
#ex. SOAP localhost 8888 "http://patient.ch01/" "/hosps" "getHosps" "some name"

A='<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
	<SOAP-ENV:Body>
		<mns1:'"$5"' xmlns:mns1="'"$3"'">
			'"$6"'
		</mns1:'"$5"'>
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
'
echo -e "POST $4 HTTP/1.1\r
Content-Type: text/xml
Content-Length: ${#A}

$A"  | nc "$1" "$2"
}

SOAP 192.168.0.102 8888 "http://patient.ch01/" "/hosps" "getHosps"

here's an example of it in use:

Code: Select all

#!/bin/ash

SOAP(){ # $1=url $2=port $3=namespace $4=endpoint $5=action $6=parameter
#ex. SOAP localhost 8888 "http://patient.ch01/" "/hosps" "getHosps" "some name"
A='<?xml version="1.0"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
	<SOAP-ENV:Body>
		<mns1:'"$5"' xmlns:mns1="'"$3"'">
			'"$6"'
		</mns1:'"$5"'>
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
'
echo -e "POST $4 HTTP/1.1\r
Content-Type: text/xml
Content-Length: ${#A}

$A"  | nc "$1" "$2"
}

D(){ echo $2 $3
echo "$1" | awk '
	BEGIN{RS="<return><name>"}
	(tolower($0) ~/'"${2}"'/ && tolower($0) ~/'"${3}"'/){
		gsub(/<[^>]*>/,"\t");
		print "\nDr. "$1" "$2 " has " $NF " patients."
		print "\tAge  First Name      Last Name"
		for (i=3;i<NF;i+=3){printf "\t%-4s %-15s %s\n",$i,$(i+1),$(i+2)}
	}'
}

P(){ echo $2 $3
echo "$1" | awk 'BEGIN{RS="<return><name>"}
tolower($0) ~/'"${2}"'/{
	gsub(/<[^>]*>/,"\t");
	for (i=3;i<NF;i+=3){
		age=i;
		first=i+1;
		last=i+2;
		if(tolower($first) ~/'"${2}"'/)
			if(tolower($last) ~/'"${3}"'/)
				print $first, $last,"is age",$age,"and is a patient of Dr.",$1,$2
	}
}'
}

soap=`SOAP 192.168.0.102 80 "http://patient.ch01/" "/hosps" "getHosps"`
while read -p "
Enter a name followed by a D for doctor or P for patient:

" first last func; do
first=`echo $first|tr [A-Z] [a-z]`
last=`echo $last|tr [A-Z] [a-z]`
case $func in
	D)D "$soap" "$first" "$last";;
	P)P "$soap" "$first" "$last";;
	*)echo "no D/P selected, exiting.";exit;;
esac
done
edit temp code

Code: Select all

#!/bin/sh

#global variables ... will eventually go to external file to be modified/sourced
MIN_PW_LEN=6

createUser(){ #input: $1=UserLogin, $2=UserPassword, $3=UserDisplayName
	#output: int (0-no errors, 1+ error)
	#todo (makes sure UserLogin does not already exist)
	[ "$1" ] || return 1 #empty UserLogin
	[ `userExists $UserLogin` ] && return 2 #UserLogin exists
	[ ${#2} -lt ${MIN_PW_LEN} ]  && return 3 #UserPasword too short
	echo 'insert into _Users(UserLogin, UserPassword, UserDisplayName, UserDeleted) values("'${1}'","'${2}'","'$3'",0);.quit;'
}

checkUserPassword(){ #input: $1=UserLogin, $2=UserPassword (both clear text for now)
	#output: int (0-no errors, 1+ error)
}

deleteUser(){ #input: UserLogin
	#output: int (0-no errors, 1+ error)
	
}

getAllUsers(){ #output: List of UserLogin

}

getUserDisplayName(){ #input: $1=UserLogin
	#output: UserDisplayName
}

initDB(){
#create table _Users(UserUID INTEGER PRIMARY KEY ASC, UserLogin VARCHAR(32) UNIQUE NOT NULL, UserPassword VARCHAR(32),UserDisplayName VARCHAR(64), UserDeleted BOOL );
#note INTEGER PRIMARY KEY ASC is redundant to row id?
}


sendHeader(){
printf "Content-type: application/javascript\r\n\r\n"
}

sendResponse(){
}

splitQueryString(){ #not used
	OLDIFS="$IFS"
	IFS="&"
	for param in $1; do
		case "$param" in
			*=*)echo $param;;
		esac
	done
	IFS="$OLDIFS"
}


updateUser(){ #input: $1=UserLogin, $2=UserPassword, $3=UserDisplayName
	# output: int (0-no errors, 1+ error)
	# (makes sure UserLogin does exist updattes UserPassword, UserDisplayName, sets UserDelete to false)
	[ "$1" ] || return 1 #empty UserLogin
	[ `userExists $UserLogin` ] && return 4 #UserLogin does not exist
	[ ${#2} -lt ${MIN_PW_LEN} ]  && return 3 #UserPasword too short
}

userExists(){
}

`splitQueryString`

case "$action" in
	checkUserPassword)checkUserPassword "$UserLogin" "$UserPassword";;
	createUser)createUser "$UserLogin" "$UserPassword" "$UserDisplayName";;
	deletUser)deleteUser "$UserLogin";;
	getAllUsers)getAllUsers;;
	getUserDisplayName)getUserDisplayName "$UserLogin";;
	updateUser)updateUser "$UserLogin" "$UserPassword" "$UserDisplayName";;
esac
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#38 Post by technosaurus »

I patched the sqlite3 shell to output json for use in web services (you could get away with using its csv output + sed, but this is a pretty small patch)

Code: Select all

--- shell.c~	2013-03-29 22:07:49.000000000 +0800
+++ shell.c	2013-04-07 02:27:33.792883620 +0800
@@ -453,6 +453,7 @@ struct callback_data {
 #define MODE_Tcl      6  /* Generate ANSI-C or TCL quoted elements */
 #define MODE_Csv      7  /* Quote strings, numbers are plain */
 #define MODE_Explain  8  /* Like MODE_Column, but do not truncate data */
+#define MODE_Json     9  /* Like MODE_Column, but do not truncate data */
 
 static const char *modeDescr[] = {
   "line",
@@ -464,6 +465,7 @@ static const char *modeDescr[] = {
   "tcl",
   "csv",
   "explain",
+  "json",
 };
 
 /*
@@ -826,6 +828,21 @@ static int shell_callback(void *pArg, in
       fprintf(p->out,"\n");
       break;
     }
+    case MODE_Json: {
+      if( p->cnt++==0 && p->showHeader ){
+      fprintf(p->out,(nArg==1)?"":"[");
+        for(i=0; i<nArg; i++){
+          fprintf(p->out,"\"%s\"%s",azCol[i], (i==nArg-1) ? (nArg==1)?",":"]," : ",");
+        }
+      }
+      if( azArg==0 ) break;
+      fprintf(p->out,(nArg==1)?"":"[");
+      for(i=0; i<nArg; i++){
+        output_csv(p, azArg[i], i<nArg-1);
+        if (i==nArg-1) fprintf(p->out,"%s", (nArg==1)?",":"],");
+      }
+      break;
+    }
     case MODE_Insert: {
       p->cnt++;
       if( azArg==0 ) break;
@@ -2066,6 +2083,9 @@ static int do_meta_command(char *zLine,
     }else if( n2==3 && strncmp(azArg[1],"csv",n2)==0 ){
       p->mode = MODE_Csv;
       sqlite3_snprintf(sizeof(p->separator), p->separator, ",");
+    }else if( n2==3 && strncmp(azArg[1],"json",n2)==0 ){
+      p->mode = MODE_Json;
+      sqlite3_snprintf(sizeof(p->separator), p->separator, ",");
     }else if( n2==4 && strncmp(azArg[1],"tabs",n2)==0 ){
       p->mode = MODE_List;
       sqlite3_snprintf(sizeof(p->separator), p->separator, "\t");
@@ -3086,6 +3106,9 @@ int main(int argc, char **argv){
     }else if( strcmp(z,"-csv")==0 ){
       data.mode = MODE_Csv;
       memcpy(data.separator,",",2);
+    }else if( strcmp(z,"-json")==0 ){
+      data.mode = MODE_Json;
+      memcpy(data.separator,",",2);
     }else if( strcmp(z,"-separator")==0 ){
       sqlite3_snprintf(sizeof(data.separator), data.separator,
                        "%s",cmdline_option_value(argc,argv,++i));
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#39 Post by technosaurus »

here is an example for using busybox's cgi-bin to host a puppy package database (hard coded for now, but could use the query string to select quirky/wary/racy/...)

Code: Select all

#!/bin/sh
printf "Content-encoding: gzip
Content-type: application/javascript

"
awk 'BEGIN{FS="|";OFS="\",\"";ORS="\"],\n";printf "petCallback([\n"}
{print "\t[\""$1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14}
END{printf "])\n"}' /root/.packages/Packages-puppy-quirky-official |gzip -9c
and a crappy test page that puts it in an unformatted table

Code: Select all

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head><title></title></head>
<body>
<table id="pets"></table>

<script>
	function petCallback(data){
		var row,cell,text,table = document.getElementById("pets")
		for (var i = 0,rows=data.length,cols=data[0].length; i < rows; i++) {
			row = document.createElement("tr");
			for (var j = 0; j < cols; j++) {
				cell = document.createElement("td");
				text = document.createTextNode(data[i][j]);
				cell.appendChild(text);
				row.appendChild(cell);
			}
		table.appendChild(row);
		}
	}
	var script=document.createElement('script'),head=document.getElementsByTagName("head")[0]
	script.src="http://localhost/cgi-bin/pets?"+(new Date()/1) //prevent cacheing
	head.insertBefore(script, head.firstChild);
</script>
</body>
</html>
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

User avatar
technosaurus
Posts: 4853
Joined: Mon 19 May 2008, 01:24
Location: Blue Springs, MO
Contact:

#40 Post by technosaurus »

I have the beginning of a statically compilable js library (targeted to the closure compiler) let me know if there are any requests.
Check out my [url=https://github.com/technosaurus]github repositories[/url]. I may eventually get around to updating my [url=http://bashismal.blogspot.com]blogspot[/url].

Post Reply