Soundmanager2 won't load sound from google translate - soundmanager2

I want to speak some text; I can get the audio-file(mp3) from google translate tts if I enter a properly formatted url in the browser.
But if I try to createSound it, I only see a 404-error in firebug.
I use this, but it fails:
soundManager.createSound(
{id:'testsound',
autoLoad:true,
url:'http://translate.google.com/translate_tts?ie=UTF-8&tl=da&q=testing'}
);
I have pre-fetched the fixed voiceprompts with wget, so they are as local mp3-files on the same webserver as the page. But I would like to say a dynamic prompt.

I see this was asked long time ago, but I have come to a similar issue, and I was able to make it work for Chrome and Firefox, but with the Audio Tag.
Here is the demo page I have made
http://jsfiddle.net/royriojas/SE6ET/
here is the code that made the trick for me...
var sayIt;
function createSayIt() {
// Tiny trick to make the request to google actually work!, they deny the request if it comes from a page but somehow it works when the function is inside this iframe!
//create an iframe without setting the src attribute
var iframe = document.createElement('iframe');
// don't know if the attribute is required, but it was on the codepen page where this code worked, so I just put this here. Might be not needed.
iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-pointer-lock');
// hide the iframe... cause you know, it is ugly letting iframes be visible around...
iframe.setAttribute('class', 'hidden-iframe')
// append it to the body
document.body.appendChild(iframe);
// obtain a reference to the contentWindow
var v = iframe.contentWindow;
// parse the sayIt function in this contentWindow scope
// Yeah, I know eval is evil, but its evilness fixed this issue...
v.eval("function sayIt(query, language, cb) { var audio = new Audio(); audio.src = 'http://translate.google.com/translate_tts?ie=utf-8&tl=' + language + '&q=' + encodeURIComponent(query); cb && audio.addEventListener('ended', cb); audio.play();}");
// export it under sayIt variable
sayIt = v.sayIt;
}
I guess that I was able to byPass that restriction. They could potentially fix this hack in the future I don't know. I actually hope they don't...
You can also try to use the Text2Speech HTML5 api, but it is still very young...
IE 11 is not working with this hack, some time in the future I might try to fix it

Even though you see this as a 404 error, you're actually running into a cross-domain restriction.
Some of the response headers from that 404 will also give you a clue of what's going on:
X-Content-Type-Options:nosniff
X-XSS-Protection:1; mode=block
So, you won't be able to do this client-side, as Google does not (and probably will never) allow you to do so.
In order to do this dynamic loading of audio, you need to work around this x-domain restriction by setting up a proxy on your own server, which would download whatever file requested by the end-user from Google's servers (via wget or whatever) and spitting whatever data comes from google.
Code I used to reproduce the issue:
soundManager.setup({
url: 'swf',
onready: function() {
soundManager.createSound({
id:'testsound',
autoLoad:true,
url:'http://translate.google.com/translate_tts?ie=UTF-8&tl=da&q=testing'
});
}
});
Your code should look like this:
soundManager.createSound({
id:'testsound',
autoLoad:true,
url:'/audioproxy.php?ie=UTF-8&tl=da&q=testing' // Same domain!
});
Regards and good luck!

Related

Dynamic Links from a CMS - Error: "redirect" can not be returned from getStaticProps during prerendering

I have a Next JS app connected to a CMS and hosted on Vercel - all links are dynamic and the pages are created by the content authors.
I am trying to create dynamic redirects that will force URLs to adhere to formats that are better for SEO. For example:
Enforce lowercase URLs
Replace spaces with dashes
Remove trailing slashes
For example, /test/Author Name/ would redirect to /test/author-name
Since I need to trigger a 301 redirect for these wrong URLs, the only way to do this with Next JS from what I have found is to return a Redirect from getStaticProps, this is what I have so far:
export const getStaticProps: GetStaticProps = async (context) => {
let requestedUrl = '/';
if (context?.params?.path) {
requestedUrl = '/' + (context?.params?.path as string[]).join('/');
}
//check for URLs with uppercases, spaces, etc. and clean them up
let modifiedUrl = requestedUrl;
modifiedUrl = modifiedUrl.trim().toLowerCase().replace(/\s\s+/g, ' ').replace(/\s/g, '-');
if (modifiedUrl != requestedUrl) {
return {
redirect: {
destination: modifiedUrl,
permanent: true,
},
};
}
This works wonderfully well running locally and connected to the CMS - everything is working as it should and all "faulty" URLs are corrected with the correct response code.
Sadly, this does not work on build, I have spent so much time so far trying to find an alternative, but no matter what I do, the build on Vercel fails with the error:
"redirect" can not be returned from getStaticProps during prerendering
The next best potential solution is to use Middleware, but that requires v.12 at least. Due to limitations from the CMS connector, we are forced to use Node v.11 :(
The alternative that I have built is to use router.push on the client side, but this... just looks terrible. The page loads, returns a 200, and then loads again with the corrected URL. Not good for the user's experience.
Any advice or suggestions? I am baffled that something this simple is this complicated with Next JS!
I resolved the issue... it looks like redirects on statically generated pages are not possible unfortunately. I removed getStaticProps and getStaticPaths, and added getServerSideProps instead. The redirects are now working correctly, but the site is not as fast as we are losing out on SSG.

Authentication That Doesn't Require Javascript?

I have a Web API app, initialized thusly:
app.UseCookieAuthentication();
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
app.UseOAuthBearerTokens(OAuthOptions);
app.UseGoogleAuthentication();
For calls to most controllers, it works great. However, it also requires a bit of javascript before client-side service calls are made:
function getSecurityHeaders() {
var accessToken = sessionStorage["accessToken"] || localStorage["accessToken"];
if (accessToken) {
return { "Authorization": "Bearer " + accessToken };
}
return {};
}
The problem is that we have a certain type of controller (one that accesses files) where no javascript can be run during the call. For example, the call might be to:
http://mysite/mycontroller/file/filename.jpg
...where the value is assigned as the src attribute of an img tag. The call works, but Thread.CurrentPrincipal.Identity is unauthenticated with a null name, so there's currently not a way to enforce security.
I'm new to Web API, so it may be a dumb question, but what's the way around this? What switches do I need to flip to not require javascript to add security headers? I was considering trying to find a way to force an authorization header in an IAuthorizationFilter or something, but I'm not even sure that would work.
So I figured out the solution to my problem.
First, I needed to configure the app to use an authentication type of external cookies thusly:
//the line below is the one I needed to change
app.UseCookieAuthentication(AuthenticationType = DefaultAuthenticationTypes.ExternalCookie);
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
app.UseOAuthBearerTokens(OAuthOptions);
app.UseGoogleAuthentication();
Second, it turned out there was a line of code in my WebApiConfig file that was disabling reading the external cookie:
//this line needed to be removed
//config.SuppressDefaultHostAuthentication();
After that, I could see the external cookie from Google, which passed along an email address I could identify the user with.

Ajax.Updater output garbled only on iPhone first load

When a user loads my page for the first time on an iPhone (works fine on Android, IE, FF,
Opera, Chrome, Safari), the two portions of the page generated by a Prototype/Scriptaculous Ajax.Updater call are garbled - they look as if a binary file were injected into the page or the character map was scrambled. If the user then reloads the page, or uses the page's tabs to navigate around via Ajax.Updater requests, everything is then fine. It's only the very first time the page is loaded in a browser session that this occurs. Here are the relevant calls with a bit of context:
soundManager.onready(function(){
new Ajax.Updater('PlayerSet', 'http://' + location.host +
playerHTMLloc, {method: 'post', onComplete: startPlayer});
});
This is only called once per site visit (so the user has to reload in order to get it to display correctly). It calls a python script that writes html to stdout.
Here's the other:
show: function(elm) {
var id = elm.identify();
elm.addClassName(id.sub('-html', '-selected'));
var link = 'ajax/' + id.sub('-', '.');
$('centercontent').update('<div id="floaterForSpinner"></div><div
id="centerSpinner"><img src="images/ajax-loader.gif"></div>');
new Ajax.Updater('centercontent', link, {evalScripts: 'true',
method: 'post'});
}
This is part of a small class that handles tabs on the page. Again, only the first time show() is called does the error occur. After that the tabber works normally. The updater is just pulling html text files from the server.
The issue occurs with both Prototype/Scripty 1.6.1/1.8.3 and 1.7/1.9.0.
The post and receive headers are identical for the first and subsequent loads, and the acceptable charset is Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7 in all cases per Firebug.
I don't have an iPhone myself, and none of the off or online iPhone simulators I've tried reproduce the problem, so testing this is going to be a nightmare. Hence, anything anyone could do to help, would be, uh, very... helpful.
UPDATE based on questions I received on the GG prototype list:
All the code above is called after the DOM is loaded:
document.observe('dom:loaded', function() {
Ajax.Responders.register({onCreate: removeListeners});
Ajax.Responders.register({onComplete: postAJAX});
new Lightbox();
initMailList();
AT = new AjaxTabber('tablist');
initInternalLinkListener();
initIE6msgClose();
$('PlayerSet').update('<div style="text-align:center">
<img src="images/ajax-loader.gif"></div>');
soundManager.onready(function(){
new Ajax.Updater('PlayerSet', 'http://' + location.host +
playerHTMLloc, {method: 'post', onComplete: startPlayer});
});
});
AjaxTabber is the tab class that contains the show() function I mentioned earlier. The document.observe function above is in the last js file in the header.
UPDATE #2:
Replacing
document.observe('dom:loaded', function() {
with
Event.observe(window, 'load', function() {
in the 3rd code block fixes the garbled loads. However, the fix raises new questions/issues:
Why do the Ajax.Updater loads need to have the entire page loaded to work correctly? A DOM load should be all that's necessary. There's no reason to need the images loaded for an ajax load to work.
My overall page performance is now substantially degraded to fix an iPhone only problem. I'd really like to go back to loading once the DOM load is complete.
Calling update() and then Ajax.Updater on the same element one after another like this might introduce timing problems that can be difficult to diagnose. I recommend doing this instead (to add a "loading" indicator to your Ajax-loading element):
new Ajax.Updater('elementID', '/path/to/server', {
parameters: {},
method: 'get',
onCreate: function(){
$('elementID').update('placeholder html here');
},
onSuccess: function(){
// any other cleanup here
}
});
The onCreate callback hook will guarantee to run and complete before the request is sent and the element is updated by A.U.

response.sendRedirect() from Servlet to JSP does not seem to work

I am writing a client server program. I am sending an arraylist from an android phone and I am able to receive the list also. After that I want the servlet to redirect to demo.jsp using response.sendRedirect(), but it just won't redirect. Tried with requestDispatcher.forward() too.
ObjectInputStream in = new ObjectInputStream((InputStream) request.getInputStream());
List<Double> al=(List<Double>)in.readObject();
in.close();
for(int x=0;x<al.size();x++)
{
System.out.println("List");
System.out.println(al.get(x));
}
System.out.println("going to demo.jsp");
response.sendRedirect("demo.jsp");
How is this caused and how can I solve it?
I'm posting this answer because the one with the most votes led me astray. To redirect from a servlet, you simply do this:
response.sendRedirect("simpleList.do")
In this particular question, I think #M-D is correctly explaining why the asker is having his problem, but since this is the first result on google when you search for "Redirect from Servlet" I think it's important to have an answer that helps most people, not just the original asker.
Instead of using
response.sendRedirect("/demo.jsp");
Which does a permanent redirect to an absolute URL path,
Rather use RequestDispatcher. Example:
RequestDispatcher dispatcher = request.getRequestDispatcher("demo.jsp");
dispatcher.forward(request, response);
Since you already have sent some data,
System.out.println("going to demo.jsp");
you won't be able to send a redirect.
You can use this:
response.sendRedirect(String.format("%s%s", request.getContextPath(), "/views/equipment/createEquipment.jsp"));
The last part is your path in your web-app

zend framework urls and get method

I am developing a website using zend framework.
i have a search form with get method. when the user clicks submit button the query string appears in the url after ? mark. but i want it to be zend like url.
is it possible?
As well as the JS approach you can do a redirect back to the preferred URL you want. I.e. let the form submit via GET, then redirect to the ZF routing style.
This is, however, overkill unless you have a really good reason to want to create neat URLs for your search queries. Generally speaking a search form should send a GET query that can be bookmarked. And there's nothing wrong with ?param=val style parameters in a URL :-)
ZF URLs are a little odd in that they force URL parameters to be part of the main URL. I.e. domain.com/controller/action/param/val/param2/val rather than domain.com/controller/action?param=val&param2=val
This isn't always what you want, but seems to be the way frameworks are going with URL parameters
There is no obvious solution. The form generated by zf will be a standard html one. When submitted from the browser using GET it will result in a request like
/action/specified/in/form?var1=val1&var2=var2
Only solution to get a "zendlike url" (one with / instead of ? or &), would be to hack the form submission using javascript. For example you can listen for onSubmit, abort the submission and instead redirect browser to a translated url. I personally don't believe this solution is worth the added complexity, but it should perform what you're looking for.
After raging against this for a day-and-a-half, and doing my best to figure out the right way to do this fairly simple this, I gave up and did the following. I still can't believe there's not a better way.
The use case that necessitates this is a simple record listing, with a form up top for adding some filters (via GET), maybe some column sorting, and Zend_Paginate thrown in for good measure. I ran into issues using the Url view helper in my pagination partial, but I suspect with even just sorting and a filter-form, Zend_View_Helper_Url would still fall down.
But I digress. My solution was to add a method to my base controller class that merges any raw query-string parameters with the existing zend-style slashy-params, and redirects (but only if necessary). The method can be called in any action that doesn't have to handle POSTs.
Hopefully someone will find this useful. Or even better, find a better way:
/**
* Translate standard URL parameters (?foo=bar&baz=bork) to zend-style
* param (foo/bar/baz/bork). Query-string style
* values override existing route-params.
*/
public function mergeQueryString(){
if ($this->getRequest()->isPost()){
throw new Exception("mergeQueryString only works on GET requests.");
}
$q = $this->getRequest()->getQuery();
$p = $this->getRequest()->getParams();
if (empty($q)) {
//there's nothing to do.
return;
}
$action = $p['action'];
$controller = $p['controller'];
$module = $p['module'];
unset($p['action'],$p['controller'],$p['module']);
$params = array_merge($p,$q);
$this->_helper->getHelper('Redirector')
->setCode(301)
->gotoSimple(
$action,
$controller,
$module,
$params);
}