cURL: follow locations with safe_mode enabled or open_basedir set

cURL is a tool to connect to a remote server and load data from it while schemes like HTTP, HTTPS, FTP, gopher, telnet, DICT, FILE, LDAP and more are supported for the request URI.

PHP has built-in support by providing its users a layer upon the underlying libcurl library. Here is an example how cURL is used in PHP:

$ch = curl_init("http://example.com");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = curl_exec($ch);
curl_close($ch);

The option CURLOPT_RETURNTRANSFER advices PHP to return the result after executing curl_exec() on success and FALSE else. If this option is ommitted it would return TRUE instead of the result.

At some point you need to follow a location. This is the case if a server you are connecting to is replying with a location redirect. In a HTTP response the server would reply with a 301 or 302 status code and the HTTP header Location pointing to the new URI. In the code the option CURLOPT_FOLLOWLOCATION needs to be set to allow libcurl to follow the redirect.

$ch = curl_init("http://example.com");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$data = curl_exec($ch);
curl_close($ch);

However if your web server has safe_mode activated or open_basedir set then CURLOPT_FOLLOWLOCATION won’t have any effect. The below warning will appear and libcurl won’t follow the new location.

Warning: curl_setopt() [function.curl-setopt]: CURLOPT_FOLLOWLOCATION
cannot be activated when in safe_mode or an open_basedir is set in ...

This blog post shows you a workaround by changing the server configuration and putting the loader script to a directory defined in open_basedir. Unfortunately many websites are hosted on a shared host. Hence most people can’t just alter something in a configuration file but rather need a user-space solution.

One solution is to follow redirects manually by examining the server response and send the request to the new location again. The next sample code does exactly this. The function curl_exec_follow is passed two arguments, one is the cURL handler and the second the maximum amount of allowed redirects. If a server response contains a redirect location the script also checks if it’s a URL or a relative path to the resource.

function curl_exec_follow($ch, &$maxredirect = null) {

  $mr = $maxredirect === null ? 5 : intval($maxredirect);

  if (ini_get('open_basedir') == '' && ini_get('safe_mode' == 'Off')) {

    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, $mr > 0);
    curl_setopt($ch, CURLOPT_MAXREDIRS, $mr);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

  } else {

    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);

    if ($mr > 0)
    {
      $original_url = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
      $newurl = $original_url;

      $rch = curl_copy_handle($ch);

      curl_setopt($rch, CURLOPT_HEADER, true);
      curl_setopt($rch, CURLOPT_NOBODY, true);
      curl_setopt($rch, CURLOPT_FORBID_REUSE, false);
      do
      {
        curl_setopt($rch, CURLOPT_URL, $newurl);
        $header = curl_exec($rch);
        if (curl_errno($rch)) {
          $code = 0;
        } else {
          $code = curl_getinfo($rch, CURLINFO_HTTP_CODE);
          if ($code == 301 || $code == 302) {
            preg_match('/Location:(.*?)\n/', $header, $matches);
            $newurl = trim(array_pop($matches));

            // if no scheme is present then the new url is a
            // relative path and thus needs some extra care
            if(!preg_match("/^https?:/i", $newurl)){
              $newurl = $original_url . $newurl;
            }
          } else {
            $code = 0;
          }
        }
      } while ($code && --$mr);

      curl_close($rch);

      if (!$mr)
      {
        if ($maxredirect === null)
        trigger_error('Too many redirects.', E_USER_WARNING);
        else
        $maxredirect = 0;

        return false;
      }
      curl_setopt($ch, CURLOPT_URL, $newurl);
    }
  }
  return curl_exec($ch);
}

This function is used in place of curl_exec() and doesn’t need extra user privileges as you would need to change the server configuration.

$ch = curl_init("http://example.com");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = curl_exec_follow($ch);
curl_close($ch);

Hopefully this helped you.

DeliciousDiggTechnorati FavoritesRedditLinkedInFacebookSpurlTwitterWebnewsYiGGMySpaceYahoo BookmarksFriendFeedGoogle BookmarksLiveJournalShare

Qt: Q_OBJECT macro

I always thought that every class subclassing QObject must contain this macro but this is not completely right. More precisely it is only required if meta-object code has to be produced by the moc tool in order to use the signals and slots mechanism, the run-time type information, the dynamic property system and translating features for internationalization.

Beside that the methods metaObject() and inherits() from QObject as well as className() and newInstance() from QMetaObject also require it.

However the Qt developers strongly recommend that Q_Object is used by every subclass of QObject no matter what of the above features they actually use, also if none is used.

DeliciousDiggTechnorati FavoritesRedditLinkedInFacebookSpurlTwitterWebnewsYiGGMySpaceYahoo BookmarksFriendFeedGoogle BookmarksLiveJournalShare

Qt: set the main window title from everywhere

In Qt the title of the main window can be set from everywhere and thankfully to the QApplication class we gain access to all created widgets by using the method findChildren() or topLevelWidgets(). The difference between both is that findChildren() returns a list only with widgets which reside inside another widget and in contrast topLevelWidgets() returns a list with parentless widgets which are always independent windows or dialogs.

With this background knowledge topLevelWidgets() is the way to go because findChildren only finds… children.

As a showing example here is a code snippet:

foreach(QWidget *widget, QApplication::topLevelWidgets()) {
  if(widget->objectName() == "MainWindow")
    qobject_cast<QMainWindow*>(widget)->setWindowTitle("-_-");
}

In the foreach loop we walk through the whole list of top-level widgets and because we want to change the title of the main window, we check the widget’s object name. In this example the main window’s object name is ‘MainWindow’ which is the default in Qt Designer.

Object names are not necessarily unique, multiple objects can have the same object name and thus the wrong widget could be chosen. MainWindow kind of implies there should only be one, so this simple check should be fine in most cases.

An alternative to the class QApplication is the macro qApp which is an instance of that class.

#define qApp (static_cast<QApplication *>(QCoreApplication::instance()))

Because QApplication implements the singleton design pattern only one instance can exist at most. If we are sure that there are no other objects of the type QMainWindow in the top-level widget list we could also check if it inherits from that class.

In place of the code above this would be fine then as well:

foreach(QWidget *widget, qApp->topLevelWidgets()) {
  if(widget->inherits("QMainWindow"))
    qobject_cast<QMainWindow*>(widget)->setWindowTitle("-_-");
}
DeliciousDiggTechnorati FavoritesRedditLinkedInFacebookSpurlTwitterWebnewsYiGGMySpaceYahoo BookmarksFriendFeedGoogle BookmarksLiveJournalShare

Qt: error message telling the copy constructor is private

In the following code sample a singleton is implemented with a static instance getter which can be called in any other class.

class MyClass{

public:

    static MyClass *instance(){
        if(!m_instance)
            m_instance = new MyClass;
        return m_instance;
    }

private:

    MyClass(){}
    ~MyClass(){}

    static MyClass *m_instance;
};

MyClass *MyClass::m_instance = NULL;

class SomeOtherClass{
    void doSomething(){
        MyClass *c = MyClass::instance();
    }
};

In SomeOtherClass the method doSomething() grabs the instance of MyClass and keeps it in a local pointer variable. Now if the asterisk * is forgotten, the variable c no longer defines a pointer and in that case ‘=’ is no assignment but the copy constructor used to initialize the local variable declaration while the compiler complains this with a error message telling you that the copy constructor is private.

If in your Qt application the compiler outputs similar messages as follows, check if you’ve forgotten the asterisk.

/usr/include/qt4/QtCore/qobject.h: In copy constructor 'MyClass::MyClass(const MyClass&)':
/usr/include/qt4/QtCore/qobject.h:309: error: 'QObject::QObject(const QObject&)' is private
src/MyClass.h:17: error: within this context
/usr/include/qt4/QtGui/qstandarditemmodel.h:424: error: 'QStandardItemModel::QStandardItemModel(const QStandardItemModel&)' is private
src/MyClass.h:17: error: within this context
/usr/include/qt4/QtGui/qstandarditemmodel.h:424: error: 'QStandardItemModel::QStandardItemModel(const QStandardItemModel&)' is private
src/MyClass.h:17: error: within this context
/usr/include/qt4/QtGui/qstandarditemmodel.h:424: error: 'QStandardItemModel::QStandardItemModel(const QStandardItemModel&)' is private
src/MyClass.h:17: error: within this context

Note: the singleton implementation above has some drawbacks like not being thread-safe. Here it’s only used as a showing example.

DeliciousDiggTechnorati FavoritesRedditLinkedInFacebookSpurlTwitterWebnewsYiGGMySpaceYahoo BookmarksFriendFeedGoogle BookmarksLiveJournalShare

Qt: QString constant in a class

A constant QString can be achieved by defining the macro

#CONSTSTRING "-_-"

and by creating a temporary QString instance in each place the constant is needed e.g. for a window title.

...
window.setWindowTitle(QString(CONSTSTRING));
...

A lot of the Qt goodness is due to macros but most of them are defined as empty for good reason. Macros are processed by a preprocessor which replaces the macro by the given text in the source file before the compiler knows what happens. Amongst others they can produce unplanned side-effects due to the missing data type and thus in Qt they are mainly used as markers for the Meta-Object-Compiler.

Another drawback is that if the constant is used in numerous places, numerous of anonymous, unnamed variables are created which reduces the efficiency.

All these drawbacks can be avoided by simply defining a static constant as shown in the following example. In myclass.h the constant is defined …

class MyClass
{
private:
  static const QString constString;
}

… and initialized in myclass.cpp

#include "MyClass.h"

const QString MyClass::constString = QString("-_-");

The assignment of const QStrings are also faster thanks to implicit sharing of QString because the first example doesn’t use implicit shared objects and thus they can’t be shallow copied.

If this global constant QString is used in other modules too then it can happen that your program crashes because of the static initialization order fiasco which should always be avoided because such errors are hard to find.

To not run into any trouble in that case use the construct on first use idiom [1, 2], where you simply wrap your static object inside a function.

const QString & constantQString()
{
  static const QString constant("-_-");
  return constant;
}
DeliciousDiggTechnorati FavoritesRedditLinkedInFacebookSpurlTwitterWebnewsYiGGMySpaceYahoo BookmarksFriendFeedGoogle BookmarksLiveJournalShare