Thursday, June 30, 2016

How can I stop my page from scrolling when I annotate on a touch device?

Leave a Comment

The problem is on this page: http://www.tagalogreader.com/document.php?id=28.

I'm using this: https://github.com/aron/annotator.touch.js with this https://github.com/openannotation/annotator.

There is one annoying bug that I have found when using my ipad. When I highlight some text and then click "annotate" the box pops up to write a note. That is desired. But what happens next is that somehow I'm automatically scrolled to the middle of the article even though I was highlighting something in the beginning of the article. So I just have to scroll back up.

How can I fix this problem?

1 Answers

Answers 1

Here is a plugin that disables the scrollbar when Annotator Editor is shown:

/** * Annotator Plugin to diasble scrollbar when Editor is shown */ Annotator.Plugin.DisableScroll = function (element, options) {   var myPlugin = {};   myPlugin.pluginInit = function () {     // This annotator instance     this.annotator         .subscribe("annotationEditorShown", function (editor, annotation) {           $(window).disablescroll();         })         .subscribe("annotationEditorHidden", function (editor) {           $(window).disablescroll("undo");         })   };   return myPlugin; }; 

It depends on the jQuery Plugin written by Josh Harrison.

Usage:

jQuery(function ($) {     $('#content').annotator().annotator('addPlugin', 'DisableScroll'); }); 

Demo: http://jsbin.com/saratucapa/1/edit?js,output

Read More

OPTIONS (failed) only on Chrome and Firefox

Leave a Comment

I make a POST request and the request just sits, pending until it eventually fails. I've monitored the nginx logs and the node server logs and the request doesn't even register. This works for anyone else that I've had test it except one other colleague. If I use the edge browser or a different computer it works fine.

I have attempted to make POST requests to other (custom) servers and it hangs on options there as well. I have also made the POST request with jQuery and it fails the same way.

It's maybe worth noting that I am using the withCredentials flag.

Headers:

Provisional headers are shown Access-Control-Request-Headers:content-type Access-Control-Request-Method:GET Origin:http://localhost:8080 Referer:http://localhost:8080/<path> User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.84 Safari/537.36 

The request:

  public login(user) {     const endpoint = `http://<url>`;      let headers = new Headers();     headers.append('Content-type', 'application/json');      return this.http       .post(endpoint, JSON.stringify(user), {         headers: headers,       });    } 

I subscribe to the call in my component:

this._accountService.login(this.user)         .subscribe(res => {             console.log("logged in!");             if (res.json().status === "success") {                 window.location.href = `/home/${this.org}/${this.product}`;             }             else {                 // What other options are there?                 console.log("Do something else maybe?");             }         },         err => {             this.invalidLogin = true;             console.log("Ye shall not pass!");         }); 

Successful user's headers

Accept:*/* Accept-Encoding:gzip, deflate, sdch Accept-Language:en-US,en;q=0.8 Access-Control-Request-Headers:content-type Access-Control-Request-Method:POST Connection:keep-alive Host:<url> Origin:<url> Referer:http://apps-dev.eng.stone-ware.com/welcome/ibm/luw User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.33 Safari/537.36 

From chrome://net-internals/#events

t=61869793 [st=    0] +REQUEST_ALIVE  [dt=60162]                        --> has_upload = false                        --> is_pending = true                        --> load_flags = 34624 (DO_NOT_SAVE_COOKIES | DO_NOT_SEND_AUTH_DATA | DO_NOT_SEND_COOKIES | MAYBE_USER_GESTURE | VERIFY_EV_CERT)                        --> load_state = 14 (WAITING_FOR_RESPONSE)                        --> method = "OPTIONS"                        --> net_error = -1 (ERR_IO_PENDING)                        --> status = "IO_PENDING"                        --> url = "<url>" t=61929955 [st=60162]   -HTTP_STREAM_PARSER_READ_HEADERS                          --> net_error = -324 (ERR_EMPTY_RESPONSE) t=61929955 [st=60162]   -HTTP_TRANSACTION_READ_HEADERS                          --> net_error = -324 (ERR_EMPTY_RESPONSE) t=61929955 [st=60162]   -URL_REQUEST_START_JOB                          --> net_error = -324 (ERR_EMPTY_RESPONSE) t=61929955 [st=60162]    URL_REQUEST_DELEGATE  [dt=0] t=61929955 [st=60162] -REQUEST_ALIVE                        --> net_error = -324 (ERR_EMPTY_RESPONSE) 

I'm really guessing this is related to something that is cached in my browser(s) but I really cannot find what. I've cleared all cookies and anything that could be stored. Where else can I check to clear things? This is clearly something local to my computer/browser (and one other unfortunate person).

4 Answers

Answers 1

Please try to subscribe() to the observable.

return this.http   .post(endpoint, JSON.stringify(user), {     headers: headers,   }).subscribe(() => console.log("POST done!")); 

Answers 2

Have you tried setting the 'Cache-Control' in your headers? I think in jQuery you can simply set

$.ajax({       cache: false  }); 

or adding a header with a regular ajax request

request.setRequestHeader("Cache-Control", "no-cache");  

Answers 3

There are issues with CORS and using localhost as the domain (which you have listed in the ORIGIN headers). Typically CORS / OPTIONS requests don't work properly when localhost is involved for certain security reasons, but hanging isn't normally what happens so this might not be the correct answer but its worth a shot!

Try adding a new host to your local machine and removing localhost from the equation. Just throwing this idea out there and hope that it might help you out!

Answers 4

Why don't you just prevent getting into OPTIONS request loop . It really drives you crazy at times . Other browsers do not trigger OPTIONS request but chrome and firefox does to ensure CORS . I have successfully used this library named as xdomain from github , and it really works !! Their github introduction page introduce xdomain as a CORS alternative . And most importantly i used it in JQuery , but it also does support Angular's http service . Have a look at it . It may help you for good :) . Here's the link to library Xdomain CORS Alternative

Read More

Remove default Android padding from HTML emails

Leave a Comment

I have a responsive email layout where some elements stretch the entire width of the viewport, whatever that may be.

In Android (native mail and Gmail app on 4.4 at least) There appears to be a ~10px padding on either side. Is there any property or trick for negating this?

(I feel like this question should have been asked somewhere already, but searches provide only completely unrelated HTML email margin issues, so sorry if this is a duplicate).

Tried

Cancelling out the body margin. This affected the layout but did not fix the issue. The result of the following code simply removed the padding on the left but doubled the padding on the right in the native app.

html, body{     padding:0 !important;     margin:0 !important;     width:100% !important; } div[style*="margin: 16px 0"] {      margin:0 !important;      font-size:100% !important;      width:100% !important;  } 

No change in the Gmail app.

More insights

It seems the body remains the same width in the viewport regardless of width settings. If you set the width to 1000px, the email is shrunk to fit in the area with the margin on either side. The margin can be cancelled out using margin:0 on the body but the body stays the same size, resulting in the extra space appearing on the right.

I believe that the client is programmatically resizing the email to fit in a given width. The only way around this is likely to somehow "trick" the client. Nothing seems to have worked yet...

1 Answers

Answers 1

The problem is simply margins, the Android 4.4 email client is applying a margin value on all sides (but its not actually visible on the right side), so even before your email message is rendered, its messed with overall viewport already.

You can normalize it, via the below block.

body { margin:0 !important; } div[style*="margin: 16px 0"] { margin:0 !important; font-size:100% !important; } 

https://blog.jmwhite.co.uk/2015/09/19/revealing-why-emails-appear-off-centre-in-android-4-4-kitkat/

Read More

Ionic hybrid app: Select multiple not working on some devices

Leave a Comment

I have a selectbox where you can select multiple failure types:

<select name="failureType" ng-model="model.failureType" required ng-options="item.name for item in data.failureType" form="regFailForm" label='{{"FAILURETYPE" | translate}}' multiple> <option value=""></option> </select>

This "works on our machines" but on some devices of the client they can't select multiple items. Like for example the LG G2 (LG-D802) with Android 4.4.2.

Is there a fix for this?

Moto G LG G2

2 Answers

Answers 1

i got an issue similar to this , i fixed it with cross walk project it makes all version of android behave the same but it added extra size to your apk

Check Here

OR Check from docs ON

Answers 2

correct code:

<select  name="failureType" ng-model="model.failureType" required    ng-options="item.name for item in data.failureType"    form="regFailForm"     label='{{"FAILURETYPE" | translate}}'    ng-multiple="true" multiple>     <option value=""></option> </select> 
Read More

Receiving “400 Bad Request” for /oauth/access_token

Leave a Comment

I have approved for public_content clientId. To get access token, I send a request to www.instagram.com:

GET /oauth/authorize?client_id=MyClientId&redirect_uri=MyRedirectURL&response_type=code&scope=likes+comments+public_content HTTP/1.1` 

After authentication, the browser redirects me to MyRedirectURL and I can get the code from the URL.

With this code I send a request to api.instagram.com:

/oauth/access_token HTTP/1.1 

client_id=MyClientId&client_secret=MyClientSecret&grant_type=authorization_code&redirect_uri=MyRedirectURL&code=CodeFromURL`

But sometimes I get response HTTP/1.1 400 Bad Request. This situation continues for a few hours, and sometimes for a day. It is interesting that the problem is very unstable. I may have two client apps that make identical requests, and one app will work fine, while the other will fail at the same time. Looks like it is a problem somewhere in the Instagram infrastructure.

2 Answers

Answers 1

Instagram is no longer supporting custom schemas for your callback urls. That was my problem, I changed it to https and the problem was solved.

Answers 2

This seems slightly relevant.

Also here they don't list any examples which is not http(s) :)

Read More

Wednesday, June 29, 2016

Dagger 2 lifecycle of a component, module and scope

Leave a Comment

I've read a lot of posts and tutorials about dagger 2:

http://frogermcs.github.io/dependency-injection-with-dagger-2-custom-scopes/

https://github.com/codepath/android_guides/wiki/Dependency-Injection-with-Dagger-2

http://fernandocejas.com/2015/04/11/tasting-dagger-2-on-android/

https://github.com/konmik/konmik.github.io/wiki/Snorkeling-with-Dagger-2

What determines the lifecycle of a component (object graph) in Dagger 2?

etc.

But I am still confused about the lifecycle of a component, and how it relates to module and scope. I want to make sure I don't create multiple instances of an object when I only want a Singleton. Hope someone can shed some light on these:

What's the lifecycle of a component that's built in the application class?

What's the lifecycle of a component that's built in the Activity or Fragment class?

If I want a singleton instance from a component, do I must annotate the component with @Singleton or a custom made scope and build that component in the application class?

If I build a component in the application class, does that mean all the object instances available through this component will be a singleton instance throughout the app until the app is killed or restarted?

I have a component with a custom scope let's say @ActivityScope, and I build that component in an Activity, will the object instances injected through this component be destroyed automatically after this activity's onDestroy() is called?

Again I have a component with a custom scope let's say @ActivityScope, and I build this component in ActivityA and ActivityB, will ActivityA and ActivityB share the same object instances from this component or they will have their own instances of the same object?

0 Answers

Read More

Why can I not place Master and Detail view next to each other in UISplitViewController on the first run, but upon rotation it works?

1 comment

I have a split view controller that has a list of items on the left and a detail view on the right. Relevant code in AppDelegate:

let splitViewController = mainView.instantiateViewControllerWithIdentifier("initial") as! UISplitViewController            let rightNavController = splitViewController.viewControllers.last as! UINavigationController         let detailViewController = rightNavController.topViewController as! DetailsIpad          let leftNavController = splitViewController.viewControllers.first as! UINavigationController         let masterViewController = leftNavController.topViewController as! MainViewController          masterSplitViewController = masterViewController         detailSplitViewController = detailViewController          // Override point for customization after application launch.         let navigationController = splitViewController.viewControllers[splitViewController.viewControllers.count-1] as! UINavigationController         navigationController.topViewController!.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem()         splitViewController.delegate = self          self.window!.rootViewController = splitViewController 

When I first launch the app I see that the right part of the split screen takes up all of the screen:

enter image description here

If I rotate the screen, it becomes properly set (probably because both views are present on the screen):

enter image description here

When I set breakpoints everywhere, I see that the detail view on the right gets loaded before the master view on the left (list of items), despite not being called directly. I cannot change the order in which the views of the split screen are called. How can I fix this?

1 Answers

Answers 1

It's the default behavior of UISplitViewController. Have a close look at the following-

// An animatable property that controls how the primary view controller is hidden and displayed. A value of `UISplitViewControllerDisplayModeAutomatic` specifies the default behavior split view controller, which on an iPad, corresponds to an overlay mode in portrait and a side-by-side mode in landscape. @property (nonatomic) UISplitViewControllerDisplayMode preferredDisplayMode NS_AVAILABLE_IOS(8_0); 

Here's the key part from same definition-

on an iPad, corresponds to an overlay mode in portrait and a side-by-side mode in landscape.

Also, if you want to query the current state (display mode) of a UISplitViewController you should use this property-

// The actual current displayMode of the split view controller. This will never return `UISplitViewControllerDisplayModeAutomatic`. @property (nonatomic, readonly) UISplitViewControllerDisplayMode displayMode NS_AVAILABLE_IOS(8_0); 

And remember, you can't compare this with UISplitViewControllerDisplayModeAutomatic because-

This will never return UISplitViewControllerDisplayModeAutomatic.

My suggestion would be to set preferredDisplayMode to the value you want. In your case, it seems like you need the primary (master) to always be visible. So here's the proposed solution-

mySplitVC.preferredDisplayMode = UISplitViewControllerDisplayModeAllVisible 

Why it loads the secondary(detail) controller first?

As you can see, a UISplitViewController instance always needs a detail view no matter what displayMode it is in currently. So it's a good call to

  • load the detail view first.
  • load the primary view after (conditionally based on displayMode).

Hope this helps.

Read More

Tuesday, June 28, 2016

Cannot read property 'bcrypt' of undefined with Meteor

Leave a Comment

I am following the Basic Tutorial to use TurkServer, but I get an error from the beginning.

The error I get when I run: meteor --settings settings.json

W20160615-01:19:27.320(-4)? (STDERR)  W20160615-01:19:27.406(-4)? (STDERR) ~/.meteor/packages/meteor-tool/.1.3.3.b5ue33++os.osx.x86_64+web.browser+web.cordova/mt-os.osx.x86_64/dev_bundle/server-lib/node_modules/fibers/future.js:280 W20160615-01:19:27.406(-4)? (STDERR)  throw(ex); W20160615-01:19:27.407(-4)? (STDERR)       ^ W20160615-01:19:27.407(-4)? (STDERR) TypeError: Cannot read property 'bcrypt' of undefined W20160615-01:19:27.407(-4)? (STDERR)     at AccountsServer.Accounts._checkPassword (packages/accounts-password/password_server.js:68:33) W20160615-01:19:27.407(-4)? (STDERR)     at ~/interactiveEstimation/.meteor/local/build/programs/server/packages/mizzao_turkserver.js:4881:18 W20160615-01:19:27.407(-4)? (STDERR)     at ~/interactiveEstimation/.meteor/local/build/programs/server/boot.js:298:5 => Exited with code: 8 

My settings file:

{   "turkserver": {     "adminPassword": "mmaatouq95",     "experiment": {       "limit": {       }     },     "mturk": {       "accessKeyId": "AKIAJDDHTM3IRYMWUX7Q",       "secretAccessKey": "eeTud7Gml3Yz6XD9gWLUZzsJokoie2rEq"     }   } } 

It seems general problem with Meteor, not with TurkServer (the project files https://www.dropbox.com/s/ppgbuwv4k3imbt5/interactiveEstimation.zip):

1 Answers

Answers 1

When examining your project, your user does not contain a bcrypt entry.

This indicates that it was not created properly and this leads to the described error.

If you delete the user from the meteor mongo database console and restart the server, the user should be created properly and the issue should be resolved.

Read More

Rails 5 rendering from outside a controller with ApplicationController.renderer.render doesn't set variables on self

Leave a Comment

I'm using the Rails 5 ApplicationController.renderer.render method to render from within a model. I need to pass some variables to my layout which I have done using the locals option; this variable is then available in the layout if accessed directly, but not via self.

Here is how I have setup my render

html_string = ApplicationController.renderer.render(   file: "/#{template_path}/base/show",   :formats => [:pdf,:html],   locals: {     :@routing_form => self,     :controller_name => controller_name,     :action_name => action_name,     :current_user => current_user   },   :layout  => '/layouts/application' ) 

Then within the layout I want to do something like this.

<div id="foo" class="<%= self.action_name %>"> 

I was able to get this working by dropping self in this particular instance

<div id="foo" class="<%= action_name %>"> 

but now my concern is how would I set a variable so that it would work correctly with self? Previously I was using the render_anywhere gem and this was handled using rendering_controller.var = "value"

1 Answers

Answers 1

Since self is a keyword in Ruby, you cannot use it as a method call in your layout template, so you should use another name to pass with the locals.

You can pass something like my_object: self and it will work fine.

If you want to name the key with a @, you should put it inside a string '@my_object': self and calls it normally in your template: <%= @my_object.action_name%>

Read More

Size Class compact height doesn't work properly with UIStackView's axis and real device

Leave a Comment

This is how it looks like in my storyboard and Preview:

enter image description here

And this is what I set up in storyboard for that UIStackView:

enter image description here

But everything changes when I run this on real device:

enter image description here

Why it happens like that?

Please note that I have here two UIStackViews: icon with labels box, two buttons. The second one works correctly, but not the first one. Why? it is done exactly the same way. Two direct subviews of UIStackView

EDIT

I realised that problem arise ONLY with UIImageView as direct subview of UIStackView.

1 Answers

Answers 1

Just tap the "+" button disribution section and choose Any x Compact height and fill equally. I hope this works well.

Read More

Does github (twitter, stripe & co) uses oauth for its own login?

Leave a Comment

Does github (twitter, stripe & co) uses OAuth for its own signin/signup forms?

All those authentications are cookie based, so is this regular web client basic auth or does it use some form of OAuth or xAuth ?

On login, a call to https://github.com/session (or https://twitter.com/sessions or https://dashboard.stripe.com/ajax/sessions) is made (with credentials given as formdata) that result in a 302 (or 200 for stripe) with Set-Cookie and a location to https://github.com (or https://twitter.com).

It does not seems that they use a client_id to get a code and exchange it with a token. All the OAuth dance seems striped. And the Bearer header too. So, what's going on here?

Thanks.

1 Answers

Answers 1

OAuth is a three-legged system, two-legs is sort of useless. The whole point of using OAuth is to give other services the ability to perform actions as you without needing to to specify authenticate or pass the data yourself. In the end you must still authenticate against some Auth service.

Since you are using these services as the Authentication mechanism for other sites, it wouldn't make sense to attempt to use it in your own. As part of setting OAuth, the second site redirects to the first and asked to authenticate there, which means you literally need to enter your credentials. Which means that if you are okay entering your credentials into say github, having a different authentication mechanism is useless.

OAuth allows non-github to create user accounts by trusting github with the authentication, or it allows non-github sites to make changes to github as the user once the user agrees to the interaction by logging into github to accept that policy (logging in using their credentials).

Read More

Monday, June 27, 2016

CORS not working with route

Leave a Comment

I have an issue with an endpoint on my web api. I have a POST method that is not working due to:

Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 405.

I cannot see why that is not working since I have plenty of methods that are working indeed with the same COSR configuration. The only difference is that this method has a specified route, as you can see below:

// POST: api/Clave         [EnableCors(origins: "*", headers: "*", methods: "*", SupportsCredentials = true)]         [Route("{id:int}/clave")]         [HttpPost]         public HttpResponseMessage Post(int id, [FromBody]CambioClaveParameters parametros)         {             UsuarioModel usuario = SQL.GetUsuario(id);              if (Hash.CreateMD5(parametros.ViejaClave) != usuario.Clave.ToUpper())             {                 return Request.CreateResponse(HttpStatusCode.BadRequest);             }             else if (Hash.CreateMD5(parametros.ViejaClave) == usuario.Clave.ToUpper())             {                 SQL.ModificarClaveUsuario(id, Hash.CreateMD5(parametros.NuevaClave));                  return Request.CreateResponse(HttpStatusCode.OK);             }             else             {                 return Request.CreateResponse(HttpStatusCode.InternalServerError);             }         } 

Any Ideas of why this is happening?.

Thanks!.

4 Answers

Answers 1

if you are using web api just create one class at root level name it Startup.cs If you can try adding following code in your startup and see if that works. This code will inject cors middelware in ur application pipeline. You probably need to add owin via nuget. Give it a try

[assembly: OwinStartup(typeof(MyProject.API.Startup))]  namespace MyProject.API {     public class Startup     {         public void Configuration(IAppBuilder app)         {             app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);             app.UseWebApi(WebApiConfig.Register());         }      } } 

Answers 2

Your Web API response is clearly a 405, which indicates that you are calling an URI that does not support your HTTP Method (in this case POST).

Starting from this you need to understand why your URI does not support POST. The most probable answer is that you are calling the wrong URI. The fact that you are getting a CORS error is not the root of your problem and derives from the fact that the wrong URI you are calling does not set any Access-Control-Allow-Origin header.

Looking at your controller method:

[EnableCors(origins: "*", headers: "*", methods: "*", SupportsCredentials = true)] [Route("{id:int}/clave")] [HttpPost] public HttpResponseMessage Post(int id, [FromBody]CambioClaveParameters parametros) 

It appears to me that you are using a Route attribute, but not setting a RoutePrefix attribute in your controller class.

This means that the correct URI for your method is the following one:

http://localhost:xxxx/1/clave 

And not, as you might think, that one:

http://localhost:xxxx/api/Clave/1/clave 

If you want to access your resource using the second URI you need to put a new RoutePrefix attribute in your Controller:

[RoutePrefix("api/Clave")] public class ClaveController : ApiController {     //.. } 

Answers 3

Hope you are doing good ! you can use below code that will allow origin access on each request response.

 protected void Application_BeginRequest(object sender, EventArgs e)         {    HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", *");} 

for more reference you can get help from below link. http://enable-cors.org/server_aspnet.html

Answers 4

Based upon the word "preflight" in your message, this is an OPTIONS verb issue. If you examine the requests and responses, I believe you'll see that the request directly before your POST is an OPTIONS request. The OPTIONS request is asking the server what methods are allowed to be called. If you haven't enabled an OPTIONS response, or your OPTIONS response doesn't include the POST method for that Uri, you'll get this response.

Here's a link describing the concept (see section Preflight CORS Requests) https://msdn.microsoft.com/en-us/magazine/dn532203.aspx

To account for this bypassing everything OPTIONS is designed to do, you can add code similar to this (don't be a cargo-cult programmer) to a new or existing module's BeginRequest method:

if (context.Request.HttpMethod.ToLower() == "options") {    var origin = context.Request.Headers["origin"];    context.Response.StatusCode = 200;    context.Response.AddHeader("Access-Control-Allow-Origin", origin);    context.Response.AddHeader("Access-Control-Allow-Credentials", "true");    context.Response.AddHeader("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, OPTIONS");    context.Response.End(); } 

Ideally, though, you would want to programmatically determine whether the request is a valid, and if so, then output a response customized for what is actually allowed.

Read More

Using py.test with compiled library code

Leave a Comment

I have a python library with the following repository structure:

repobase  |- mylibrary  |  |- __init__.py  |- tests     |- test_mylibrary.py 

Up to now, running the tests could simply be done by calling py.test in the repobase directory. The import mylibrary in test_mylibrary.py then used the local code in repobase/mylibrary.

Now, I've extended the library to use compiled code. Therefore the source code at repobase/mylibrary is not functional on its own. I have to do a setup.py build. This creates repobase/build/lib.linux-x86_64-2.7/mylibrary.

Is there a reasonable way to make py.test use this directory for importing mylibrary? Given these constraints:

  1. I do not want to include any sys.path / import magic in test_mylibrary.py because this may break tests in other envrionments.

  2. I don't want to give up the possibility to run py.test from repobase. Therefore modifying the PYTHONPATH does not help because . will still be first in sys.path. And thus repobase/mylibrary would be favored over repobase/build/lib.linux-x86_64-2.7/mylibrary.

If not, what's the standard way for testing python libraries, that need building?

2 Answers

Answers 1

I think your problem is simply that py.test is not copying the built shared object to the root of your repository.

I just tried running the UT straight from the Python wiki on testing C extensions using py.test as follows:

python setup.py build py.test test/examp_unittest.py 

This failed with AssertionError: No module named examp.

However, when I follow the wiki to the letter (and run python setup.py test instead), I note that it copies the .so to the root directory (note the last line before it starts running the test):

running test running egg_info writing examp.egg-info/PKG-INFO writing top-level names to examp.egg-info/top_level.txt writing dependency_links to examp.egg-info/dependency_links.txt reading manifest file 'examp.egg-info/SOURCES.txt' writing manifest file 'examp.egg-info/SOURCES.txt' running build_ext copying build/lib.linux-x86_64-2.6/examp.so -> runTest (test.examp_unittest.DeviceTest) ... ok  ---------------------------------------------------------------------- Ran 1 test in 0.001s  OK 

Having run that on my system, I can now run py.test quite happily on the same code base - as shown below.

============================= test session starts ============================== platform linux2 -- Python 2.7.3, pytest-2.9.2, py-1.4.31, pluggy-0.3.1 rootdir: /tmp/sotest, inifile:  collected 1 items   test/examp_unittest.py .  =========================== 1 passed in 0.01 seconds =========================== 

The solution is therefore to copy your shared object to the root of your repository.

To make sure I have run the whole thing from scratch, just building the extension, copying the shared object and then running py.test. This all works as expected.

Answers 2

From the discussion in chat, it sounds as if the C implementation only provides a subset of the functionality of the Python implementation.

A common solution is to split the module such that the parts which require optimized implementations exist in a separate module.

Consider a more concrete example of a library which needs convert between different image formats.

Let's assume your layout looks like this...

repobase  |- image  |  |- __init__.py  |  |- pyJPEG.py  |- build  |  |- lib.linux-x86_64-2.7  |     |- cJPEG.so  |- tests     |- test_image.py 

...your PYTHONPATH includes /path/to/repobase:/path/to/repobase/build/lib.linux-x86_64-2.7, your cJPEG.so exports symbols jpeg_decompress and jpeg_compress, and your files look like this...

image/__init__.py

# Load the C implementation if we have it, otherwise fall back to # a pure Python implementation try:     from cJPEG import jpeg_decompress, jpeg_compress except ImportError:     from pyJPEG import jpeg_decompress, jpeg_compress  def load_image(filename):     data = open(filename, 'rb').read()     if filename.endswidth('.jpg'):         return jpeg_decompress(data)     else:         raise NotImplementedError  def save_image(data, filename, filetype='JPEG'):     if filetype == 'JPEG':         data = jpeg_compress(data)     else:         raise NotImplementedError     open(filename, 'wb').write(data) 

image/pyJPEG.py

def jpeg_decompress(data):     # A pure Python implementation of a JPEG decoder  def jpeg_compress(data):     # A pure Python implementation of a JPEG encoder 

With this sort of layout, the test suite need not care whether the library is built or not - you can use the same suite in both cases, and the presence (or absence) of cJPEG.so will determine which version is tested.

Read More

How to build hsdis.dll for Windows 32-bit?

Leave a Comment

I am trying to build hsdis.dll in my laptop 32-bit Windows. I read http://dropzone.nfshost.com/hsdis.htm instructions and got to know that I will have to follow those steps. I saw that I have to use the mingw64-i686-gcc-core. I followed the steps, but have always found this error.

make[2]: i686-w64-mingw32: Command not found Makefile:246: recipe for target 'libiberty.a' failed make[2]: *** [libiberty.a] Error 127 make[2]: Leaving directory '/home/User/hsdis/build/Linux-i586/libiberty' Makefile:8045: recipe for target 'all-libiberty' failed make[1]: *** [all-libiberty] Error 2 make[1]: Leaving directory '/home/User/hsdis/build/Linux-i586' Makefile:192: recipe for target 'build/Linux-i586/bfd/libbfd.a' failed make: *** [build/Linux-i586/bfd/libbfd.a] Error 2 

I would also like to know how to use the directive PrintAssembly, because i wanted to see the assembly code, of a Java class.

I have already saw other posts here, but none of them helped.

Thanks in advance

1 Answers

Answers 1

Here are the steps which help me to build it (x64 version, x86 should be almost the same):

  • download and unpack the latest hsdis sources as described in the building manual from the http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/tags;
  • download the latest bintuils-2.26.tar.gz package from the http://mirror.tochlab.net/pub/gnu/binutils/;
  • copy it to your Cygwin home directory and unpack it from the Cygwin terminal (this is very important, otherwise you may get permission problems): tar -xzvf ./binutils-2.26.tar.gz
  • install the following Cygwin packages: mingw64-x86_64-gcc-core for x64 or mingw64-i686-gcc-core for x86, diffutils and make;
  • go to hsdis directory;
  • for x64 library build with the command: make OS=Linux MINGW=x86_64-w64-mingw32 'AR=x86_64-w64-mingw32-ar' BINUTILS=~/binutils-2.26 CONFIGURE_ARGS="--host=x86_64-w64-mingw32", for x86 library build with the command: make OS=Linux MINGW=i686-w64-mingw32 'AR=i686-w64-mingw32-ar' BINUTILS=~/binutils-2.26 CONFIGURE_ARGS="--host=i686-w64-mingw32"
  • if you have errors with undefined references to zlib (i.e. build/Linux-amd64/bfd/libbfd.a(compress.o):compress.c:(.text+0x7e): undefined reference to inflate), modify Makefile in hsdis: find the line $(CC) $(OUTFLAGS) $(CPPFLAGS) $(CFLAGS) $(SOURCE) $(DLDFLAGS) $(LIBRARIES) for the $(TARGET) target and append to the end -lz -L$(TARGET_DIR)/zlib, then run the build command again;
  • after that you should find the library hsdis-amd64.dll in hsdis\build\Linux-amd64\ for x64, or hsdis-i386.dll in hsdis\build\Linux-i586\ for x86.
Read More

Sunday, June 26, 2016

Android signature verification

Leave a Comment

I have got lot of doubts to be cleared in the case of Android signature verification and its vulnerability.

Once we generate apk for an application we can unpack the apk and edit resource files using apktool. As we repack the edited apk back it loses its signature. I can resign the unsigned apk using the jarsigner with my own private key that i used while generating the apk. I found an application named zipsigner in playstore which can be used to sign such kind of unsigned apk.

So when this zipsigner signs the unsigned apk, whether the apk is signed with my same private key or with a different key? Because my META-INF folder still holds the XXX.SF and XXX.RSA files which holds the information of my private key. If it is with my same private key then the new apk will be an upgrade for my application or if it is a different key i will be having two different applications with same name.

From the above situations there are possibilities that malware could be included in my apk while repacking. There seems to be a loophole in Android's signature verification mechanism where the message digest of the files inside the META-INF folder are not included in the MANIFEST.MF as well as in the XXX.SF file. This creates a possibility for anyone to include malware codes inside these folders, repack the apk and resign it with the zipsigner application.

I was searching for a solution where i can prevent files being added into the META-INF folder and i found one from the below blog. But I'm unable to get the point of the solution. This looks like more of a research topic so there is not much information available in the internet. Can someone try and figure out the solution specified in the blog. The blog link is specified below the question.

http://blog.trustlook.com/2015/09/09/android-signature-verification-vulnerability-and-exploitation/

1 Answers

Answers 1

  1. Private key is never part of a distributed APK, unless I misunderstood your question. Someone else signing on your behalf is not possible unless your own system is hacked.

  2. The shared link (blog.trustlook.com) talks about Android skipping checking of files with .sf (and files with related extensions) extensions. So a malware could cloak itself in a file with one of these extensions. The fix mentioned there is an Android "system firmware" fix, not something that can be done at application level. This means, an OEM (Google itself, or Samsung/other) has to release an updated firmware to fix this. Check the latest updates, it might have been fixed already.

  3. In my opinion, even if an user sideloads APK's, this is more of a nuisance than a real attack/threat. Refer to the Blackhat paper below for further details - https://www.blackhat.com/docs/ldn-15/materials/london-15-Xiao-What-Can-You-Do-To-An-APK-Without-Its-Private-Key-wp.pdf

You should also read this for potential ways of tamper proofing APK - https://www.airpair.com/android/posts/adding-tampering-detection-to-your-android-app

Read More

Saturday, June 25, 2016

Weird behavior of Lucene query parser 5.1.0

Leave a Comment

I am using Lucene Query Parser 5.1.0

These filter queries do not work:

* AND {!tag=guid}guid:(*) * && {!tag=guid}guid:(*) * {!tag=guid}guid:(*) 

it throws

org.apache.solr.search.SyntaxError: Cannot parse 'guid:(*': Encountered \"<EOF>\" at line 1, column 7.\nWas expecting one of:\n <AND> ...\n <OR> ...\n <NOT> ...\n \"+\" ...\n \"-\" ...\n <BAREOPER> ...\n \"(\" ...\n \")\" ...\n \"*\" ...\n \"^\" ...\n <QUOTED> ...\n <TERM> ...\n <FUZZY_SLOP> ...\n <PREFIXTERM> ...\n <WILDTERM> ...\n <REGEXPTERM> ...\n \"[\" ...\n \"{\" ...\n <LPARAMS> ...\n <NUMBER> ...\n

And these filter queries do work:

* AND {!tag=guid}guid:* * AND guid:(*) * AND guid:* * && {!tag=guid}guid:* * && guid:(*) * && guid:* * {!tag=guid}guid:* * guid:(*) * guid:* {!tag=guid}guid:(*) {!tag=guid}guid:* guid:(*) guid:* 

Why the first three do not work? Is it a bug in the query parser?

EDIT: I have found weird behavior also with spaces:

This does work:

* AND {!tag=guid}guid:"a" 

This does not work:

* AND {!tag=guid}guid:"a " 

1 Answers

Answers 1

Tags in FilterQueries are just special kind of LocalParameter used as reference point for faceting in SOLR.

Note that LocalParameters are SOLR specific and are not parsed in any meaningfull way with LuceneQueryParser.

If you are interested in general LocalParameter syntax, you can check:

https://cwiki.apache.org/confluence/display/solr/Local+Parameters+in+Queries

According to that document

Local parameters are arguments in a Solr request that are specific to a query parameter.

and

Basic Syntax of Local Parameters:

To specify a local parameter, insert the following before the argument to be modified:

  • Begin with {!
  • Insert any number of key=value pairs separated by white space
  • End with } and immediately follow with the query argument

You may specify only one local parameters prefix per argument.

You shouldn't therefore prefix Local Parameters with any parts of query as you do. If you really need to use multiple LocalParameters consider splitting big FilterQuery to multiple smaller ones using CNF


Additional usefull resource: https://github.com/apache/lucene-solr/blob/master/solr/core/src/java/org/apache/solr/search/QParser.java

Read More

Getting Product Collection Sorted by minimum price

Leave a Comment

Summary of Work Environment

I am working on a website where we have customer and dealers both. Each Dealer can have their own price for a product.

Production collection data is having another duplicate record (CLONING PRODUCT) for each product having price of that seller. For example if master catalog have IPHONE 6S . than 5 dealers who deal in Iphone 6s can have their own prices. Cloning product creates a new product ID related to Seller ID

Requirement

I need to get the category wise product listing having lowest price of dealer. Also need to sort that listing according to lowest price.

what I tried

Currently I can list out all the products having lowest price according to category.

$productCollection = Mage::getResourceModel('catalog/product_collection')                     ->addAttributeToSelect('sellingprice')                     ->setStoreId($storeId)                     ->joinField('category_id', 'catalog/category_product', 'category_id', 'product_id=entity_id', null, 'left')                     ->addAttributeToFilter('category_id', array('in' => $_POST['category_id']))                     ->addAttributeToFilter('status', array('eq' => 1))                     ->addAttributeToFilter('dis_continue', array('eq' => 0));    $productCollection->addAttributeToFilter('seller_id', array('in' => $seller_list));  $productCollection->addExpressionAttributeToSelect(                     'lowest_price', 'IF(({{special_from_date}}<=now() AND {{special_to_date}}>=now() OR {{special_from_date}} IS NULL AND {{special_price}}>0),{{special_price}},IF({{sellingprice}}>0,{{sellingprice}},{{price}}))', array('special_from_date', 'special_to_date', 'special_price', 'sellingprice', 'price'));   $productCollection->getSelect()->columns('MIN(IF((IF(at_special_from_date.value_id > 0, at_special_from_date.value, at_special_from_date_default.value)<=now() AND IF(at_special_to_date.value_id > 0, at_special_to_date.value, at_special_to_date_default.value)>=now() OR IF(at_special_from_date.value_id > 0, at_special_from_date.value, at_special_from_date_default.value) IS NULL AND at_special_price.value>0),at_special_price.value,IF(at_sellingprice.value>0,at_sellingprice.value,at_price.value))) as l_price')->group('product_name'); 

I find out lowest of selling price , special price , mrp of a dealer.

Using Group By which groups all the data by Product Name , get MINIMUM of Lowest Price , SORTING that according to LOWEST Price.

PROBLEM

As I explained that I am Using GROUP BY Name so that I can have unique products but I am not able to get the PRODUCT ID of associated seller who is having lowest price. I need to get the Seller ID Of having LOWEST PRICE

GROUP BY always Returns the first ROW , but MIN() function gives the lowest of price. First ROW do not have the associated PRODUCT ID of lowest price.....

EDIT - MYSQL QUERY

SELECT `e`.*, `at_category_id`.`category_id`, IF(   at_status.value_id > 0,   at_status.value,   at_status_default.value ) AS `status`, `at_dis_continue`.`value` AS `dis_continue`, `at_seller_id`.`value` AS `seller_id`, `at_popular_product`.`value` AS `popular_product`, IF(   at_special_from_date.value_id > 0,   at_special_from_date.value,   at_special_from_date_default.value ) AS `special_from_date`, IF(   at_special_to_date.value_id > 0,   at_special_to_date.value,   at_special_to_date_default.value ) AS `special_to_date`, `at_special_price`.`value` AS `special_price`, `at_sellingprice`.`value` AS `sellingprice`, `at_price`.`value` AS `price`, IF(   (     IF(       at_special_from_date.value_id > 0,       at_special_from_date.value,       at_special_from_date_default.value     ) <= NOW() AND IF(       at_special_to_date.value_id > 0,       at_special_to_date.value,       at_special_to_date_default.value     ) >= NOW() OR IF(       at_special_from_date.value_id > 0,       at_special_from_date.value,       at_special_from_date_default.value     ) IS NULL AND at_special_price.value > 0   ),   at_special_price.value,   IF(     at_sellingprice.value > 0,     at_sellingprice.value,     at_price.value   ) ) AS `lowest_price`, `at_name`.`value` AS `name`, `at_name`.`value` AS `product_name`, MIN(   IF(     (       IF(         at_special_from_date.value_id > 0,         at_special_from_date.value,         at_special_from_date_default.value       ) <= NOW() AND IF(         at_special_to_date.value_id > 0,         at_special_to_date.value,         at_special_to_date_default.value       ) >= NOW() OR IF(         at_special_from_date.value_id > 0,         at_special_from_date.value,         at_special_from_date_default.value       ) IS NULL AND at_special_price.value > 0     ),     at_special_price.value,     IF(       at_sellingprice.value > 0,       at_sellingprice.value,       at_price.value     )   ) ) AS `l_price` FROM   `catalog_product_entity` AS `e` LEFT JOIN   `catalog_category_product` AS `at_category_id` ON(     at_category_id.`product_id` = e.entity_id   ) INNER JOIN   `catalog_product_entity_int` AS `at_status_default` ON(     `at_status_default`.`entity_id` = `e`.`entity_id`   ) AND(     `at_status_default`.`attribute_id` = '96'   ) AND `at_status_default`.`store_id` = 0 LEFT JOIN   `catalog_product_entity_int` AS `at_status` ON(     `at_status`.`entity_id` = `e`.`entity_id`   ) AND(`at_status`.`attribute_id` = '96') AND(`at_status`.`store_id` = 1) INNER JOIN   `catalog_product_entity_int` AS `at_dis_continue` ON(     `at_dis_continue`.`entity_id` = `e`.`entity_id`   ) AND(     `at_dis_continue`.`attribute_id` = '261'   ) AND(`at_dis_continue`.`store_id` = 0) INNER JOIN   `catalog_product_entity_varchar` AS `at_seller_id` ON(     `at_seller_id`.`entity_id` = `e`.`entity_id`   ) AND(     `at_seller_id`.`attribute_id` = '134'   ) AND(`at_seller_id`.`store_id` = 0) INNER JOIN   `catalog_product_entity_varchar` AS `at_popular_product` ON(     `at_popular_product`.`entity_id` = `e`.`entity_id`   ) AND(     `at_popular_product`.`attribute_id` = '1078'   ) AND(     `at_popular_product`.`store_id` = 0   ) LEFT JOIN   `catalog_product_entity_datetime` AS `at_special_from_date_default` ON(     `at_special_from_date_default`.`entity_id` = `e`.`entity_id`   ) AND(     `at_special_from_date_default`.`attribute_id` = '77'   ) AND `at_special_from_date_default`.`store_id` = 0 LEFT JOIN   `catalog_product_entity_datetime` AS `at_special_from_date` ON(     `at_special_from_date`.`entity_id` = `e`.`entity_id`   ) AND(     `at_special_from_date`.`attribute_id` = '77'   ) AND(     `at_special_from_date`.`store_id` = 1   ) LEFT JOIN   `catalog_product_entity_datetime` AS `at_special_to_date_default` ON(     `at_special_to_date_default`.`entity_id` = `e`.`entity_id`   ) AND(     `at_special_to_date_default`.`attribute_id` = '78'   ) AND `at_special_to_date_default`.`store_id` = 0 LEFT JOIN   `catalog_product_entity_datetime` AS `at_special_to_date` ON(     `at_special_to_date`.`entity_id` = `e`.`entity_id`   ) AND(     `at_special_to_date`.`attribute_id` = '78'   ) AND(     `at_special_to_date`.`store_id` = 1   ) LEFT JOIN   `catalog_product_entity_decimal` AS `at_special_price` ON(     `at_special_price`.`entity_id` = `e`.`entity_id`   ) AND(     `at_special_price`.`attribute_id` = '76'   ) AND(`at_special_price`.`store_id` = 0) LEFT JOIN   `catalog_product_entity_decimal` AS `at_sellingprice` ON(     `at_sellingprice`.`entity_id` = `e`.`entity_id`   ) AND(     `at_sellingprice`.`attribute_id` = '143'   ) AND(`at_sellingprice`.`store_id` = 0) LEFT JOIN   `catalog_product_entity_decimal` AS `at_price` ON(     `at_price`.`entity_id` = `e`.`entity_id`   ) AND(`at_price`.`attribute_id` = '75') AND(`at_price`.`store_id` = 0) LEFT JOIN   `catalog_product_entity_varchar` AS `at_name` ON(     `at_name`.`entity_id` = `e`.`entity_id`   ) AND(`at_name`.`attribute_id` = '71') AND(`at_name`.`store_id` = 0) WHERE   (     at_category_id.category_id IN('119')   ) AND(     IF(       at_status.value_id > 0,       at_status.value,       at_status_default.value     ) = 1   ) AND(at_dis_continue.value = 0) AND(at_seller_id.value IN('1065')) AND(     at_popular_product.value IN('Yes',     'No')   ) GROUP BY   `product_name` 

Please help.

1 Answers

Answers 1

I'm afraid I'm not familiar enough with Magento itself to help directly with your code, but, more generally speaking, this is a common question when it comes to SQL SELECT queries.

GROUP BY

Firstly, an important clarification: When using GROUP BY, any fields in the SELECT part of the query not included in the GROUP BY clause itself may not be legal. The outcome depends on your server version and/or the ONLY_FULL_GROUP_BY SQL mode.

More importantly, assuming your server/configuration supports it, selecting fields not included in the GROUP BY clause means you get a value from an arbitrary row in the group, not the first row. From the MySQL Handling of GROUP BY page in the MySQL documentation:

In this case, the server is free to choose any value from each group, so unless they are the same, the values chosen are indeterminate, which is probably not what you want.

Selecting specific rows within groups

One way of achieving the behaviour you're looking for that has always worked well for me is by using counters and sub-queries to order and filter your sub-groups. This gives you a greater level of control than a GROUP BY (although you do make some performance sacrifices):

SELECT @num := IF(products_name=@last_products_name, @num + 1, 1) b, (@last_products_name := products_name) AS last_pname, t1.* FROM (     SELECT p.products_id, p.products_name, p.selling_price     FROM products p     WHERE p.category_id = 123     ORDER BY p.products_name,     p.selling_price ASC ) t1, (SELECT @num := 0, @last_products_name := 0) d HAVING b=1; 

To understand more clearly how this works, run the query without the HAVING clause. You get a result like this:

+------+------------+-------------+---------------+---------------+ | b    | last_pname | products_id | products_name | selling_price | +------+------------+-------------+---------------+---------------+ |    1 | Bar        |           8 | Bar           |          5.00 | |    2 | Bar        |           2 | Bar           |         12.00 | |    3 | Bar        |           4 | Bar           |         14.00 | |    1 | Fizz       |           3 | Fizz          |         30.00 | |    2 | Fizz       |           5 | Fizz          |         70.00 | |    3 | Fizz       |           7 | Fizz          |        100.00 | |    1 | Foo        |           1 | Foo           |         10.00 | |    2 | Foo        |           6 | Foo           |         18.00 | +------+------------+-------------+---------------+---------------+ 

The b column shows the value of the @num variable, which is incremented for each row in a group of identically named products, and reset each time the product name in the current row is not equal to the name of the last one. Adding the HAVING b=1 clause means we only get the cheapest product in each group.

A potential gotcha when using ORDER BY in sub-queries!

When I last used MySQL, the above solution would work (and I imagine that is still true now). However, this is not actually standard SQL behaviour. Database servers which adhere more strictly to the standard (such as MariaDB) will ignore an ORDER BY clause contained within a sub-query, unless the sub-query also features a LIMIT clause. Therefore, if you are using MariaDB, you need to force the server to honour the ORDER BY by including a LIMIT. A technique I have used before (as described in a comment on the previous link) is to specify a very large LIMIT value:

SELECT @num := IF(products_name=@last_products_name, @num + 1, 1) b, (@last_products_name := products_name) AS last_pname, t1.* FROM (     SELECT p.products_id, p.products_name, p.selling_price     FROM products p     WHERE p.category_id = 123     ORDER BY p.products_name,     p.selling_price ASC     LIMIT 18446744073709551615 -- LIMIT clause forces sub-query ORDER BY ) t1, (SELECT @num := 0, @last_products_name := 0) d HAVING b=1; 

I hope that helps.

Read More

certificate problems trying to send email with libcurl

Leave a Comment

This is my libcurl code. I am trying to send email to my own email domain in linux.

This is my sample libcurl code.

curl_easy_setopt(curl, CURLOPT_USERNAME, "username@mydomain.com");     curl_easy_setopt(curl, CURLOPT_PASSWORD, "mypassword");     curl_easy_setopt(curl, CURLOPT_URL, "smtp://mail.mydomain.com:25");     curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL);     curl_easy_setopt(curl, CURLOPT_MAIL_FROM, FROM);     recipients = curl_slist_append(recipients, TO);     curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients);     curl_easy_setopt(curl, CURLOPT_INFILESIZE, file_size);     curl_easy_setopt(curl, CURLOPT_READFUNCTION, fileBuf_source);     curl_easy_setopt(curl, CURLOPT_READDATA, &file_upload_ctx);     curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);     curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); //Dont display Curl Connection data Change 1L to 0      res = curl_easy_perform(curl); 

When I run this code, I am getting the below error.

* Rebuilt URL to: smtp://mail.mydomain.com:25/ * Hostname was NOT found in DNS cache *   Trying <My mail domain Ip address>... * Connected to mail.mydomain.com (<My mail domain Ip address>) port 25 (#0) < 220 mail.mydomain.com ESMTP > EHLO client6 < 250-mail.mydomain.com < 250-PIPELINING < 250-SIZE 20480000 < 250-VRFY < 250-ETRN < 250-STARTTLS < 250-AUTH PLAIN LOGIN < 250-ENHANCEDSTATUSCODES < 250-8BITMIME < 250 DSN > STARTTLS < 220 2.0.0 Ready to start TLS * successfully set certificate verify locations: *   CAfile: none   CApath: /etc/ssl/certs * SSL certificate problem: self signed certificate * Closing connection 0 curl_easy_perform() failed: Peer certificate cannot be authenticated with given CA certificates 

1 Answers

Answers 1

Your issue is that your server is providing a self-signed certificate so curl is not able to verify its provenance. You have several options:

  • The best option is to get a server certificate that is signed by a well-known certificate authority. Some CAs will issue a certificate you can use for free; search for "free ssl certificate". You will need to be able to provide some proof that you control the domain.

  • You can install your self-signed certificate to the list of trusted CAs on the computer(s) that run your libcurl code. The procedure to do this depends on your OS (even different distributions of Linux may do this differently). This link is a decent starting point for Linux.

  • Your program can tell libcurl to verify with the self-signed certificate. See Adding self-signed SSL certificate for libcurl.

  • You can create your own certificate authority and use either of the previous two approaches. The advantage of this over self-signing is it decouples the signing and the signed certificates. If you want to change the server certificate (e.g. if it expires or the host name changes) you don't necessarily need to reconfigure all the clients.

  • For completeness, you could disable verification by setting CURLOPT_SSL_VERIFYPEER to 0. This is highly discouraged, however, as it makes the access insecure. You should only do this for testing purposes, or in the rare case that the network between client and server is guaranteed to be secure.

Read More

Proper approach to feature detection with opencv

Leave a Comment

My goal is to find known logos in static image and videos. I want to achieve that by using feature detection with KAZE or AKAZE and RanSac.

I am aiming for a similar result to: https://www.youtube.com/watch?v=nzrqH...

While experimenting with the detection example from the docs which is great btw, i was facing several issues:

  • Object resolution: Differences in size between the known object and the resolution of the scene where the object should be located sometimes breaks the detection algorithm - the object won't be recognized in images with a low resolution although the image quality is still allright for a human eye.
  • Color contrast with the background: It seems, that the detection can easily be distracted by different background contrasts (eg: object is logo black on white background, logo in scene is white on black background). How can I make the detection more robust against different luminations and background contrasts?
  • Preprocessing: Should there be done any kind of preprocessing of the object / scene? For example enlarge the scene up to a specific size? Is there any guideline how to approach the feature detection in several steps to get the best results?

1 Answers

Answers 1

I think your issue is more complicated than feature-descriptor-matching-homography process. It is more likely oriented to pattern recognition or classification.

You can check this extended paper review of shape matching:

http://www.staff.science.uu.nl/~kreve101/asci/vir2001.pdf

Firstly, the resolution of images is very important, because usually matching operation makes a pixel intensity cross-correlation between your sample image (logo) and your process image, so you will get the best-crosscorrelated area.

In the same way, the background colour intensity is very important because background illumination could affect severally to your final result.

Feature-based methods are widely researched:

http://docs.opencv.org/2.4/modules/features2d/doc/feature_detection_and_description.html

http://docs.opencv.org/2.4/modules/features2d/doc/common_interfaces_of_descriptor_extractors.html

So for example, you can try alternative methods such as:

Hog descritors: Histogram oriented gradients: https://en.wikipedia.org/wiki/Histogram_of_oriented_gradients

Pattern matching or template matching http://docs.opencv.org/2.4/doc/tutorials/imgproc/histograms/template_matching/template_matching.html

I think the lastest (Pattern matching) is the easiest to check your algorithm.

Hope these references helps.

Cheers.

Unai.

Read More

How can I set videos to “private yet shared” using the v3 YouTube API?

Leave a Comment

I work for a school that has an institutional YouTube account (Google Apps for Education). The video privacy options are Public, Unlisted, and Private.

The important bit: Private videos can be shared with either: - the institution (i.e., all students with a school account), or - a list of specific email addresses.

We have a tool that uses the v3 YouTube API (Java) to automatically upload videos to YouTube.

I can use the API to set privacy:

VideoStatus videoStatus = new VideoStatus(); videoStatus.setPrivacyStatus("private"); 

But how do I set sharing (e.g., "Shared with school.edu") using the YouTube API? I assume it's possible because it can be done (manually) using YouTube's online Video Manager.

3 Answers

Answers 1

It seems more people are being left in the dark about this, but most questions date from some years ago.

E.g.: YouTube API: Private Video Access which links to a YT dev reaction: https://groups.google.com/forum/#!topic/youtube-api-gdata/LkfDtwxjWp8/discussion (May 2012)

There is not, unfortunately, and I don't believe that specific functionality will be added.

Moreover the bug JAL linked to dates from April 2014, so it seems like private video's come with their own set of problems.

To conclude, I'll be sticking to the unlisted video approach, which seems like a good trade-off for me. I can return the unlisted video's for my own set of users, which gives me control on that level. If some user feels like mailing around the YouTube link, that's just too bad. As the aforementioned link states:

Sometimes, security is about compromise. At one end of the spectrum, you can lock things down completely so that no one can access the data. At the other end, the most usable and accessible data will not be secure.

Answers 2

After reviewing the YouTube Data API v3 documentation, I have come to the conclusion that this is not possible with the current API.

This may be related to Issue 6265 that is currently reported as an API defect. If this does not address your use case I strongly suggest you file an enhancement ticket to gdata-issues.

Answers 3

Sounds like bad logic. How about creating a list email addresses and then sharing with that list only. It's kind of confusing to have it private, then shared.

Read More

Friday, June 24, 2016

Receiving touch events outside bounds

Leave a Comment

There have been similar questions before and I have referred to Capturing touches on a subview outside the frame of its superview using hitTest:withEvent: and Delivering touch events to a view outside the bounds of its parent view. But they do not seem to answer my particular problem.

I have a custom control with the following structure:

+-------------------------------+ |           UIButton            | +-------------------------------+ |                          | |                          | |        UITableView       | |                          | |                          | +------------------------- + 

The custom control overrides the UIButton subclass and adds the UITableView as its subView. The idea is to have the whole control act like a dropdown. When the UIButton is pressed, the UITableView will dropdown and enable selection of a choice.

This all works fine with the hitTest overridden in UIButton as described in the Apple's Q&A link above, if the control is an immediate child of the topmost UIView. However, if the control is in another view hierarchy, the UITableView is not receiving touch events.

The following is the hitTest code used:

override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {     // Convert the point to the target view's coordinate system.     // The target view isn't necessarily the immediate subview     let pointForTargetView = self.spinnerTableView.convertPoint(point, fromView:self)       if (CGRectContainsPoint(self.spinnerTableView.bounds, pointForTargetView)) {         // The target view may have its view hierarchy,         // so call its hitTest method to return the right hit-test view         return self.spinnerTableView.hitTest(pointForTargetView, withEvent:event);     }     return super.hitTest(point, withEvent: event) } 

Edit:

I apologise for not having been able to look at the answers and check if they resolve the issue, due to some other tasks that require immediate attention. I shall check them and accept one that helps. Thanks for your patience.

5 Answers

Answers 1

As you stated:

However, if the control is in another view hierarchy, the UITableView is not receiving touch events.

Even if you made it working what if you have subviewed this control under another UIView??

This way we have a burden of converting points for the view hierarchy, my suggestion is that, as you can see in this control, it adds the tableview on the same hierarchy where the control itself is present. (e.g., it adds the table view on the controller where this control was added)

A part from the link:

-(void)textFieldDidBeginEditing:(UITextField *)textField {     [self setupSuggestionList];     [suggestionListView setHidden:NO];      // Add list to the super view.     if(self.dataSourceDelegate && [self.dataSourceDelegate isKindOfClass:UIViewController.class])     {         [((UIViewController *)self.dataSourceDelegate).view addSubview:suggestionListView];     }      // Setup list as per the given direction     [self adjustListFrameForDirection:dropDownDirection]; } 

Hope that helps!

Answers 2

I was thinking about the UIResponder , something like:

override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {         // Convert the point to the target view's coordinate system.         // The target view isn't necessarily the immediate subview          var responder: UIResponder = self         while responder.nextResponder() != nil {             responder = responder.nextResponder()!             if responder is UITableView {                 // Got UITableView                 break;             }         }         let pointForTargetView = responder.convertPoint(point, fromView:self)         if (CGRectContainsPoint(responder.bounds, pointForTargetView)) {             // The target view may have its view hierarchy,             // so call its hitTest method to return the right hit-test view             return self.responder.hitTest(pointForTargetView, withEvent:event);         }         return super.hitTest(point, withEvent: event) } 

If this method don't work, try to convertPoint with superview:

When you are sure that self.spinnerTableView is not nil and it is your table, do:

let pointForTargetView = self.spinnerTableView.superView.convertPoint(point, fromView:self)  

Answers 3

I think you should overridden pointInside implement:

class Control: UIButton {      var dropdown: Bool = false      override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {         if dropdown {             return CGRectContainsPoint(CGRect(x: 0, y:0, width: self.bounds.width, self.bounds.height + spinnerTableView.frame.height), point)         }         return super.pointInside(point, withEvent: event)     } } 

like this, superview call control's hittest when touch outside control bounds, it won't return nil.

But there are still a problem, if the control is in another view hierarchy, the UITableView may not receiving touch events.

I think this problem is normal,you can't decide other view's pointInside or not which under control, if the control superview hitTest return nil, the control hitTest method will not be called. Unless you overridden all view pointInside method which under the control, but it is unrealistic.

Answers 4

You need to subClass UIView,and use it as your UIViewController's root view.

class HitTestBottomView: UIView {    override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {      if  let hitTestView  =    self.getHitTestButtonFrom(self){         let pointForHitTestView = hitTestView.convertPoint(point, fromView: self)         let pointForHitTestTableView = hitTestView.spinnerTableView.convertPoint(point, fromView: self)          if CGRectContainsPoint(hitTestView.bounds, pointForHitTestView) ||  CGRectContainsPoint(hitTestView.spinnerTableView.bounds, pointForHitTestTableView){             return hitTestView.hitTest(pointForHitTestView, withEvent: event)         }     }      return super.hitTest(point, withEvent: event)   }    func getHitTestButtonFrom(view:UIView) ->HitTestButton?{     if let testView = view as? HitTestButton {         return testView     }      for  subView  in view.subviews {         if let testView = self.getHitTestButtonFrom(subView) {             return testView         }     }     return nil   } } 

Answers 5

You have to implement

func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool 

for your UIButton and check UITableView bounds. Because hitTest first checks if this tap point is within your view's bounds then calls hitTest for your view. so you have to implement pointInside and return true for your bounds.

WWDC for advanced scroll views and touch handling techniques wwdc

Read More

wallaby.js got error >> SyntaxError: Unexpected token u

Leave a Comment

i tried to set up wallaby.js on visual studio code.

my project use language: node.js (es6)

  1. test: mocha
  2. ide: visual studio code
  3. node version: v5.9.0

i always got this error when i run wallaby

SyntaxError: Unexpected token u 

====== my wallaby config file (wallaby.js) =======

module.exports = function (wallaby) {   return {     files: [       'server/**/*.js',       '!node_modules/**/*.js'     ],     tests: [       'test/**/*.js'     ],     compilers: {       '**/*.js': wallaby.compilers.babel()     },     env: {       type: 'node',       params: {         runner: '--harmony --harmony_arrow_functions'       }     },     testFramework: 'mocha'   }; }; 

====== error =======

​SyntaxError: Unexpected token u /PATH/config/index.js:3:0 

====== config.index.js ======

'use strict'  module.exports  = {   // do something } 

it looks like there is an error on line module.exports = { because of the es6 syntax.

but i used node 5.9 which support es6

how should i solved this issue?

2 Answers

Answers 1

i have tried to create a small project with simple test cases and wallaby.js work fine.

I am not sure what the cause is but it should be my big code not wallaby.js.

Answers 2

Seems like you need to add missing semicolon at the end of first config line:

'use strict';  module.exports  = {   // do something } 
Read More

Which kind of DBs calculate rate per minute statistics?

Leave a Comment

I have a use case requirement, where I want to design a hashtag ranking system. 10 most popular hashtag should be selected. My idea is something like this:

[hashtag, rateofhitsperminute, rateofhisper5minutes]

Then I will query, find out the 10 most popular #hashtags, whose rateofhits per minute are highest.

My question is what sort of databases, can I use, to provide me statistics like 'rateofhitsperminute' ?

What is a good way to calculate such a detail and store in it db ? Do some DBs offer these features?

4 Answers

Answers 1

No database has rate per minute statistics just built in, but any modern database could be used to create a database in which you could quite easily calculate rate per minute or any other calculated values you need.

Your question is like asking which kind of car can drive from New York to LA - well no car can drive itself or refuel itself along the way (I should be careful with this analogy because I guess cars are almost doing this now!), but you could drive any car you like from New York to LA, some will be more comfortable, some more fuel efficient and some faster than others, but you're going to have to do the driving and refueling.

Answers 2

First of all, "rate of hits per minute" is calculated:

[hits during period]/[length of period] 

So the rate will vary depending on how long the period is. (The last minute? The last 10 minutes? Since the hits started being recorded? Since the hashtag was first used?)

So what you really want to store is the count of hits, not the rate. It better to either:

  • Store the hashtags and their hit counts during a certain period (less memory/cpu required but less flexible)
  • OR the timestamp and hashtag of each hit (more memory/cpu required but more flexible)

Now it is a matter of selecting the time period of interest, and querying the database to find the top 10 hashtags with the most hits during that period.

If you need to display the rate, use the formula above, but notice it does not change the order of the top 10 hashtags because the period is the same for every hashtag.


You can apply the algorithm above to almost any DB. You can even do it without using a database (just use a programming language's builtin hashmap).

If performance is a concern and there will be many different hashtags, I suggest using an OLAP database. OLAP databases are specially designed for top-k queries (over a certain time period) like this.

Having said that, here is an example of how to accomplish your use case in Solr: Solr as an Analytics Platform. Solr is not an OLAP database, but this example uses Solr like an OLAP DB and seems to be the easiest to implement and adapt to your use case:

Your Solr schema would look like:

<fields>  <field name="hashtag"  type="string"/>  <field name="hit_date" type="date"/> </fields> 

An example document would be:

{  "hashtag": "java",  "hit_date": '2012-12-04T10:30:45Z' } 

A query you could use would be:

http://localhost:8983/solr/select?q=*:*&facet=true&facet.field=hashtag&facet.mincount=1&facet.limit=10&facet.range=hit_date&facet.range.end=2013-01-01T00:00:00Z&facet.range.start=2012-01-01T00:00:00 

Finally, here are some advanced resources related to this question:

Answers 3

You can use InfluxDB. It's well suited for your use case, since it was created to handle time series data (for example "hits per minute").

In your case, every time there is a hit, you could send a record containing the name of the hashtag and a timestamp.

The data is queryable, and there are already tools that can help you process or visualize it (like Grafana).

Answers 4

If you are happy with a large data set you could store and calculate this information yourself.

I believe Mongo is fairly fast when it comes to index based queries so you could structure something like this.

Every time a tag is "hit" or accessed you could store this information as a row

[Tag][Timestamp] 

Storing it in such a fashion allows you to first of all run simple Group, Count and Sort operations which will lead you to your first desired ability of calculating the 10 most popular tags.

With the information in this format you can then perform further queries based on tag and timestamp to Count the amount of hits for a specific tag between the times X and Y which would give you your hits Per period.

Benefits of doing it this way:

  • High information granularity depending on time frames supplied via query
  • These queries are rather fast in mongoDB or similar databases even on large data sets

Negatives of doing it this way:

  • You have to store many rows of data
  • You have to perform queries to retrieve the information you need rather than returning a single data row
Read More

Javascript Event Listener quits (?) from listening… Youtube API - No console error

Leave a Comment

I spent 6 hours on this already.
(plus 1 editing this question!)

I'm kind of debugging the last 4 lines of it.

Problem is that I get NO console error as a hint.



Concept:
I want to link numerous Youtube videos to text links.
The wanted effect for the user is to be able to click on a citation link while reading a text... In order to be able to confirm the citation.
The video has NOT to play entirely.

The video shall start at a specific timecode AND end at a specific timecode.
Bonus complexity: All this is wanted to be shown in a modal view style.

My code WORKED quite fast for ONE video. See here.

I based my code on this tutorial and succedded real fast.

Then, having this working...
I had the need to build arrays to handle multiple videos.
For links ids, players ids, timecodes for start/end... AND LISTENERS!
Fun begins!

Like said, I spent most of my day on this. I always encountered bugs WITH console errors as clear (LOLLL) guides.

I am satisfied of my work... This is going in the right direction I think.
This is almost working...


But this time, no errors! See here. (check the console!)

WHATT!!! NO ERROR?!?
My arms are hacked off now.
In fact, the 1st shows but video doesn't start... And the second looks to be completely lost in the haze.

In console log messages, I see the 1st occurance of the onStateChange listener, wich is -1 (Unstarted). But then ??? It dies!
Arrgg!

I have to overstep my pride... And bring it as a question on StackOveflow.
;)



My full code (for multiple links):
This is a page called via ajax... So all external ressources like jQuery are already loaded.

<style> .ytplayer{     position:fixed;     z-index:2;     width:60%;     height:40%;     top:30%;     left:20%;     display:none; } #ytplayerModal{     display:none;     background-color:#000;     opacity:0;     position:fixed;     z-index:1;     top:0;     left:0;     width:100%;     height:100%; } .ytTriggerPlay{     text-decoration:underline;     color:dodgerblue;     cursor:pointer; } </style>    <h1>Youtube modal trigger link test</h1> <br> <br> <div id="text">     Lorem ipsum dolor sit amet, consectetur <a id="0" class="ytTriggerPlay">adipiscing elit</a>. Quisque feugiat lectus ut est vestibulum ornare. Vivamus felis nulla, facilisis id cursus non, pharetra non diam. Sed pellentesque turpis vel sem tincidunt consectetur. Aenean ut lorem erat. Donec ut tellus sed leo ultrices cursus. <a id="1" class="ytTriggerPlay">Cras varius libero</a> ut purus suscipit ultrices. Vivamus eget efficitur turpis. Aenean suscipit, dui nec luctus fringilla, neque tellus fringilla risus, et porta enim justo et turpis. Sed risus orci, vehicula sed eleifend eget, tincidunt ut turpis. Vestibulum in sapien non lacus tristique mattis id eget tortor.<br>     <br>     Proin est purus, maximus id nunc vel, consectetur tristique urna. Mauris cursus ipsum a varius luctus. Nunc interdum condimentum massa vitae rutrum. Morbi volutpat nec lorem eleifend malesuada. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Duis fringilla metus vel nunc elementum efficitur. Duis sed dolor diam. In eu ultrices libero, eget lobortis mi. Sed pretium orci non augue vehicula, eget placerat leo lacinia. Sed sed gravida dui. Lorem ipsum dolor sit amet, consectetur adipiscing elit. In bibendum, erat eget venenatis elementum, nulla enim posuere lacus, quis efficitur dolor ex quis ipsum. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Phasellus volutpat finibus odio id venenatis. Fusce at leo libero. Cras eget velit sed justo egestas vehicula efficitur sit amet ex.<br> </div>  <!--iframe id="ytplayer" type="text/html" width="720" height="405" src="https://www.youtube.com/embed/5V_wKuw2mvI?end=60&start=20" frameborder="0" allowfullscreen-->  <div id="ytplayerModal"></div> <div id="player1" class="ytplayer"></div> <div id="player2" class="ytplayer"></div>  <script> // https://developers.google.com/youtube/iframe_api_reference // https://css-tricks.com/play-button-youtube-and-vimeo-api/  // Global variable for the player var player = []; var statePlaying=false;  playerArr = [{             linkID:"0",             divID:"player1",             ytID:"5V_wKuw2mvI", // Heavy metal playlist             start:20,             end:40,             },             {             linkID:"1",             divID:"player2",             ytID:"39b5v3-d6ZA", // Maiden             start:30,             end:60,             }];  // This function gets called when API is ready to use  function onYouTubePlayerAPIReady() {     for(i=0;i<playerArr.length;i++){         // Create the global player from the specific iframe (#video)         thisPlayer = new YT.Player(playerArr[i].divID, {             height: '352',             width: '640',             videoId: '5V_wKuw2mvI',             startSeconds:20,             endSeconds:40,             events: {                 // Call this function when player is ready to use                 // 'onReady': onPlayerReady         // Commented out willingly.             }         });         player[i] = thisPlayer;      }     onPlayerReady(); }  function onPlayerReady(event) {      // Binding events loop     console.log("playerArr.length: "+playerArr.length);     for(i=0;i<playerArr.length;i++){         console.log("");         console.log("onPlayerReady for loop ->i: "+i);          var playButton = document.getElementById(playerArr[i].linkID);         console.log("playButton.id: "+playButton.id);          var thisArr = playerArr[i];         console.log("playerArr[i] object (below): ");         console.log(thisArr);          var thissPlayer = player[i];          playButton.addEventListener("click", function() {             thisLinkID = parseInt($(this).attr("id"));             console.log("thisLinkID: "+thisLinkID);              var ytID = playerArr[thisLinkID].ytID;             var start = playerArr[thisLinkID].start;             var end = playerArr[thisLinkID].end;              console.log("ytID: "+ytID);             console.log("start: "+start);             console.log("end: "+end);             console.log("thissPlayer object (below): ");             console.log(thissPlayer);              $("#ytplayerModal").css({"display":"block"});             $("#ytplayerModal").animate({"opacity":"0.7"},1000,function(thissPlayer,ytID,start,end){                 $(".ytplayer").show();                  player[thisLinkID].loadVideoById({videoId:ytID, startSeconds:start, endSeconds:end});                 setTimeout(function(){                     player[thisLinkID].playVideo();                 },500);             });         });            thissPlayer.addEventListener("onStateChange", function(stateObj){             console.log("Player State: "+stateObj.data);             console.log("Again, thissPlayer object in the onStateChange listener (below).");             console.log(thissPlayer);             // State sequence : -1, 3, 1, 2, 0, which is: Unstarted, Buffering, Playing, Paused, Ended.              if(stateObj.data==1){                 statePlaying=true;             }             console.log("Player State bolean memory: "+statePlaying);              // Closes the modal             if((statePlaying) && (stateObj.data==0)){                 setTimeout(function(){                     console.log("Closing Modal");                     $(".ytplayer").css({"display":"none"});                     $("#ytplayerModal").animate({"opacity":"0"},1000,function(){                         $("#ytplayerModal").css({"display":"none"});                     });                     statePlaying=false;                 },500);             }         });     } }  // Inject YouTube API script var tag = document.createElement('script'); tag.src = "//www.youtube.com/player_api"; var firstScriptTag = document.getElementsByTagName('script')[0]; firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); </script> 





EDIT (Work in progress)

Based on the answer below, I modified my code.
It give some new results... But I'm still in the woods.

Here is my «work in progress» live link.

I now get player states like this:
State 5 (video cued) for 1 second (100 x 10 millisec).
State undefined 1 time.
State 3 (buffering) for 120 millisec.
State -1 (unstarted) endlessly...

Here is the new code, placed in the click listener:
The onStateChange listener is commented out.

// Bugfix - Set Interval instead of listener var IntervalCounter=0; listenerInterval = setInterval( function() {      var state = player[thisLinkID].getPlayerState();     var stateMsg;      switch (state){         case -1: stateMsg="unstarted"; break;         case  0: stateMsg="ended"; break;         case  1: stateMsg="playing"; break;         case  2: stateMsg="paused"; break;         case  3: stateMsg="buffering"; break;         case  5: stateMsg="video cued"; break;         default: stateMsg="Undefined player state...";     }     console.log(state+" : "+stateMsg);      if(state==1){         statePlaying=true;     }      // Closes the modal     if((statePlaying) && (state==0)){     //if((statePlaying) && (stateObj.data==0)){         setTimeout(function(){             console.log("Closing Modal");             $(".ytplayer").css({"display":"none"});             $("#ytplayerModal").animate({"opacity":"0"},1000,function(){                 $("#ytplayerModal").css({"display":"none"});             });             statePlaying=false;         },500);     }      // Stop the interval at 1000... Endless instead!     IntervalCounter++;     if(IntervalCounter>999){         clearInterval(listenerInterval);         console.log("Interval loop volontarely stopped. Endless otherwise.")     } }, 10); 

Here is a snapshot of my console:
enter image description here

1 Answers

Answers 1

There was a temporary issue with the iFrame Player API that you can read about here: https://code.google.com/p/gdata-issues/issues/detail?id=4706

As a temporary fix, you just need to add the event listener within the onReady event:

function onReady() { player.addEventListener('onStateChange', function(e) { console.log('State is:', e.data); }); } 

Also, as someone mentioned on the Google Code Issue Thread, you set an interval and poll the player for its current state instead of listening for the onStateChange event. Here is an example code snippet for doing that:

setInterval( function() { var state = player.getPlayerState(); if ( playerState !== state ) { onPlayerStateChange( { data: state }); } }, 10); 
Read More