Thursday, February 1, 2018

Force Heroku PHP app to use https for both www and non-www versions

Leave a Comment

I have a PHP app on Heroku with an SSL certificate for the www version of the domain name. I need all requests (to both www and non-www) to go to via https, and I have added .htaccess to that affect. However, there are still circumstances where it's possible for a user to access the http version and I don't understand why.

Here is my .htaccess:

RewriteEngine on  RewriteCond %{HTTPS}::%{HTTP_HOST} ^off::(?:www\.)?(.+)$ RewriteRule ^ https://www.%1%{REQUEST_URI} [NE,L,R] 

My understanding is that this should force all users to access via https://www, but that doesn't always happen. For example, Google sometimes provides search results without the https and the links open insecure http instead.

Any ideas about what I'm doing wrong?

2 Answers

Answers 1

first redirect to the same host-name on :443, then redirect to www.. ordinary www. is just an alias in DNS, while most use the shorter non-www hostname for websites. you might have to extend the certificate, because it requires both host-names explicitly added, unless it's wild-carded.

one does not have to filter for the host-name:

RewriteEngine On RewriteCond %{HTTPS} !=on RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] 

also see this answer here, concerning robots.txt with enforced SSL.

Answers 2

Try the following rules and let me know if it works or not these rule will use https request instead of http or www and non-www version. The following rule will now redirect the user to the something like this.

https://www.example.com/

RewriteEngine On  RewriteCond %{HTTP_HOST} !^www\. [NC,OR] RewriteCond %{HTTPS} !on RewriteCond %{HTTP_HOST} ^(?:www\.)?(.+)$ [NC] RewriteRule ^ https://www.%1%{REQUEST_URI} [R=301,L,NE] 

Hope this will help to achieve what you wanted

Read More

Node attribute value replace program getting exception?

Leave a Comment

I'm trying to create a program which will search the xml files for nodes in the form <disp-formula id="deqnX-Y">, create a dictionary where keys are like rid="deqnX" ... rid="deqnY", (where X is incremented by +1 till it reaches Y) and their respective value counterparts are like rid="deqnX-Y" each, Then I can simply do a search and replace using the dictionary to change the link nodes. i.e. if the file has nodes like <disp-formula id="deqn5-7">, <disp-formula id="deqn9-11">, <disp-formula id="deqn3a-3c">, <disp-formula id="deqn4p-5b"> and there are link nodes in the form

<xref ref-type="disp-formula" rid="deqn5"> <xref ref-type="disp-formula" rid="deqn6"> <xref ref-type="disp-formula" rid="deqn10"> <xref ref-type="disp-formula" rid="deqn5c"> 

which should be changed to

<xref ref-type="disp-formula" rid="deqn5-7"> <xref ref-type="disp-formula" rid="deqn5-7"> <xref ref-type="disp-formula" rid="deqn9-11"> <xref ref-type="disp-formula" rid="deqn4p-5b"> 

I'm using the below code for now

void Button1Click(object sender, EventArgs e)         {             string active_filename = "";             string DirectoriesName = textBox1.Text;             string[] path = Directory.GetDirectories(DirectoriesName, "xml", SearchOption.AllDirectories)                 .SelectMany(x => Directory.GetFiles(x, "*.xml", SearchOption.AllDirectories)).ToArray();             Dictionary<string, string> dict = new Dictionary<string, string> ();             var re = new Regex(@"deqn(\w+)-(\w+)");             foreach (var file in path)             {                 dict.Clear();                 active_filename = file;                 XDocument doc = XDocument.Load(file, LoadOptions.PreserveWhitespace);                 IEnumerable<XAttribute> list_of_elements = doc.Descendants("disp-formula").Where(z => (z.Attribute("id") != null) && re.IsMatch(z.Attribute("id").Value)).Attributes("id");                  foreach (XAttribute ele in list_of_elements)                 {                     int from = 0, to = 0;                      string strform = re.Match(ele.Value).Groups[1].Value;                      string strTo = re.Match(ele.Value).Groups[2].Value;                      Boolean bfrom = int.TryParse(strform,out from);                     Boolean bto  = int.TryParse(strTo,out to);                     if (bfrom && bto)                     {                         for (int i = from; i <= to; i++)                             dict.Add("rid=\"deqn" + i + "\"", "rid=\"" + ele.Value + "\"");                     }                     else {                         for (int i = base36toInt(strform); i <= base36toInt(strTo); i++)                         {                             int temp = 0;                             if (!int.TryParse(IntTo36Base(i), out temp))                             {                                 dict.Add("rid=\"deqn" + IntTo36Base(i) + "\"", "rid=\"" + ele.Value + "\"");                             }                         }                     }                     foreach (KeyValuePair<string, string> element in dict)                     {                         //do a search all replace all (search Key and replace by Value                         string text = File.ReadAllText(file);                         text = text.Replace(element.Key, element.Value);                         File.WriteAllText(file, text);                     }                 }             }             MessageBox.Show("Done");          }         public static int base36toInt(string s)         {             char[] baseChars = "0123456789abcdefghijklmnopqrstuvwxyz".ToCharArray();             char[] target = s.ToCharArray();             double result = 0;             for (int i = 0; i < target.Length; i++)             {                 result += Array.IndexOf(baseChars, target[i]) * Math.Pow(baseChars.Length, target.Length - i - 1);             }             return Convert.ToInt32(result);         }         public static string IntTo36Base(int value)         {             char[] baseChars = "0123456789abcdefghijklmnopqrstuvwxyz".ToCharArray();             string result = string.Empty;             int targetBase = baseChars.Length;             do             {                 result = baseChars[value % targetBase] + result;                 value = value / targetBase;             }             while (value > 0);              return result;         } 

But the problem occurs when there are nodes like <disp-formula id="deqn5-7c"> or <disp-formula id="deqn2a-4"> in the file. The error I get is System.IO.IOException: The requested operation cannot be performed on a file with a user-mapped section open. How do I get rid of this error.

Furthermore, I want the program to ignore nodes like <disp-formula id="deqn5-7c"> and/or <disp-formula id="deqn2a-4">, what is the most efficient way of doing this?

2 Answers

Answers 1

Okay, this might be a stupid answer, but... have you thought about changing your regex? I mean, right now, it's going to match "deqn", followed by any stream of alphanumeric chars, followed by "-", followed by another stream of alphanumerics. So even stuff like "deqnasdf-zxcv" is going to fit.

I'd suggest changing it to: "deqn(\d+)-(\d+)" - aka, change the "any alphanumeric" to "any digit". I mean, if you're wanting to skip the stuff like deqn1-2c anyways, this will prevent them from even showing up in the matches. Plus, the more you narrow down your regex, the more potential bugs you stop in the future for matches you didn't plan for.

Answers 2

I get is System.IO.IOException: The requested operation cannot be performed on a file with a user-mapped section open.

It seems the file that you want change it is using, so you can not change it. Because you say sometimes it happen then I guess your loop is raising the error. It open and close a file fast while you can open the file out of the loop and write to it after the loop. Anyway you can find the app that is using the file when you get the above error by a program such as Process Explorer.

Test it:

Instead of using this code:

foreach (KeyValuePair<string, string> element in dict) {   //do a search all replace all (search Key and replace by Value   string text = File.ReadAllText(file);   text = text.Replace(element.Key, element.Value);   File.WriteAllText(file, text); } 

Use this one:

string text = File.ReadAllText(file); foreach (KeyValuePair<string, string> element in dict) {   //do a search all replace all (search Key and replace by Value   text = text.Replace(element.Key, element.Value); } File.WriteAllText(file, text); 
Read More

Severe performance drop with MongoDB Change Streams

Leave a Comment

I want to get real-time updates about MongoDB database changes in Node.js.

A single MongoDB change stream sends update notifications almost instantly. But when I open multiple (10+) streams, there are massive delays (up to several minutes) between database writes and notification arrival.

That's how I set up a change stream:

let cursor = collection.watch([   {$match: {"fullDocument.room": roomId}}, ]); cursor.stream().on("data", doc => {...}); 

I tried an alternative way to set up a stream, but it's just as slow:

let cursor = collection.aggregate([   {$changeStream: {}},   {$match: {"fullDocument.room": roomId}}, ]); cursor.forEach(doc => {...}); 

An automated process inserts tiny documents into the collection while collecting performance data.

Some additional details:

  • Open stream cursors count: 50
  • Write speed: 100 docs/second (batches of 10 using insertMany)
  • Runtime: 100 seconds
  • Average delay: 7.1 seconds
  • Largest delay: 205 seconds (not a typo, over three minutes)
  • MongoDB version: 3.6.2
  • Cluster setup #1: MongoDB Atlas M10 (3 replica set)
  • Cluster setup #2: DigitalOcean Ubuntu box + single instance mongo cluster in Docker
  • Node.js CPU usage: <1%

Both setups produce the same issue. What could be going on here?

1 Answers

Answers 1

The default connection pool size in the Node.js client for MongoDB is 5. Since each change stream cursor opens a new connection, the connection pool needs to be at least as large as the number of cursors.

const mongoConnection = await MongoClient.connect(URL, {poolSize: 100}); 

(Thanks to MongoDB Inc. for investigating this issue.)

Read More

How to get the LDAP OU of the user using node / passport?

Leave a Comment

I'm working on LDAP authentication / authorization flow in my Node.js app, and need to retrieve the OU to which a given user belongs.

The following code get me the user, but when I inspect it, I do not see the OU:

var express = require('express'),     passport = require('passport'),     bodyParser = require('body-parser'),     LdapStrategy = require('passport-ldapauth');  var opts = {     server: {         url: 'ldap://ldap.forumsys.com:389',             // Host + port         bindDn: 'cn=read-only-admin,dc=example,dc=com',  // user DN         bindCredentials: 'password',                     // Password         searchBase: 'dc=example,dc=com',                 // Base DN         searchFilter: '(uid={{username}})'     } };  var app = express();  passport.use(new LdapStrategy(opts, function(user, done){     done(null, user); }));  app.use(bodyParser.json()); app.use(bodyParser.urlencoded({extended: false})); app.use(passport.initialize());  app.post('/login', passport.authenticate('ldapauth', {session: false}), function(req, res) {     var ou = req.user.distinguishedName;     res.send({status: 'Hello ' + req.user.uid}); });  app.listen(8998); 

Given this code, what is the proper way to retrieve the OU?

2 Answers

Answers 1

The issue is the LDAP server, not your code. If run against an Active Directory server, your code will return the full path to the object.

I tested both against your online test server, and an AD server.

From the comments on the forumsys site, it seems that to get the OU you would need to query the OU objects themselves for members. I don't think this is standard in most LDAP setups.

In this particular LDAP setup, the OUs are of type groupOfUniqueNames. Because of this, membership in the group is determined by the uniqueMember attributes that are present with each OU. To determine a user’s OU membership, you would have to scan each of the OUs and find a uniqueMember attribute containing the DN of the user you are looking for.

If you wish to look at this for yourself, please use Apache Directory Studio and the information provided above to review the setup.

Answers 2

You can retrieve OU using member, memberof or distinguishedName search criteria supplying a specific user's DN in the query which should resolve this.

From your code:

User's DN is:

cn=read-only-admin,dc=example,dc=com 

So, your search filter can be, memeber=user's DN or distinguishedName=user's DN:

searchFilter: '(member = {{cn=read-only-admin,dc=example,dc=com}})'  searchFilter: '(distingushedName = {{cn=read-only-admin,dc=example,dc=com}})' 

Don't have an LDAP AD to test the code but this should work.

Read More

iOS - ScopeBar overlaps SearchBar in UISearchController in TabBarController

Leave a Comment

I am running into a peculiar issue regarding a scope bar shown under my UISearchBar. Basically, the issue I previously had was that whenever my UISearchController was active and the user switched tabs, if he came back to the UIViewController containing the UISearchController, the background would turn back. This issue was solved by embedding the UIViewController into a UINavigationController.

Now, a new issue has appeared. When I switch tabs with the UISearchController already active, when I switch back, the UIScopeBar is displayed on top of the UISearchBar. This can only be fixed by Canceling the search, and starting over.

Illustration: enter image description here

I have tried hiding the following code:

-(void)viewWillAppear:(BOOL)animated{ if(self.searchController.isActive){     [self.searchController.searchBar setShowsScopeBar:TRUE]; } }  -(void)viewDidDisappear:(BOOL)animated{     if(self.searchController.isActive){         [self.searchController.searchBar setShowsScopeBar:FALSE];     } } 

To no avail. If anybody has a trick for this one, I'd be glad to try it out.

1 Answers

Answers 1

Setting a constraint programatically each time you generate the view and come back to that tab might do the trick by keeping the UIScopeBar at a fixed distance from the top. You can also try setting the contraint between UIScopeBar and UISearchBar.

NSLayoutConstraint *topSpaceConstraint = [NSLayoutConstraint constraintWithItem:self.view                                                                              attribute:NSLayoutAttributeTop                                                                              relatedBy:NSLayoutRelationEqual                                                                                 toItem:UIScopeBar                                                                               attribute:NSLayoutAttributeTop                                                                             multiplier:1.0                                                                               constant:5.0]; [self.view addConstraint:topSpaceConstraint]; 

If this does not do the trick, you'll need to provide more code for me/people here to replicate the bug you're having.

Read More

ld: framework not found MCCMerchant_sandbox

Leave a Comment

I am trying to integrate Master card merchant SDK. I am following all steps as described but always fails with error framework not found.

https://developer.mastercard.com/page/masterpass-merchant-sdk-for-ios#

enter image description here

Below is the screen shot of my framework search path

enter image description here

Below is the error which I am getting when trying to add framework in Xcode project

enter image description here

1 Answers

Answers 1

First of all You need to be sure that framework included in linked libraries. Go to project settings and check it is listed in Link binary With Libraries section. enter image description here

Read More

Mysql lock timeout when inserting concurrently

Leave a Comment

I am trying to insert concurrently (heavy inserts by 8 threads) into sql throught hibernate. My pojo consists of two tables, one table references the other through foreign key constraint. I am trying to save a lot of instances of my pojo to the db concurrently. Sometimes the insert is failing and rolling back because of lock wait timeout.

Caused by: java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction.

Suppose there are table A(table edges in the screenshot) and table B. Table B has a foreign key constraint which references it's id to primary key of table A. What I could infer from the locks table is an S lock is being held on table A's record by trx 114888 while try to insert in table B(id corresponding to table B) and 11493 is waiting to acquire X lock to insert new record in table A. Table A has index on some of its columns.

What is meant by supremum pseudo-record here? Is it a gap lock? If so then why is the record type as 'RECORD'? Is there a way around this so as to avoid this gap lock or whatever lock it is?

These are the screenshots of the lock tables. INNODB_LOCKS table screnshot

Some innodb status logs

---TRANSACTION 114893, ACTIVE 2611 sec inserting mysql tables in use 1, locked 1 LOCK WAIT 48609 lock struct(s), heap size 4726992, 585460 row lock(s), undo log entries 1132742 MySQL thread id 12620, OS thread handle 123145553027072, query id 38123782 localhost 127.0.0.1 root update insert into edges (---some values--) Trx read view will not see trx with id >= 114862, sees < 114817 ------- TRX HAS BEEN WAITING 22 SEC FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 408 page no 135298 n bits 240 index PRIMARY of table `**database**.edges` trx id 114893 lock_mode X insert intention waiting Record lock, heap no 1 

1 Answers

Answers 1

You are using the repeatable read isolation level. In the repeatable read isolation level so called gap locks are used and are held for the duration of the transaction (you can read more about gap locks in the documentation). If you switch the isolation level from repeatable read to read committed, the problem will go away. You can set the isolation level with

set transaction isolation level read committed 

You should check the documentation of the command. The isolation level can be set at a session level or global level.

Read More