tag:blogger.com,1999:blog-17503962919951719192024-03-09T03:06:24.705+02:00Xizhi's BlogKeep logging what I am interested inXizhi Zhuhttp://www.blogger.com/profile/11132645470363367082noreply@blogger.comBlogger20125tag:blogger.com,1999:blog-1750396291995171919.post-42902466703712600762011-04-28T20:44:00.000+03:002011-04-28T20:44:41.154+03:00Create Debian and RPM packages using OBSHave you ever tried to create both Debian and RPM packages using <a href="https://build.opensuse.org/">OBS</a>? Well, a little bit different from the package generation locally, but not that much ;)<br />
<br />
Before continuing, you should prepare yourself with basic <a href="http://www.debian.org/doc/maint-guide/index.en.html">Debian</a> and <a href="http://en.opensuse.org/openSUSE:Packaging_guidelines">RPM</a> packaging knowledge.<br />
<br />
First, make a tar-ball for your source code, without any packaging information inside. Name it <i>obs-sample.tar.gz</i>.<br />
<br />
Then for <b>Debian packaging</b>, you need the following files.<br />
obs-sample_1.0.dsc: indicating you want to create a Debian package; the <i>Files</i> section is not needed, but the <i>Build-Depends</i> section is necessary.<br />
debian.rules: the <i>rules</i> file for Debianization.<br />
debian.control: the <i>control</i> file for Debianization.<br />
debian.tar.gz: all the other files inside the <i>debian</i> folder.<br />
<br />
For <b>RPM packaging</b>, you only need the .spec file as expected.<br />
<br />
Finally, here goes <a href="https://build.opensuse.org/package/show?package=sample&project=home%3Axizzhu">the simple sample</a> I created. Happy hacking!Xizhi Zhuhttp://www.blogger.com/profile/11132645470363367082noreply@blogger.com0tag:blogger.com,1999:blog-1750396291995171919.post-17368263481281040372010-12-07T11:25:00.000+02:002010-12-07T11:25:49.834+02:00The Beauty of Qt 3: Implicit SharingTo maximize resource usage and minimize copying, Qt uses <a href="http://doc.qt.nokia.com/implicit-sharing.html"><b><span class="Apple-style-span" style="color: blue;"><span class="Apple-style-span" style="font-size: large;">implicit data sharing</span></span></b></a> in many classes, so that the data is copied <b>only when</b> a function writes to it. This trick is also referred to as <a href="http://en.wikipedia.org/wiki/Flyweight_pattern">flyweight pattern</a> sometimes.<br />
<br />
Now let's take <i>QByteArray</i> as an example to see <span class="Apple-style-span" style="color: #38761d;"><b>how it's implemented</b></span>. It uses a private struct of <i>Data</i> to track the shared data:<br />
<code class="prettyprint lang-cpp">struct Data {<br />
QBasicAtomicInt ref; // reference count, the operation on it is atomic<br />
int alloc; // allocated space for the data<br />
int size; // actual size of the data, not counting the ending '\0' added by QByteArray<br />
char *data; // point to the data<br />
char array[1]; // where the data is stored, and the data always end with '\0'<br />
};</code><br />
<br />
Here, we use both the pointer of <i>data</i> and <i>array</i> just because the data might actually be stored in another object. When an object is copied, e.g. through the assignment operator, it only copies the pointer to the shared data:<br />
<code class="prettyprint lang-cpp">QByteArray &QByteArray::operator=(const QByteArray & other)<br />
{<br />
// increase the reference count of the shared data it's supposed to be used<br />
other.d->ref.ref();<br />
<br />
// decrease the reference count of the share data currently used, and free it if no one else is using<br />
if (!d->ref.deref())<br />
qFree(d);<br />
<br />
// point to the shared data<br />
d = other.d;<br />
<br />
return *this;<br />
}</code><br />
<br />
On the other hand, if it's to be changed by e.g. the <i>resize()</i> function, it copies the data if any other object also shares it:<br />
<code class="prettyprint lang-cpp">void QByteArray::resize(int size)<br />
{<br />
if (size <= 0) {<br />
// if the target is no bigger than 0, points to an empty data block<br />
Data *x = &shared_empty;<br />
x->ref.ref();<br />
if (!d->ref.deref())<br />
qFree(d);<br />
d = x;<br />
} else if (d == &shared_null) {<br />
// if currently a null array, just create a new data block<br />
Data *x = static_cast<data *>(qMalloc(sizeof(Data)+size));<br />
Q_CHECK_PTR(x);<br />
x->ref = 1;<br />
x->alloc = x->size = size;<br />
x->data = x->array;<br />
x->array[size] = '\0';<br />
(void) d->ref.deref();<br />
d = x;<br />
} else {<br />
// if any other object uses this data block, or the current memory is too small or too big<br />
// reallocate space, and copy the data for it<br />
// note that this operation might consume some time if the data is huge<br />
if (d->ref != 1 || size > d->alloc || (size < d->size && size < d->alloc >> 1))<br />
realloc(qAllocMore(size, sizeof(Data)));<br />
if (d->alloc >= size) {<br />
d->size = size;<br />
if (d->data == d->array) {<br />
d->array[size] = '\0';<br />
}<br />
}<br />
}<br />
}</code><br />
<br />
With this in mind, let's see how to use <i>QSharedData</i> and <i>QSharedDataPointer</i> to <b><span class="Apple-style-span" style="color: #38761d;">implement our own</span></b> implicit shared data objects.<br />
<code class="prettyprint lang-cpp">// first implement your data object inheriting from QSharedData, which provides the reference count<br />
class SharedData: public QSharedData<br />
{<br />
public:<br />
SharedData()<br />
: QSharedData()<br />
, var(0)<br />
{}<br />
<br />
SharedData(const SharedData &other)<br />
: QSharedData(other)<br />
, var(other.var)<br />
{}<br />
<br />
int var;<br />
};<br />
<br />
// then the data owner<br />
class DataOwner<br />
{<br />
public:<br />
DataOwner()<br />
: d(new SharedData)<br />
{}<br />
<br />
DataOwner(int var)<br />
: d(new SharedData)<br />
{<br />
// for write access, the -> operator will automatically copy the shared data if needed<br />
d->var = var;<br />
}<br />
<br />
private:<br />
// this template class hides all the details for implicit sharing<br />
// therefore, no need to provide copy constructor or assignment operator<br />
QSharedDataPointer<SharedData> d;<br />
};</code><br />
<br />
Quite simple, right ;) Then just proceed to implement explicit shared data objects using <i>QExplicitlySharedDataPointer</i> yourself.Xizhi Zhuhttp://www.blogger.com/profile/11132645470363367082noreply@blogger.com0tag:blogger.com,1999:blog-1750396291995171919.post-44599481894663948952010-12-01T13:56:00.001+02:002010-12-02T12:55:57.708+02:00The Beauty of Qt 2: Meta ObjectBesides the <a href="http://xizhizhu.blogspot.com/2010/11/beauty-of-qt-1-d-pointer-private.html">D-pointers</a>, another interesting thing in Qt is the <i><b>Q_OBJECT</b></i> macro. It provides the access to meta objects, which enables you to enjoy more features of a <i>QObject</i>, e.g. signals and slots. The <span class="Apple-style-span" style="color: blue;"><b><span class="Apple-style-span" style="font-size: large;">meta object</span></b></span> provides information about class name, properties and methods of a QObject, which is also known as <a href="http://en.wikipedia.org/wiki/Reflection_(computer_science)">reflection</a>.<br />
<br />
Using <i>QMetaObject</i>, you can print the information of the class name, etc.:<br />
<code class="prettyprint lang-cpp">QObject obj;<br />
const QMetaObject *metaObj = obj.metaObject();<br />
qDebug() << "class name: " << metaObj->className();<br />
qDebug() << "class info count: " << metaObj->classInfoCount();<br />
qDebug() << "methods: ";<br />
// starting from QMetaObject::methodOffset() so it won't display the methods inherited<br />
for (int i = metaObj->methodOffset(); i < metaObj->methodCount(); ++i)<br />
qDebug() << metaObj->method(i).methodType() << " " << metaObj->method(i).signature();</code><br />
<br />
As none of these information is supported in pure C++, Qt uses the <a href="http://doc.trolltech.com/moc.html">Meta Object Compiler</a> (moc) to do all the tricks. It reads each header file, and generates a C++ source file (moc_*.cpp) containing the code for meta-object, if it finds a <i>Q_OBJECT</i> macro used in any class declaration. With the code generation approach, Qt not only gains the <b><span class="Apple-style-span" style="color: #38761d;">flexibility</span></b> as in e.g. Java, but also keeps the <b><span class="Apple-style-span" style="color: #38761d;">performance and scalability</span></b> as in C++.<br />
<br />
Suppose we have the following simple class:<br />
<code class="prettyprint lang-cpp">class MyObject : public QObject<br />
{<br />
Q_OBJECT<br />
public:<br />
explicit MyObject(QObject *parent = 0);<br />
<br />
void myFunc();<br />
<br />
public slots:<br />
void mySlot(int myParam);<br />
<br />
signals:<br />
void mySignal(int myParam);<br />
};</code><br />
<br />
The following code / information will be generated by moc, and can be retrieved through pointers defined in the anonymous struct of <i>QMetaObject::d</i>:<br />
<code class="prettyprint lang-cpp">// pointed by QMetaObject::d.data, the beginning stored "as" a QMetaObjectPrivate struct<br />
static const uint qt_meta_data_MyObject[] = {<br />
5, // revision, the internals have been changed several times<br />
0, // classname, offset of qt_meta_stringdata_MyObject<br />
<br />
// the following are defined as (number, index) pair<br />
0, 0, // classinfo<br />
2, 14, // we have two methods, starting at index 14 (i.e. the signal)<br />
0, 0, // properties<br />
0, 0, // enums/sets<br />
0, 0, // constructors<br />
<br />
0, // flags<br />
1, // signal counts<br />
<br />
// for signals slots, and properties, the signatures and parameters are offset of qt_meta_stringdata_MyObject<br />
// signals: signature, parameters, type, tag, flags<br />
18, 10, 9, 9, 0x05,<br />
<br />
// slots: signature, parameters, type, tag, flags<br />
32, 10, 9, 9, 0x0a,<br />
<br />
0 // eod<br />
};<br />
<br />
// pointed by QMetaObject::d.stringdata<br />
static const char qt_meta_stringdata_MyObject[] = {<br />
"MyObject\0\0myParam\0mySignal(int)\0"<br />
"mySlot(int)\0"<br />
};</code><br />
<br />
The above information, as well as the information for its base class, is stored as the static meta object for this class:<br />
<code class="prettyprint lang-cpp">const QMetaObject MyObject::staticMetaObject = {<br />
{ &QObject::staticMetaObject, // pointer to its base class, stored at QMetaObject::d.superdata<br />
qt_meta_stringdata_MyObject, qt_meta_data_MyObject, 0 }<br />
};</code><br />
<br />
In this way, if you want to do type cast for <i>QObject</i>, instead of using the somewhat expensive operator of <i>dynamic_cast</i>, we can use <i><b><span class="Apple-style-span" style="color: #38761d;"><span class="Apple-style-span" style="font-size: large;">qobject_cast</span></span></b></i>. It exploits the benefits of the meta object system, thus avoiding the runtime type cast:<br />
<code class="prettyprint lang-cpp">template <class T> inline T qobject_cast(QObject *object)<br />
{<br />
#if !defined(QT_NO_QOBJECT_CHECK)<br />
reinterpret_cast<t>(0)->qt_check_for_QOBJECT_macro(*reinterpret_cast<t>(object));<br />
#endif<br />
return static_cast<t>(reinterpret_cast<t>(0)->staticMetaObject.cast(object));<br />
}</t></t></t></t></code><br />
<br />
Here, the trick is that the <i>QMetaObject</i> of the target type checks if the object inherits from it:<br />
<code class="prettyprint lang-cpp">const QObject *QMetaObject::cast(const QObject *obj) const<br />
{<br />
if (obj) {<br />
const QMetaObject *m = obj->metaObject();<br />
do {<br />
if (m == this)<br />
return obj;<br />
} while ((m = m->d.superdata));<br />
}<br />
return 0;<br />
}</code><br />
<br />
Also, moc will generate some code for each <b><span class="Apple-style-span" style="color: #38761d;"><span class="Apple-style-span" style="font-size: large;">signal</span></span></b>. Whenever a signal is emitted, this function will be called internally:<br />
<code class="prettyprint lang-cpp">void MyObject::mySignal(int _t1)<br />
{<br />
void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };<br />
// it checks all the connected slots, and call each of them based on the connection type<br />
QMetaObject::activate(this, &staticMetaObject, 0, _a);<br />
}</code><br />
<br />
In the end, the slots are invoked by the generated <b><span class="Apple-style-span" style="color: #38761d;"><span class="Apple-style-span" style="font-size: large;">qt_metacall</span></span></b> function:<br />
<code class="prettyprint lang-cpp">int MyObject::qt_metacall(QMetaObject::Call _c, int _id, void **_a)<br />
{<br />
// if this function is called by the super class, just return<br />
_id = QObject::qt_metacall(_c, _id, _a);<br />
if (_id < 0)<br />
return _id;<br />
<br />
// call the function based on its ID<br />
if (_c == QMetaObject::InvokeMetaMethod) {<br />
switch (_id) {<br />
case 0: mySignal((*reinterpret_cast< int(*)>(_a[1]))); break;<br />
case 1: mySlot((*reinterpret_cast< int(*)>(_a[1]))); break;<br />
default: ;<br />
}<br />
<br />
// remove the IDs "consumed" by this class so that in its subclass the ID always starts with 0, and the return value of -1 means already consumed<br />
_id -= 2;<br />
}<br />
<br />
return _id;<br />
}</code>Xizhi Zhuhttp://www.blogger.com/profile/11132645470363367082noreply@blogger.com0tag:blogger.com,1999:blog-1750396291995171919.post-23287524623060186132010-11-25T21:01:00.000+02:002010-11-25T21:01:07.339+02:00The Beauty of Qt 1: D-Pointer / Private ImplementationI believe many of you who just start reading the <a href="http://qt.gitorious.org/">source code</a> of Qt will have the question: why Qt uses those private classes? What's the benefit of such a design pattern? Well, the most significant reason is to <b><span class="Apple-style-span" style="color: blue;"><span class="Apple-style-span" style="font-size: large;">keep the binary compatibility</span></span></b>.<br />
<br />
Then what is binary compatibility? The <a href="http://techbase.kde.org/Policies/Binary_Compatibility_Issues_With_C%2B%2B">article</a> from KDE TechBase defines it like this:<br />
<blockquote>A library is binary compatible, if a program linked dynamically to a former version of the library continues running with newer versions of the library without the need to recompile.</blockquote>With this definition in mind, the <b><span class="Apple-style-span" style="color: #38761d;">benefit</span></b> is easy to see: without it, whenever a library is updated, all the applications rely on it <span class="Apple-style-span" style="color: red;"><b><span class="Apple-style-span" style="font-size: large;">should be recompiled</span></b></span> to work. Definitely, it's totally unacceptable for any widely used libraries like Qt. More information on binary compatibility itself can be found on that article from KDE TechBase, and here I only want to share with you how it's used.<br />
<br />
Without the usage of D-pointers, we may have a class defined as below:<br />
<code class="prettyprint lang-cpp">class MyClass<br />
{<br />
public:<br />
MyClass();<br />
~MyClass();<br />
private:<br />
int myVar;<br />
};</code><br />
<br />
Obviously, the private member of <i>myVar</i> here is a big enemy of binary compatibility. There fore, we refactor the code into the following:<br />
<code class="prettyprint lang-cpp">class MyClassPrivate;<br />
class MyClass<br />
{<br />
public:<br />
MyClass();<br />
~MyClass();<br />
private:<br />
MyClassPrivate * const d_ptr;<br />
Q_DECLARE_PRIVATE(MyClass);<br />
};</code><br />
<br />
Here, we use a pointer <i>d_ptr</i> to refer to the private implementation, and the macro of <i>Q_DECLARE_PRIVATE</i> is employed to define some helper functions and friend class:<br />
<code class="prettyprint lang-cpp">#define Q_DECLARE_PRIVATE(Class) \<br />
inline Class##Private* d_func() { return reinterpret_cast<Class##Private *>(qGetPtrHelper(d_ptr)); } \<br />
inline const Class##Private* d_func() const { return reinterpret_cast<const Class##Private *>(qGetPtrHelper(d_ptr)); } \<br />
friend class Class##Private;</code><br />
<br />
Then we define the private class as below:<br />
<code class="prettyprint lang-cpp">class MyClassPrivate<br />
{<br />
public:<br />
MyClassPrivate(MyClass *parent);<br />
private:<br />
MyClass * const q_ptr;<br />
Q_DECLARE_PUBLIC(MyClass);<br />
int myVar;<br />
};</code><br />
<br />
Here, the <i>q_ptr</i> pointer points the public interface, and the <i>Q_DECLARE_PUBLIC</i> macro is used to define some helper functions:<br />
<code class="prettyprint lang-cpp">#define Q_DECLARE_PUBLIC(Class) \<br />
inline Class* q_func() { return static_cast<Class *>(q_ptr); } \<br />
inline const Class* q_func() const { return static_cast<const Class *>(q_ptr); } \<br />
friend class Class;</code><br />
<br />
And we can further use the following two macros to ease the access:<br />
<code class="prettyprint lang-cpp">#define Q_D(Class) Class##Private * const d = d_func()<br />
#define Q_Q(Class) Class * const q = q_func()</code><br />
<br />
That's all about the usage of D-pointers and private implementations in Qt. Let me use a simple sample to end this post ;)<br />
<code class="prettyprint lang-cpp">// myclass.h<br />
#ifndef MYCLASS_H<br />
#define MYCLASS_H<br />
<br />
#include <QtCore/QObject><br />
<br />
class MyClassPrivate;<br />
class MyClass: public QObject<br />
{<br />
Q_OBJECT<br />
public:<br />
MyClass(QObject *parent = 0);<br />
virtual ~MyClass();<br />
void dummyFunc();<br />
<br />
signal:<br />
void dummySignal();<br />
<br />
private:<br />
MyClassPrivate * const d_ptr;<br />
Q_DECLARE_PRIVATE(MyClass);<br />
Q_DISABLE_COPY(MyClass);<br />
};<br />
<br />
#endif // MYCLASS_H<br />
<br />
// myclass.cpp<br />
#include "myclass.h"<br />
<br />
class MyClassPrivate<br />
{<br />
public:<br />
MyClassPrivate(MyClass *parent)<br />
: q_ptr(parent)<br />
{<br />
}<br />
<br />
void foobar()<br />
{<br />
Q_Q(MyClass);<br />
emit q->dummySignal();<br />
}<br />
<br />
private:<br />
MyClass * const q_ptr;<br />
Q_DECLARE_PUBLIC(MyClass);<br />
};<br />
<br />
MyClass::MyClass(QObject *parent)<br />
: QObject(parent)<br />
, d_ptr(new MyClassPrivate(this))<br />
{<br />
}<br />
<br />
MyClass::~MyClass()<br />
{<br />
Q_D(MyClass);<br />
delete d;<br />
}<br />
<br />
void MyClass::dummyFunc()<br />
{<br />
Q_D(MyClass);<br />
d->foobar();<br />
}</code><br />
<br />
The Chinese translation is available at: <a href="http://blog.csdn.net/zhu_xz/archive/2010/11/25/6035861.aspx">http://blog.csdn.net/zhu_xz/archive/2010/11/25/6035861.aspx</a>Xizhi Zhuhttp://www.blogger.com/profile/11132645470363367082noreply@blogger.com4tag:blogger.com,1999:blog-1750396291995171919.post-68283492159119016702010-11-01T11:34:00.000+02:002010-11-01T11:34:11.855+02:00New release of Web Runtime for N900Finally, I'm happy to push the latest <a href="http://maemo.org/packages/view/qtwrt/">Web Runtime</a> (v1.1.0) for N900 to the <a href="http://wiki.maemo.org/Extras-devel">extras-devel</a> repository. Please <b><span class="Apple-style-span" style="color: red;">note</span></b> that this release is only tested against PR 1.3. There's no new features implemented compared to the <a href="http://developer.qt.nokia.com/forums/viewthread/307/">previous release</a> back in July, but only bug fixes. Personally, this is one of the last duties for me in the WRT project, and let's see what I would play with in the future ;)<br />
<blockquote><b>What is Web Runtime?</b><br />
It's a development framework with which you can write applications in standard Web technologies, like HTML, CSS, and JavaScript. Also, a bunch of Device APIs are provided to grant you the access to native resources, e.g. file system, sensors, etc., using JavaScript.</blockquote>To <b>install</b> WRT on N900, you should first enable the <a href="http://wiki.maemo.org/Extras-devel">extras-devel</a> repository.<br />
<br />
If you have the previous release installed, you should first uninstall:<br />
sudo gainroot<br />
apt-get purge libwrt-experimental1<br />
<br />
Then install the new release:<br />
sudo gainroot<br />
apt-get install qtwrt<br />
<br />
<a href="http://xizhizhu.blogspot.com/search/label/qtwrt">Have fun</a> and feel free to go to the <a href="http://developer.qt.nokia.com/forums/viewforum/20/">public forum</a> for more questions ;)Xizhi Zhuhttp://www.blogger.com/profile/11132645470363367082noreply@blogger.com10tag:blogger.com,1999:blog-1750396291995171919.post-38599906597293496042010-10-28T19:36:00.000+03:002013-09-10T09:56:41.674+03:00Hybrid application using QML and Qt C++Moved to <a href="http://www.zionsoft.net/2010/10/hybrid-application-qml-qt/">http://www.zionsoft.net/2010/10/hybrid-application-qml-qt/</a><br />
<br />
Though <a href="http://doc.qt.nokia.com/4.7/qdeclarativeintroduction.html">QML</a> provides a nice way to design user interfaces, and JavaScript is employed there to implement the application logic and works pretty nice in many cases, we might still need Qt C++ in some situations (well, at least JavaScript has limited access outside its sandbox).<br />
<br />
<b><span class="Apple-style-span" style="color: blue;">1) integrate QML into Qt C++</span></b><br />
Suppose we have a QML file, named "myqml.qml", like this:<br />
<code class="prettyprint lang-javascript">// this line should be "import QtQuick 1.0" since Qt 4.7.1<br />
import Qt 4.7<br />
<br />
Rectangle {<br />
id: myRectangle<br />
width: 800<br />
height: 480<br />
color: "lightgray"<br />
<br />
Text {<br />
id: myText<br />
text: "I love hybrid application!"<br />
anchors.centerIn: parent<br />
font.pointSize: 28<br />
font.bold: true<br />
}<br />
}</code><br />
<br />
One easy way to integrate is to use the <a href="http://doc.qt.nokia.com/4.7/qdeclarativeview.html">QDeclarativeView</a> class, which provides a widget to display QML files. You just need the following three lines:<br />
<code class="prettyprint lang-cpp">QDeclarativeView view;<br />
view.setSource(QUrl::fromLocalFile("myqml.qml"));<br />
view.show();</code><br />
<br />
However, <i>QDeclarativeView</i> consumes more resources than normal widgets. Fortunately, we can <b><span class="Apple-style-span" style="color: #38761d;"><span class="Apple-style-span" style="font-size: large;">integrate QML into a graphics scene</span></span></b>. The following lines shows the basic usage:<br />
<code class="prettyprint lang-cpp">// provides an environment for instantiating QML components<br />
QDeclarativeEngine engine;<br />
<br />
// encapsulates a QML component definition<br />
QDeclarativeComponent component(&engine, QUrl::fromLocalFile("myqml.qml"));<br />
<br />
// creates the graphics item for QML at the engine's root context<br />
QDeclarativeItem *item = qobject_cast<QDeclarativeItem *>(component.create());<br />
<br />
scene.addItem(item);</code><br />
<br />
Then with the help of the <i>QDeclarativeItem</i> class, you can easily <b><span class="Apple-style-span" style="color: #38761d;">access the properties</span></b> of the QML element, e.g.:<br />
<code class="prettyprint lang-cpp">qDebug() << item->property("color").typeName();<br />
item->setProperty("color", QColor(255, 255, 255));</code><br />
<br />
<b><span class="Apple-style-span" style="color: blue;">2) exposing Qt C++ objects to QML</span></b><br />
You can also <b><span class="Apple-style-span" style="color: #38761d;">expose native Qt C++ objects to QML</span></b> through <i>QDeclarativeContext</i>:<br />
<code class="prettyprint lang-cpp">QDeclarativeContext *context = engine->rootContext();<br />
context->setContextProperty("textFromQt", QString("I love hybrid application!"));</code><br />
<br />
Then in QML, you can have e.g. the following line to access them:<br />
<code class="prettyprint lang-javascript">text: textFromQt</code><br />
<br />
You can also use <i>QDeclarativePropertyMap</i> to manage the exposed properties:<br />
<code class="prettyprint lang-cpp">QDeclarativePropertyMap map;<br />
map.insert("key1", "value1");<br />
map.insert("key2", "value2");<br />
context->setContextProperty("map", &map);</code><br />
<br />
<blockquote>In a QML engine, there could be a couple of contexts, forming a tree structure. The child contexts inherit properties in the parent context. By default, there is only one root context, but you can always add more to give finer control of the exposed data, i.e. different QDeclarativeComponent inside the same context have the same exposed data set.</blockquote><br />
To <b><span class="Apple-style-span" style="color: #38761d;">expose a self-defined object</span></b>, we can use the following code:<br />
<code class="prettyprint lang-cpp">// define a class with properties<br />
class MyObject: public QObject<br />
{<br />
Q_OBJECT<br />
<br />
// the NOTIFY signal is needed to inform about changes<br />
// all properties will be exposed to QML<br />
Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)<br />
public:<br />
MyObject(QObject *parent = 0) : QObject(parent), m_text("I love hybrid application!") {}<br />
<br />
QString text() const { return m_text; }<br />
void setText(QString &text)<br />
{<br />
m_text = text;<br />
emit textChanged();<br />
}<br />
<br />
signals:<br />
void textChanged();<br />
<br />
private:<br />
QString m_text;<br />
};<br />
<br />
// then just expose it so QML can access it through name "myObject"<br />
engine->rootContext()->setContextProperty("myObject", new MyObject());</code><br />
<br />
Moreover, we can <b><span class="Apple-style-span" style="font-size: large;"><span class="Apple-style-span" style="color: #38761d;">create new QML types</span></span></b>:<br />
<code class="prettyprint lang-cpp">// define the new type<br />
class MyType : public QDeclarativeItem<br />
{<br />
Q_OBJECT<br />
<br />
public:<br />
MyType(QDeclarativeItem *parent = 0) : QDeclarativeItem(parent)<br />
{<br />
setFlag(QGraphicsItem::ItemHasNoContents, false);<br />
}<br />
<br />
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0)<br />
{<br />
QPen pen(QColor(100, 100, 100), 2);<br />
painter->setPen(pen);<br />
painter->drawLine(0, 100, 100, 100);<br />
}<br />
};<br />
<br />
// then register to expose it<br />
qmlRegisterType<mychart>("com.blogspot.xizhizhu.mytype", 1, 0, "MyType");</code><br />
<br />
In QML, you can use it like this:<br />
<code class="prettyprint lang-javascript">import com.blogspot.xizhizhu.mytype 1.0<br />
<br />
MyChart {<br />
id: myChart<br />
width: 100<br />
height: 200<br />
}</code><br />
<br />
Now let's jump to <b><span class="Apple-style-span" style="color: #38761d;">invoke a Qt C++ function from QML</span></b>. Basically, QML can invoke slots and functions declared with <i>Q_INVOKABLE</i>. Suppose we have the following function in MyObject:<br />
<code class="prettyprint lang-cpp">Q_INVOKABLE void showMessage()<br />
{<br />
QMessageBox::information(NULL, "My Test", "Invoking a native function ;)");<br />
}</code><br />
<br />
Then you can invoke it in QML:<br />
<code class="prettyprint lang-javascript">myObject.showMessage();</code><br />
<br />
<b><span class="Apple-style-span" style="color: blue;">3) write plugins as QML extension</span></b><br />
The benefits for using plugins as QML extensions are similar to using shared libraries, and it can be easily achieved with the help of <i>QDeclarativeExtensionPlugin</i>. Let's reuse the MyType class defined in the previous section. First, we need to <b>create a plugin</b>:<br />
<code class="prettyprint lang-cpp">class MyPlugin : public QDeclarativeExtensionPlugin<br />
{<br />
Q_OBJECT<br />
public:<br />
void registerTypes(const char *uri)<br />
{<br />
qmlRegisterType<MyType>(uri, 1, 0, "MyType");<br />
}<br />
};<br />
<br />
Q_EXPORT_PLUGIN2(myPlugin, MyPlugin);</code><br />
<br />
Then <b>create a file named "qmldir"</b> to define which plugin to load from where (suppose the plugin is called "myplugin):<br />
<code class="prettyprint lang-javascript">plugin myplugin /path/to/plugin</code><br />
<br />
Now we can use <i>qmlviewer</i> to launch the QML file:<br />
<code class="prettyprint lang-javascript">// no need to import now<br />
MyChart {<br />
id: myChart<br />
width: 100<br />
height: 200<br />
}</code><br />
<br />
<b><span class="Apple-style-span" style="color: blue;">4) summary</span></b><br />
<li>Use <i>QDeclarativeView</i> or <i>QDeclarativeComponent</i> to integrate a QML file into native Qt C++.</li><li>Qt C++ can access the properties of QML elements through <i>QDeclarativeItem</i>.</li><li>Expose native objects to QML through <i>QDeclarativeContext</i>.</li><li>New QML types can be exported through <i>qmlRegisterType</i>.</li><li>The properties of native objects are exported as properties, and the slots or functions declared with Q_INVOKABLE can be invoked in QML.</li><li>Create plugins for extension using <i>QDeclarativeExtensionPlugin</i>.</li>Xizhi Zhuhttp://www.blogger.com/profile/11132645470363367082noreply@blogger.com11tag:blogger.com,1999:blog-1750396291995171919.post-56135134856199291592010-09-10T22:23:00.004+03:002010-09-15T14:49:04.566+03:00Unofficial Qt Web Runtime tutorial 2: Menu APIIf there is no API, Qt WRT is merely nothing but a naive web browser. Then what APIs are supported other than standard HTML and JavaScript now? You can first get a list of features already supported, or to be supported in the near future <a href="http://bugs.meego.com/showdependencytree.cgi?id=2772&hide_resolved=0">here</a>.<br />
<br />
As a summary, we have already supported the APIs of menus, <a href="http://www.w3.org/TR/widgets-apis/">widget object</a>, <a href="http://www.w3.org/TR/widgets-uri/">URI schemes</a>, <a href="http://trac.webkit.org/wiki/WebInspector">web inspector</a>, console log, some Device APIs, as well as some HTML 5 features and standard JavaScript from Qt WebKit. Let's start with the menu API.<br />
<br />
<b><span class="Apple-style-span" style="color: blue;">1 view menu</span></b><br />
You can create <b>the menu items to the chrome's menu bar</b> (we call it view menu) with the following JavaScript code:<br />
<code class="prettyprint lang-javascript">var menuItem = new nokia.device.MenuItem("Menu item", changeTitle);<br />
nokia.device.menu.addMenuItem(menuItem);<br />
function changeTitle()<br />
{ <br />
nokia.device.menu.title = "New title"; <br />
}</code><br />
<br />
Here, you have created a menu item named "Menu item" and added it to the menu bar. When it's triggered, the function changeTitle() will be called to set the menu's title to "New title".<br />
<br />
<b>Note</b> that since on the device the menu's title is also the same as the window's title, it actually changes the window's title too.<br />
<br />
<b><span class="Apple-style-span" style="color: blue;">2 context menu</span></b><br />
The <b>context menu</b> can be created with the following piece of code:<br />
<code class="prettyprint lang-javascript">var contextMenu = new nokia.device.ContextMenu("contextMenuArea");<br />
var changeTitleItem = new nokia.device.MenuItem("Change Title");<br />
changeTitleItem.onselect = changeTitle;<br />
contextMenu.addMenuItem(changeTitleItem);</code><br />
<br />
Here, a context menu is created and an item named "Change Title" is added to the menu. When you long tap on the HTML element with id "contextMenuArea", this context menu will pop up. Then if you select the "Change Title" item, the changeTitle() function will be called.<br />
<br />
<blockquote>Of course, only the widgets in the <i>windowed</i> or <i>fullscreen</i> mode could have <b>context menus</b>; and only the widgets in the <i>windowed</i> mode can have <b>view menus</b>.</blockquote><br />
<b>Note</b> that there's a known bug (already fixed for the next release) that if you long tap on the area where no context menu is defined, an empty context menu is popped-up.<br />
<br />
<b><span class="Apple-style-span" style="color: blue;">3 sample</span></b><br />
Only the HTML file this time ;)<br />
<code class="prettyprint lang-html"><html><br />
<header><br />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"><br />
<title>Menu sample</title><br />
<script type="text/javascript"><br />
function changeTitle()<br />
{<br />
if (nokia.device.menu.title == "Title 1")<br />
nokia.device.menu.title = "Title 2";<br />
else<br />
nokia.device.menu.title = "Title 1";<br />
}<br />
<br />
function init()<br />
{<br />
var menuItem = new nokia.device.MenuItem("item", changeTitle);<br />
nokia.device.menu.addMenuItem(menuItem);<br />
<br />
var contextMenu = new nokia.device.ContextMenu("contextMenuArea");<br />
contextMenu.addMenuItem(menuItem);<br />
}<br />
</script><br />
</header><br />
<body onload="init()"><br />
<div id="contextMenuArea">There is a context menu.</div><br />
</body><br />
</html></code><br />
<br />
As you can see, one menu item can be added to multiple menus, exactly the same as native Qt apps. Here goes some screenshots:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://media.share.ovi.com/m1/s/2428/c180ec06bf9f4804850c76e13ff5be20.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="192" src="http://media.share.ovi.com/m1/s/2428/c180ec06bf9f4804850c76e13ff5be20.jpg" width="320" /></a> <a href="http://media.share.ovi.com/m1/s/2428/d13371e97dfc4657a55d8887edfe6459.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="192" src="http://media.share.ovi.com/m1/s/2428/d13371e97dfc4657a55d8887edfe6459.jpg" width="320" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://media.share.ovi.com/m1/s/2428/fa9df2d3f04e4b5196488145bdff67e0.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="192" src="http://media.share.ovi.com/m1/s/2428/fa9df2d3f04e4b5196488145bdff67e0.jpg" width="320" /></a> <a href="http://media.share.ovi.com/m1/s/2431/c099edca2f2247fd832c03ed7b83ca49.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="192" src="http://media.share.ovi.com/m1/s/2431/c099edca2f2247fd832c03ed7b83ca49.jpg" width="320" /></a></div><br />
The first one shows the simple sample when launched. The second and third one show the view menu and the context menu, respectively, while the last one shows that the title has been updated after you tap on the menu. More screenshots can be found <a href="http://share.ovi.com/album/xizhizhu.QtWebRuntim">here</a>, while the sample code is available <a href="http://gitorious.org/xizzhu-samples/qtwrt-menu-sample">here</a>.Xizhi Zhuhttp://www.blogger.com/profile/11132645470363367082noreply@blogger.com6tag:blogger.com,1999:blog-1750396291995171919.post-4539316286332275902010-08-18T23:07:00.010+03:002010-09-10T17:47:06.133+03:00Unofficial QtWRT tutorial 1: Hello, view modes!Almost one month ago, we <a href="http://labs.trolltech.com/blogs/2010/07/19/the-qt-web-runtime-journey-begins/">announced</a> Qt Web Runtime, and <a href="http://download.qt.nokia.com/qtwrt/">released</a> some snapshot for N900. Basically, QtWRT is a framework, using which you can write "native" application with standard web technology, e.g. HTML, CSS, and JavaScript. As a good starting point, you should take a look at <a href="http://dkothari.blogspot.com/2010/08/qt-web-runtime-for-n900.html">this article</a>.<br />
<br />
<b>Note that we're still working on it, and it's now just in the technology preview state ;)</b><br />
<br />
<b><span class="Apple-style-span" style="color: blue;">1 install QtWRT</span></b><br />
You should <a href="http://wiki.maemo.org/Extras-devel">enable the extras-devel repository</a> on your Rover and install the <b><i>qtwrt-experimental</i></b> package from there. Then, you can find in your Application Manager that Qt Web Runtime Technology Preview for N900 installed.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://media.share.ovi.com/m1/s/2371/612d8bc2545744dca9ccbf497309bbc8.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="192" src="http://media.share.ovi.com/m1/s/2371/612d8bc2545744dca9ccbf497309bbc8.jpg" width="320" /></a></div><br />
<b><span class="Apple-style-span" style="color: blue;">2 config.xml</span></b><br />
To write your own web applications, besides the normal HTML pages, you also need a <b>config.xml<i></i></b> file to define e.g. the starting file, icon, features you need (i.e. access to Device APIs), as well as author's information, etc. More details and default values are defined <a href="http://www.w3.org/TR/widgets/">here</a>.<br />
<br />
The following piece shows a minimum sample:<br />
<code class="prettyprint lang-xml"><?xml version="1.0" encoding="UTF-8"?><br />
<widget xmlns = "http://www.w3.org/ns/widgets"><br />
</widget></code><br />
<br />
You can also define the name and icon (only PNG files supported) of the web app in config.xml:<br />
<code class="prettyprint lang-xml"><?xml version="1.0" encoding="UTF-8"?><br />
<widget xmlns = "http://www.w3.org/ns/widgets"><br />
<name>A sample web app</name><br />
<icon src="app_icon.png" /><br />
</widget></code><br />
The name and icon will be appeared in the Application Grid or the Desktop menu --> Add widget based on the view mode the web app supports (see below).<br />
<br />
<b><span class="Apple-style-span" style="color: blue;">3 view modes</span></b><br />
View modes define the visual presentation of web applications. The W3C spec has <a href="http://www.w3.org/TR/view-mode/">defined</a> five different view modes, but we only support three of them in this snapshot:<br />
<b>windowed</b> - The default view mode. You can find / launch web apps in this mode from the Application Grid. It also supports the native chromes and user-defined menus.<br />
<b>fullscreen</b> - It can also be found / launched from the Application Grid. No need to say what is full screen, right ;)<br />
<b>minimized</b> - It equals to the native widgets on the Home Screen.<br />
<br />
The following piece defines the view modes in config.xml:<br />
<code class="prettyprint lang-xml"><?xml version="1.0" encoding="UTF-8"?><br />
<widget xmlns = "http://www.w3.org/ns/widgets"<br />
viewmodes = "someviewmode fullscreen minimized" ><br />
</widget></code><br />
The unknown view mode "someviewmode" is ignored. It supports both "fullscreen" and "minimized" mode in this case. If no supported view mode is defined, "windowed" mode is used.<br />
<br />
You can get the current view mode through the <b>widget.viewMode</b> interface in JavaScript.<br />
<br />
Also, the transfer among different view modes is supported, with the exception from windowed / fullscreen to minimized, e.g.:<br />
<code class="prettyprint lang-html"><a href="javascript:widget.viewMode='windowed'">Go to windowed mode</a></code><br />
<br />
With the following code, you can handle the view mode change event in the viewModeChanged function:<br />
<code class="prettyprint lang-javascript">widget.onviewmodechange = viewModeChanged;<br />
function viewModeChanged(mode)<br />
{<br />
if (mode == "windowed") {<br />
// going to windowed mode<br />
} else if (mode == "minimized") {<br />
// going to minimized mode<br />
} else if (mode == "fullscreen") {<br />
// going to full screen mode<br />
}<br />
}</code><br />
<br />
<b><span class="Apple-style-span" style="color: blue;">4 package your application and install it</span></b><br />
Well, I just assume you have enough knowledge to write whatever HTML page you like, and have renamed it to <b><i>index.htm</i></b> (the default starting file name).<br />
<br />
Now just zip all your HTML files together with the config.xml file. <b>Note</b> that the config.xml file should be at the top level of the zip, and the name is case sensitive.<br />
<br />
Then please rename it to *.wgt and copy it to your Rover. To make it like a native application, you can install it from the File Manager, and you can find your installed web applications in Application Manager!<br />
<br />
<blockquote>Eh, I'm talking about some details during the installation here. You can skip this if not interested.<br />
<br />
When you tap on the wgt file in File Manager, <i>widgetinstaller</i> is launched. It does some sanity checking of it, e.g. whether it's a valid zip file, if the config.xml is valid, etc., then convert it to a Debian file, and use the Application Manager to install the generated Debian file.<br />
<br />
If you are interested in the generated Debian file, you can use the "--no-install" option of the widgetinstaller to have it copied to the current directory.</blockquote><br />
<b><span class="Apple-style-span" style="color: blue;">5 a sample</span></b><br />
First, let's write the <b>config.xml</b> file.<br />
<code class="prettyprint lang-xml"><?xml version="1.0" encoding="UTF-8"?><br />
<widget xmlns="http://www.w3.org/ns/widgets"<br />
id="http://xizhizhu.blogspot.com/qtwrt/view-modes-sample"<br />
viewmodes="minimized fullscreen windowed"><br />
<name>View Modes Sample</name><br />
<description><br />
Well, it shows how the view modes work.<br />
</description><br />
<author href="http://xizhizhu.blogspot.com/" email="xizhi.zhu@gmail.com">Xizhi Zhu</author><br />
<license>In the public domain without any warranty.</license><br />
</widget></code><br />
<br />
Then the HTML file.<br />
<code class="prettyprint lang-html"><html><br />
<header><br />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"><br />
<title>View Modes</title><br />
<script type="text/javascript"><br />
function init()<br />
{<br />
output = document.getElementById("viewmode");<br />
output.innerHTML = widget.viewMode;<br />
<br />
widget.onviewmodechange = changeViewMode;<br />
}<br />
<br />
function changeViewMode(mode)<br />
{<br />
output.innerHTML = widget.viewMode;<br />
}<br />
</script><br />
</header><br />
<br />
<body onload="init()"><br />
<div id="viewmode"></div><br /><br />
<a href="javascript:widget.viewMode='minimized'">minimized</a><br /><br />
<a href="javascript:widget.viewMode='windowed'">windowed</a><br /><br />
<a href="javascript:widget.viewMode='fullscreen'">fullscreen</a><br />
</body><br />
</html></code><br />
<br />
Now let's zip the file, send it to N900 and install it from the File Manager. You can find it installed in the Application Manager and already launched in the home screen.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://media.share.ovi.com/m1/s/2371/e60a8041c7d84c70909e0be9b48c379f.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="192" src="http://media.share.ovi.com/m1/s/2371/e60a8041c7d84c70909e0be9b48c379f.jpg" width="320" /></a><a href="http://media.share.ovi.com/m1/s/2371/67a55e14988b4ed290d4e21943addb79.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="192" src="http://media.share.ovi.com/m1/s/2371/67a55e14988b4ed290d4e21943addb79.jpg" width="320" /></a></div><br />
You may ask, why the last line of "fullscreen" is not shown there? Well, that's due to the <b>fixed size</b> in the <i>minimized</i> mode, 312x82. Also, in the <i>minimized</i> mode, you can't actually interact with it, but only tap on it and open the <i>windowed</i> or <i>fullscreen</i> mode if supported. In the <i>minimized</i> mode, it's <b>the same as native widgets</b> that you can move it around, close it and add it back, as well as the transparent background by default.<br />
<br />
Then you can tap the links to toggle between <i>windowed</i> and <i>fullscreen</i> mode. And for sure you'll find another "limitation" that you can't go back to <i>minimized</i> mode from the link. The only way is to close the window. Well, that's exactly what is expected.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://media.share.ovi.com/m1/s/2371/90ca8dbb537d4053afb2bcd781a37922.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="192" src="http://media.share.ovi.com/m1/s/2371/90ca8dbb537d4053afb2bcd781a37922.jpg" width="320" /></a><a href="http://media.share.ovi.com/m1/s/2371/7b05ca2788c349b280a02733b392cc1b.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="192" src="http://media.share.ovi.com/m1/s/2371/7b05ca2788c349b280a02733b392cc1b.jpg" width="320" /></a></div><br />
<br />
Another thing is, in the <i>fullscreen</i> mode, it automatically shows the "go back to windowed" button if <i>windowed</i> mode is supported, otherwise the "close" button. Emm, the same as the browser, right?<br />
<br />
<br />
<b>Updated on 19.8.2010</b><br />
Screenshots added into the posts ;)Xizhi Zhuhttp://www.blogger.com/profile/11132645470363367082noreply@blogger.com13tag:blogger.com,1999:blog-1750396291995171919.post-76278972135774973322010-08-16T22:13:00.000+03:002010-08-16T22:13:24.617+03:00Basic samples for SSL communication over Qt<b><span class="Apple-style-span" style="color: blue;">1) client</span></b><br />
<code class="prettyprint lang-cpp">class SSLClient: public QObject<br />
{<br />
Q_OBJECT<br />
<br />
public:<br />
SSLClient(QObject* parent = NULL)<br />
: QObject(parent)<br />
{<br />
connect(&client, SIGNAL(encrypted()),<br />
this, SLOT(connectionEstablished()));<br />
connect(&client, SIGNAL(sslErrors(const QList<QSslError> &)),<br />
this, SLOT(errorOccured(const QList<QSslError> &)));<br />
}<br />
<br />
void start(QString hostName, quint16 port)<br />
{<br />
client.setProtocol(QSsl::TlsV1);<br />
client.connectToHostEncrypted(hostName, port);<br />
}<br />
<br />
public slots:<br />
// handle the signal of QSslSocket.encrypted()<br />
void connectionEstablished()<br />
{<br />
// get the peer's certificate<br />
QSslCertificate cert = client.peerCertificate();<br />
<br />
// write on the SSL connection<br />
client.write("hello, world", 13);<br />
}<br />
<br />
// handle the signal of QSslSocket.sslErrors()<br />
void errorOccured(const QList<QSslError> &error)<br />
{<br />
// simply ignore the errors<br />
// it should be very careful when ignoring errors<br />
client.ignoreSslErrors();<br />
}<br />
<br />
private:<br />
QSslSocket client;<br />
};<br />
<br />
<br />
int main(int argc, char** argv)<br />
{<br />
QApplication app(argc, argv);<br />
<br />
SSLClient client;<br />
client.start("127.0.0.1", 8888);<br />
<br />
return app.exec();<br />
}</code><br />
<br />
<br />
<b><span class="Apple-style-span" style="color: blue;">2) server</span></b><br />
<code class="prettyprint lang-cpp">class SSLServer: public QTcpServer<br />
{<br />
Q_OBJECT<br />
<br />
public:<br />
SSLServer(QObject* parent = NULL)<br />
: QTcpServer(parent)<br />
{<br />
}<br />
<br />
void start(QString certPath, QString keyPath, quint16 port)<br />
{<br />
listen(QHostAddress::Any, port);<br />
this->certPath = certPath;<br />
this->keyPath = keyPath;<br />
}<br />
<br />
public slots:<br />
void readyToRead()<br />
{<br />
qDebug() << serverSocket->readAll();<br />
}<br />
<br />
void errorOccured(const QList<QSslError> &)<br />
{<br />
serverSocket->ignoreSslErrors();<br />
}<br />
<br />
protected:<br />
void incomingConnection(int socketDescriptor)<br />
{<br />
serverSocket = new QSslSocket;<br />
if (serverSocket->setSocketDescriptor(socketDescriptor)) {<br />
connect(serverSocket, SIGNAL(readyRead()), this, SLOT(readyToRead()));<br />
connect(serverSocket, SIGNAL(sslErrors(const QList<QSslError> &)),<br />
this, SLOT(errorOccured(const QList<QSslError> &)));<br />
serverSocket->setProtocol(QSsl::TlsV1);<br />
serverSocket->setPrivateKey(keyPath);<br />
serverSocket->setLocalCertificate(certPath);<br />
serverSocket->startServerEncryption();<br />
} else {<br />
delete serverSocket;<br />
}<br />
}<br />
<br />
private:<br />
QSslSocket *serverSocket;<br />
QString certPath;<br />
QString keyPath;<br />
};<br />
<br />
int main(int argc, char** argv)<br />
{<br />
QApplication app(argc, argv);<br />
<br />
SSLServer server;<br />
server.start("ca.cer", "ca.key", 8888);<br />
<br />
return app.exec();<br />
}</code>Xizhi Zhuhttp://www.blogger.com/profile/11132645470363367082noreply@blogger.com10tag:blogger.com,1999:blog-1750396291995171919.post-2304825758947461582010-05-30T14:40:00.000+03:002010-05-30T14:40:43.918+03:00JavaScript benchmarking on N900 PR1.2Two months earlier, I did my <a href="http://xizhizhu.blogspot.com/2010/03/javascript-benchmarking-on-n900-and-my.html">JavaScript benchmarking</a> on N900 PR1.1, and compare it with other platforms. Now, as N900 PR1.2 got released, Opera has <a href="http://labs.opera.com/news/2010/05/11/">released</a> a preview for Maemo, and Chrome is ported to N900 by <a href="http://jacekowski.org/maemo/index.html">Jacekowski</a>, I did another round of benchmarking.<br />
<br />
<table><tr><td></td><td><b>V8</b></td><td><b>SunSpider</b></td><td><b>Peacekeeper</b></td></tr>
<tr><td><b>MicroB (default browser)</b></td><td>21.2</td><td>35.12</td><td>128</td></tr>
<tr><td><b>FireFox</b></td><td>21.4</td><td>15.84</td><td>141</td></tr>
<tr><td><b>Opera</b></td><td>49.5</td><td>24.41</td><td>119</td></tr>
<tr><td><b>Qt 4.6.2</b></td><td>105</td><td>12.04</td><td>238</td></tr>
<tr><td><b><a href="http://gitorious.org/+qtwebkit-packagers/webkit/qtwebkit-maemo5">QtWebKit 2.0</a></b></td><td>104</td><td>9.36</td><td>286</td></tr>
<tr><td><b>Chrome</b></td><td>113</td><td>8.84</td><td>344</td></tr>
</table>For V8 and Peacemaker, the higher the score, the better performance it has. For Sunspider, it's the lower the better.<br />
<br />
Chrome is really fast as a result of its excellent V8 JavaScript engine and frequent release cycle.<br />
<br />
Qt 4.6.2 is still quite good, especially considering the fact that the WebKit integrated is quite old. Note that QtWebKit will be released <a href="http://labs.trolltech.com/blogs/2010/03/03/qtwebkit-releases/">separately</a> from Qt, meaning we could enjoy more about the latest WebKit technology then.<br />
<br />
However, both Opera and FireFox (MicroB uses FireFox's Gecko JavaScript engine) have quite a long way to go. Moreover, when running V8 and Peacekeeper, both MicroB and FireFox complained about unresponsive JavaScript.Xizhi Zhuhttp://www.blogger.com/profile/11132645470363367082noreply@blogger.com1tag:blogger.com,1999:blog-1750396291995171919.post-43354089582090687832010-05-15T22:43:00.003+03:002010-08-18T23:13:13.525+03:00这位评论真的用过N900吗?!刚看了一篇<a href="http://mobile.it168.com/a2010/0515/886/000000886613_2.shtml">谈论手机杯具</a>的文章,说的是N900。不过很怀疑这位老兄是否真的用过N900......<br />
<br />
文章说:N900最大的尴尬在于它那被消极淡化的通话功能。<br />
话说Nokia对Maemo/MeeGo系列的定义是“移动电脑”(mobile computer)吧!打开N900的<a href="http://maemo.nokia.com/n900/">官方首页</a>,上面就写得非常清楚:Nokia N900 mobile computer。本来定位就不是智能手机,所以通话功能被“淡化”不正常吗?或者说你见过哪部PDA会“强化”电话功能的?好吧,你会说我这样强词夺理了,那我们接着看......<br />
<br />
然后文章对N900的“消极淡化通话功能”列出了几个“铁证”:<br />
1,机身正面没有任何拨号快捷键,哪怕是触控按键都没有。<br />
2,默认桌面菜单也没有任何与通话相关的快捷方式。<br />
3,QWERTY全键盘采用了三排式的布局,因此并没有单独的数字键。也就是说,打开侧滑盖还是没法直接拨号。<br />
4,没有竖屏模式,也就是说诺基亚设计它的初衷就是让你始终横着拿它。横着打电话?有难度吧。。。<br />
<br />
好吧,我们看图说话:<br />
<div class="separator" style="clear: both; text-align: left;"><a href="http://3.bp.blogspot.com/_j2Abq_R5P6w/S-7vRN42zTI/AAAAAAAADZU/8rV6v-Fdswk/s1600/homescreen.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/_j2Abq_R5P6w/S-7vRN42zTI/AAAAAAAADZU/8rV6v-Fdswk/s320/homescreen.jpg" /></a></div>这是我N900上四个桌面之一,上面可以任意摆设各种Widget、快捷方式和联系人,也可以自行调整其放置的位置。标号为1的红圈就是<b>联系人</b>的快捷方式,标号为2的红圈是<b>最近通话和拨号功能</b>的快捷方式,标号为3的红圈则是放在<b>单个联系人</b>的快捷方式。当然单个联系人也是可以自定义头像的,只不过考虑到隐私我暂时删除罢了。<br />
<br />
当然了,默认情况下,桌面也是有联系人和最近通话的快捷方式的,好像也有邮件或者短信息的快捷方式......我就不刷机证明了啊;)<br />
<br />
当然了,既然有如此方便的软键盘拨号,为何还要打开侧滑盖呢?<br />
<div class="separator" style="clear: both; text-align: left;"><a href="http://4.bp.blogspot.com/_j2Abq_R5P6w/S-75JVseeNI/AAAAAAAADZs/WtWzvp3h_fw/s1600/20100515_001.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/_j2Abq_R5P6w/S-75JVseeNI/AAAAAAAADZs/WtWzvp3h_fw/s320/20100515_001.jpg" /></a></div><br />
然后我们再看看“没有竖屏模式”的笑话!你点开最近通话和拨号功能,然后看下图:<br />
<div class="separator" style="clear: both; text-align: left;"><a href="http://3.bp.blogspot.com/_j2Abq_R5P6w/S-7zjLp2xUI/AAAAAAAADZc/qYLlr3R5u5o/s1600/portrait.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/_j2Abq_R5P6w/S-7zjLp2xUI/AAAAAAAADZc/qYLlr3R5u5o/s320/portrait.jpeg" /></a></div>我觉得这个应该叫做“竖屏模式”了吧?!而且通话功能的竖屏模式是默认开启的......<br />
<br />
我想,我只能说这位搞评论的朋友没有用过N900吧!<br />
<br />
PS 这三张照片都是用另一部N900的相机在晚上10点左右拍摄的,外界光线不好,室内也没开灯:)Xizhi Zhuhttp://www.blogger.com/profile/11132645470363367082noreply@blogger.com1tag:blogger.com,1999:blog-1750396291995171919.post-41511108687021094072010-03-20T15:11:00.027+02:002010-04-19T05:52:55.140+03:00JavaScript benchmarking on N900 and my laptopI just ran some JavaScript benchmark tests of <a href="http://v8.googlecode.com/svn/data/benchmarks/v5/run.html">V8 version 5</a>, <a href="http://www2.webkit.org/perf/sunspider-0.9.1/sunspider-0.9.1/driver.html">SunSpider v0.9.1</a> and <a href="http://service.futuremark.com/peacekeeper/run.action">Peacekeeper</a> on my laptop. My laptop is HP EliteBook 6930p, which has Intel Core 2 Duo CPU P8600 @ 2.40GHz, 4 GB RAM, running KUbuntu 9.10 with kernel 2.6.31-20-generic. Also, I ran it on my N900 PR1.1 with Qt 4.6.2, and collected some results for <a href="http://arstechnica.com/apple/reviews/2009/06/iphone-3g-s-review.ars/6">iPhone 3GS</a>, <a href="http://www.gubatron.com/blog/2010/01/10/droid-vs-nexus-1-sunspider-javascript-benchmark-showdown/">Droid and Nexus One</a>, and <a href="http://mobile.zol.com.cn/174/1744080.html">HTC Desire</a>.<br />
<br />
The following scores are from <strong>V8</strong>, the higher the better.<br />
FireFox for Ubuntu 3.5.8 - 248<br />
Qt 4.6.2 – 910<br />
Chrome 5.0.307.11 Beta – 4155<br />
QtWebKit 2.0 – 2816<br />
N900 - 105<br />
iPhone 3GS - no results<br />
Droid - 39.5<br />
Nexus One - 63.5<br />
HTC Desire - 66.1<br />
<br />
Then I found some <a href="http://arstechnica.com/apple/reviews/2009/06/iphone-3g-s-review.ars/6">results</a> of iPhone 3GS for V8 version 3:<br />
N900 - 103<br />
iPhone 3GS - 53<br />
<br />
The following scores are from <strong>SunSpider</strong>, the lower the better.<br />
FireFox for Ubuntu 3.5.8 – 2484.7<br />
Qt 4.6.2 – 1136.0<br />
Chrome 5.0.307.11 Beta – 462.1<br />
QtWebKit 2.0 – 635.6<br />
N900 - 12.5<br />
iPhone 3GS - 16.7<br />
Droid - 34.2<br />
Nexus One - 14.7<br />
HTC Desire - 12.02<br />
<br />
The following scores are from <strong>Peacekeeper</strong>, the higher the better.<br />
FireFox for Ubuntu 3.5.8 – 1510<br />
Qt 4.6.2 – 3261<br />
Chrome 5.0.307.11 Beta – 4324<br />
QtWebKit 2.0 – 4288<br />
N900 - 244<br />
<br />
Chrome’s V8 engine is <span style="color: red;"><strong>really fast</strong></span>, and WebKit still has a long way to go!<br />
<br />
Also, N900 performs <span style="color: red;"><strong>much better</strong></span> than iPhone 3GS, Droid and Nexus. Considering HTC Desire, N900 wins easily on V8, but lost a little on SunSpider. However, if you consider MicroB, the default browser on N900, it’s a <b>disaster</b> due to the slow engine of Gecko and N900 even used a pretty old version.<br />
<br />
Then the <a href="http://acid3.acidtests.org/">ACID3</a> test.<br />
FireFox for Ubuntu 3.5.8 – 93<br />
Qt 4.6.2 – 100<br />
Chrome 5.0.307.11 Beta – 100<br />
QtWebKit 2.0 – 100<br />
<br />
<br />
* The test for QtWebKit 2.0 is done with the revision number of 56441.Xizhi Zhuhttp://www.blogger.com/profile/11132645470363367082noreply@blogger.com0tag:blogger.com,1999:blog-1750396291995171919.post-55124986585683123562010-02-21T15:28:00.000+02:002010-04-14T15:28:27.266+03:00IC cards are vulnerable to MITM attacksResearchers from Cambridge <a href="http://www.cl.cam.ac.uk/research/security/banking/nopin/">found</a> a vulnerability in IC cards using <a href="http://en.wikipedia.org/wiki/EMV">EMV</a>, which is used worldwide (with over 730 million cards in circulation) in chip and pin credit/debit cards. Note that the authors claimed that “the protocol is broken”. The details will be published at <a href="http://www.ieee-security.org/TC/SP-Index.html">IEEE Security and Privacy Symposium</a> in May this year, and <a href="http://www.cl.cam.ac.uk/research/security/banking/nopin/oakland10chipbroken.pdf">a working draft</a> is available now.<br />
<br />
With this vulnerability, criminals are able to launch Man-In-The-Middle (MITM) attacks easily and use stolen cards without knowing the correct PIN. The attack works for both online and offline transactions on terminals. Fortunately, it can’t work for ATM transactions.<br />
<br />
Let’s see how it works. The EMV protocol can be split into three steps:<br />
1 <b>Card authentication</b> – assure which bank issued the card and the data hasn’t been tampered.<br />
1.1 The terminal requests the list of available applications (e.g. card use at shops, ATM functionality, etc.), and selects one of them.<br />
1.2 The terminal reads the information of the card-holder, including card details (e.g. primary account number, start and expiry date), backwards compatibility data, and control parameters for the protocol. Some information is signed by RSA, and the certificate chain is also included in the information.<br />
<br />
2 <b>Card-holder verification</b> – assure the PIN entered matches the one stored on the card.<br />
2.1 The terminal sends the inputed PIN to the card for verification.<br />
2.2 If the inputed PIN matches the one stored on the card, 0×9000 is returned to the terminal. Otherwise, 0×63Cx is returned, where ‘x’ is the number of further PIN verification attempts the card allows. <span style="color: red;"><b>Note that the response is NOT directly authenticated.</b></span><br />
<br />
3 <b>Transaction authorization</b> – assure the bank authorizes the transaction.<br />
3.1 The terminal asks the card to generate a cryptographic MAC over the transaction details, including e.g. the transaction amount, currency, type, a random nonce generated by the terminal, and the terminal verification result. <span style="color: red;"><b>Note that the terminal verification result merely enumerates possible failure conditions, and doesn’t indicate which particular method is used in case of success.</b></span><br />
3.2 The card sends back also a sequence counter identifying the transaction, a variable length field containing data generated by the card, and the MAC. The MAC is usually generated using 3DES with a symmetric key shared between the card and the issuer.<br />
3.3 The terminal sends the response to the bank for transaction authorization.<br />
3.4 If the check passes, the bank sends back a two byte long response code, and a MAC over the message sent from the card and the response code.<br />
3.5 The response is forwarded by the terminal to the card. If the card verifies the response from the bank, it updates some internal states to note that the bank authorizes the transaction.<br />
3.6 The terminal asks the card to generate a transaction certification, signifying that it’s authorizing the transaction to proceed. It will be sent to the bank and stored locally for further use.<br />
<br />
Due to the above two flaws, the bad boy is able to <span style="color: blue;"><b>launch the MITM attack like this</b></span>:<br />
1) It hijacks the communication in step 2, sending 0×9000 to the terminal to fool it into believing the PIN verification succeeds.<br />
2) As the PIN is never sent to the card, it will be fooled into believing the terminal doesn’t support PIN verification, and the PIN retry counter is not modified.<br />
3) As the terminal verification result doesn’t tell the particular method used, the terminal believes the PIN verification succeeds and the card believes the PIN verification is not attempted.<br />
4) The variable length field containing data generated by the card generated in step 3.2 is issuer-specific, and not specified in EMV. Therefore, the terminal can’t decode it, and the issuing bank doesn’t know which card-holder verification scheme is used.<br />
<br />
Also, the researchers found that EMV failed to provide adequate evidence to produce in dispute resolution and litigation, among other issues. And we should be aware that this vulnerability is not implementation-specific, but <b>the fundamental protocol is broken</b>!Xizhi Zhuhttp://www.blogger.com/profile/11132645470363367082noreply@blogger.com0tag:blogger.com,1999:blog-1750396291995171919.post-39344843728873465222009-11-16T15:29:00.003+02:002013-08-24T00:39:40.679+03:00SSL renegotiation vulnerability exploitedThis post has been moved to <a href="http://www.zionsoft.net/2009/11/ssl-renegotiation-vulnerability-exploited/">http://www.zionsoft.net/2009/11/ssl-renegotiation-vulnerability-exploited/</a><br />
<br />
The <a href="http://www.zionsoft.net/2009/11/details-of-ssl-renegotiation-attack/">SSL renegotiation vulnerability</a> revealed earlier this month has been <a href="http://www.securegoose.org/2009/11/tls-renegotiation-vulnerability-cve.html">demonstrated</a> by a Turkish grad student, named Anil Kurmus, to steal user names and passwords of Twitter. The code is also <a href="http://perso.telecom-paristech.fr/%7Ekurmus/ssl.c">available</a> in the wild.<br />
<br />
Yes, it’s totally true that even the attacker can inject a small amount of message at the beginning, he’s still unable to read the encrypted data. But let’s see how Kurmus’ attack works. (Of course, this hole has been patched by Twitter)<br />
<br />
You can update your Twitter status with its API by posting your new status to http://twitter.com/statuses/update.xml, as well as your user name and password. The message is something like below:<br />
<i>POST /statuses/update.xml HTTP/1.1<br />
Authorization: Basic username:password<br />
User-Agent: curl/7.19.5<br />
Host: twitter.com<br />
Accept:*/*<br />
Content-Length: 22<br />
Content-Type: application/x-www-form-urlencoded</i><br />
<i>status=your new status</i><br />
<br />
All that the attacker need to do is to inject a POST request header, and post the victim’s POST request to his own twitter account:<br />
<i><span style="color: red;">POST /statuses/update.xml HTTP/1.1<br />
Authorization: Basic username:password<br />
User-Agent: curl/7.19.5<br />
Host: twitter.com<br />
Accept:*/*<br />
Content-Length: 140<br />
Content-Type: application/x-www-form-urlencoded<br />
status=</span><span style="color: blue;">POST /statuses/update.xml HTTP/1.1<br />
Authorization: Basic username:password<br />
…</span></i><br />
<br />
The red part is injected by the attacker, and the blue part is submitted by the victim. Then the server would be fooled to post the victim’s credential, and now, the attacker gets the user name and password of the victim.<br />
<br />
Quite simple, but really destructive!Xizhi Zhuhttp://www.blogger.com/profile/11132645470363367082noreply@blogger.com0tag:blogger.com,1999:blog-1750396291995171919.post-25607167479171126812009-11-07T15:30:00.004+02:002013-08-24T00:34:52.411+03:00The details of the SSL renegotiation attackThis post has been moved to <a href="http://www.zionsoft.net/2009/11/details-of-ssl-renegotiation-attack/">http://www.zionsoft.net/2009/11/details-of-ssl-renegotiation-attack/</a><br />
<br />
This MITM attack is against all versions of the SSL/TLS protocols, allowing an attacker to inject any amount of data into the beginning of the application protocol stream.<br />
<br />
I assume you understand how SSL/TLS works, especially the renegotiation part, which is the weak point leading to the following three attacks. Also, a basic understanding of the HTTP protocol is recommended.<br />
<span style="color: blue;"><strong><strong><br />
</strong></strong></span><br />
<span style="color: blue;"><strong><strong>1st scenario: when the client certificate is required</strong></strong></span><br />
In the ideal case, the client certificate is requested when the server sends its certificate. However, in the real world, it’s requested only when the client requests something that needs the client certificate. Instead of a brand new handshake procedure, this would trigger the server to start a renegotiation.<br />
Unfortunately, as HTTP has no way to instruct the client to resubmit the request after the renegotiation, the server has to reply with the requested content after the renegotiation, resulting a gap of authentication.<br />
<br />
The sequence of this attack is summarized below:<br />
1) client –> attacker : handshake1<br />
2) attacker –> server: handshake2<br />
3) attacker –> server: request something<br />
4) attacker <– server: renegotiation, requesting client certificate<br />
5) client <–> attacker <–> server: attacker forwards handshake1, and handshake3 is built which is only readable by the server and the client<br />
6) client <– attack <– server: the server responds with the content requested at step 3<br />
<br />
Now, the client gets what he hasn’t required…<br />
<span style="color: blue;"><strong><strong><br />
</strong></strong></span><br />
<span style="color: blue;"><strong><strong>2nd scenario: different cipher suites used</strong></strong></span><br />
Some websites are configured that different resources are protected by different cipher suites. If the client requests a resource protected by another cipher suite, a renegotiation is needed. However, the request from the client is buffered by the server for future use, resulting to this attack. Just have a look at the following example.<br />
<br />
The attacker sends a request:<br />
<em>GET /index.html HTTP/1.1<br />
Host: server_address<br />
Connection: keep-alive</em><br />
<em>GET /evil.html HTTP/1.1<br />
x-ignore:</em><br />
<br />
The second request is completed by the client:<br />
<em>GET /good.html HTTP/1.1<br />
Host: server_address<br />
Cookie: client_cookie</em><br />
<br />
Unfortunately, the second request is consider by the server as below:<br />
<em>GET /evil.html HTTP/1.1<br />
x-ignore: GET /good.html HTTP/1.1<br />
Host: server_address<br />
Cookie: client_cookie</em><br />
<br />
The client get <em>/evil.html</em> instead of <em>/good.html</em>……<br />
<span style="color: blue;"><strong><strong><br />
</strong></strong></span><br />
<span style="color: blue;"><strong><strong>3rd scenario: client initiated renegotiation</strong></strong></span><br />
This attack is based on the fact that the client can also launch a renegotiation, and the server would buffer the previous request and use them after the renegotiation. It’s reasonable to believe that this is the most dangerous scenario as it requires nothing special from the server. Here is the details:<br />
1) The attacker builds an SSL connection with the server, and sends the request:<br />
<em>GET /evil.html HTTP/1.1<br />
R<br />
x-ignore:</em><br />
<br />
Here, the <em>R</em> would trigger a renegotiation, while the <em>x-ignore:</em> is an unfinished header line without line termination, which would be buffered and used by the server later.<br />
<br />
2) The attacker forwards the messages, and builds a connection between the client and the server.<br />
<br />
3) The client sends a request to the server:<br />
<em>GET /index.html HTTP/1.1</em><br />
<em>Host: server_address<br />
Connection: keep-alive</em><br />
<br />
However, due to the injected request from the attacker, the server considers the whole request as:<br />
<em>GET /evil.html HTTP/1.1<br />
R<br />
x-ignore: GET /index.html HTTP/1.1<br />
Host: server_address<br />
Connection: keep-alive</em><br />
<br />
It will return the <em>/evil.html</em> rather than <em>/indes.html</em> as expected.<br />
<br />
Now, I’d like to <strong>notify</strong> you again that all these attacks are against the SSL/TLS protocols, rather than the implementations, which means that either the client or the server could smell anything about the attacker. To <strong>summarize</strong>, the attacker tries to renegotiate the SSL connection before the client really communicates with the server, and the request made by the attacker before the negotiation will be replied to the client, which may lead to serious attacks. Quite easy to understand and implement, right?<br />
<br />
A draft has already been <a href="https://svn.resiprocate.org/rep/ietf-drafts/ekr/draft-rescorla-tls-renegotiate.txt">proposed</a> to fix this problem by cryptographically binding renegotiation handshakes to the enclosing TLS channel, which is not supported by current clients and servers. The fix is to include the digest data from the <strong>FINISHED</strong> message of the previous handshake in <strong>CLIENT-HELLO</strong> or <strong>SERVER-HELLO</strong> of the renegotiation.<br />
<br />
Finally, I’d like to remind you about the vulnerabilities of DNS and BGP discovered last year, as I consider the attack against SSL is equally disastrous as those two.<br />
<br />
UPDATED: The final fix for this issue is available as <a href="http://tools.ietf.org/html/rfc5746">RFC 5746</a>.Xizhi Zhuhttp://www.blogger.com/profile/11132645470363367082noreply@blogger.com0tag:blogger.com,1999:blog-1750396291995171919.post-77062562644212623772009-10-29T15:33:00.000+02:002010-04-14T15:34:56.162+03:00WPA is next to death!Last November, German researches found the <a href="http://dl.aircrack-ng.org/breakingwepandwpa.pdf">first vulnerability</a> in WPA/TKIP, which allows the attacker to break some short packets with most fields known, e.g. ARP request/response, within 12-15 minutes, and inject up to 7 packets.<br />
<br />
Two months earlier, Japanese researchers <a href="http://jwis2009.nsysu.edu.tw/location/paper/A%20Practical%20Message%20Falsification%20Attack%20on%20WPA.pdf">improved</a> the attack:<br />
<blockquote>In 2008, Beck and Tews have proposed a practical attack on WPA. Their attack (called the Beck-Tews attack) can recover plaintext from an encrypted short packet, and can falsify it. The execution time of the Beck-Tews attack is about 12-15 minutes. However, the attack has the limitation, namely, the targets are only WPA implementations those support IEEE802.11e QoS features. In this paper, we propose a practical message falsification attack on any WPA implementation. In order to ease targets of limitation of wireless LAN products, we apply the Beck-Tews attack to the man-in-the-middle attack. In the man-in-the-middle attack, the user’s communication is intercepted by an attacker until the attack ends. It means that the users may detect our attack when the execution time of the attack is large. Therefore, we give methods for reducing the execution time of the attack. As a result, the execution time of our attack becomes about one minute in the best case.</blockquote><br />
Now, Halvorsen with others made another <a href="http://j.mp/2pHX7G">progress</a>, enabling hackers to inject a huge number of malicious bytes within approximately 18 minutes and 25 seconds:<br />
<blockquote>Beck and Tews described the first practical cryptographic attack on IEEE 802.11i TKIP in November 2008, and this paper continues this line of protocol cryptanalysis. We show that their attack on TKIP can be used to create an ARP poisoning attack and a cryptographic DoS attack. Moreover, we are able to decrypt DHCP ACK packets, which are over 12 times longer than the ARP packet used by Beck and Tews. Our method of analysis recovers 596 bytes of keystream that can be used in new attacks on other control protocol messages.</blockquote><br />
We should remember that the attacks would always improve. Therefore, switch your network to WPA2/CCMP right now!Xizhi Zhuhttp://www.blogger.com/profile/11132645470363367082noreply@blogger.com0tag:blogger.com,1999:blog-1750396291995171919.post-13202726336882272032009-08-26T15:36:00.009+03:002010-04-14T15:45:02.077+03:00Chinese version of GTalk is NOT encrypted!My friend just told me that the Chinese version of Google Talk is <strong>NOT</strong> encrypted, while the English version is encrypted. As shown below, when using the Chinese version, the message (in the red circle) is not encrypted at all! One thing you should know is that the Chinese version is higher than the English version, which suggests <span style="color: red;"><strong>Google might remove the encryption on purpose</strong></span>. It reminds me of <a href="http://xizhizhu.blogspot.com/2008/10/youre-watched-on-tom-skype_03.html">the shit of TOM-Skype</a>, which watches the text conversation of users.<br />
<br />
Here goes the screen shot of <a href="http://dl.google.com/googletalk/googletalk-setup-zh-CN.exe">the Chinese version</a> (1.0.0.105), and you can see the text transmitted unencrypted at all:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/_j2Abq_R5P6w/S8W4LKMqM7I/AAAAAAAADXc/mI6_fi-NEwg/s1600/1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/_j2Abq_R5P6w/S8W4LKMqM7I/AAAAAAAADXc/mI6_fi-NEwg/s320/1.png" /></a></div><br />
<br />
Here goes the screen shot of <a href="http://dl.google.com/googletalk/googletalk-setup.exe">the English version</a> (1.0.0.104), which is obviously encrypted using TLS 1.0 as the first 3 bytes are 0×17 0×03 0×01:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/_j2Abq_R5P6w/S8W4PV-V_bI/AAAAAAAADXk/_dSEpTpiOns/s1600/2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/_j2Abq_R5P6w/S8W4PV-V_bI/AAAAAAAADXk/_dSEpTpiOns/s320/2.png" /></a></div>Xizhi Zhuhttp://www.blogger.com/profile/11132645470363367082noreply@blogger.com0tag:blogger.com,1999:blog-1750396291995171919.post-59183350818001699732009-07-14T15:48:00.001+03:002011-04-11T19:21:07.681+03:00Tricks & skills in UbuntuTo <b>delete unused kernels</b>, use the following command:<br />
<i>sudo aptitude purge ~ilinux-image-.*\(\!`uname -r`\)</i><br />
<br />
To <b>delete the RC packages</b>, use the following command:<br />
<i>dpkg -l | grep ^rc | cut -d' ' -f3| sudo xargs dpkg -P</i><br />
<br />
Use this command to <b>remove the unused configuration files</b>:<br />
<i>dpkg -l |grep ^rc|awk '{print $2}' |sudo xargs dpkg -P</i><br />
<br />
<b>Make sudo regards http_proxy</b> etc., add in file /etc/sudoers:<br />
Defaults env_keep += "http_proxy"Xizhi Zhuhttp://www.blogger.com/profile/11132645470363367082noreply@blogger.com1tag:blogger.com,1999:blog-1750396291995171919.post-71200691911881081012009-01-04T03:50:00.000+02:002010-04-19T04:03:32.134+03:00TCP communication over Qt<b>1.QTcpSocket</b><br />
<br />
<a href="http://qt.nokia.com/doc/4.6/qtcpsocket.html">QTcpSocket</a> is used as the TCP socket in Qt. It's used both in client and server side.<br />
<br />
To perform as a client, following steps are used:<br />
a) call <i>QTcpSocket.connectToHost()</i> to connect to a server;<br />
b) when connected, <i>QTcpSocket.connected()</i> will be emitted;<br />
c) communicate with the server.<br />
<br />
The following code shows a simple client sending "Hello, world" to the server.<br />
<code class="prettyprint lang-cpp"><br />
// client.h<br />
#include <QtNetwork><br />
#include <QtCore><br />
<br />
class Client: public QObject<br />
{<br />
Q_OBJECT<br />
public:<br />
Client(QObject* parent = 0);<br />
~Client();<br />
void start(QString address, quint16 port);<br />
public slots:<br />
void startTransfer();<br />
private:<br />
QTcpSocket client;<br />
};<br />
<br />
// client.cc<br />
#include "client.h"<br />
#include <QHostAddress><br />
<br />
Client::Client(QObject* parent): QObject(parent)<br />
{<br />
connect(&client, SIGNAL(connected()), this, SLOT(startTransfer()));<br />
}<br />
<br />
Client::~Client()<br />
{<br />
client.close();<br />
}<br />
<br />
void Client::start(QString address, quint16 port)<br />
{<br />
QHostAddress addr(address);<br />
client.connectToHost(addr, port);<br />
}<br />
<br />
void Client::startTransfer()<br />
{<br />
client.write("Hello, world", 13);<br />
}<br />
<br />
// main.cc<br />
#include "client.h"<br />
#include <QApplication><br />
<br />
int main(int argc, char** argv)<br />
{<br />
QApplication app(argc, argv);<br />
<br />
Client client;<br />
client.start("127.0.0.1", 888);<br />
<br />
return app.exec();<br />
}<br />
</code><br />
<br />
<b>2.QTcpServer</b><br />
<br />
In Qt, the class <a href="http://qt.nokia.com/doc/4.6/qtcpserver.html">QTcpServer</a> is used as a TCP server. Generally, the following steps are used:<br />
a) call <i>QTcpServer.listen()</i> to start listening;<br />
b) <i>QTcpServer.newConnection()</i> signal will be emitted when a new connection comes;<br />
c) call <i>QTcpServer.nextPendingConnection()</i> to get the socket object (QTcpSocket) connecting to the client.<br />
<br />
The following code shows a simple server receiving and printing a string from its client.<br />
<code class="prettyprint lang-cpp"><br />
#include <QtNetwork><br />
#include <QtCore><br />
<br />
class Server: public QObject<br />
{<br />
Q_OBJECT<br />
public:<br />
Server(QObject * parent = 0);<br />
~Server();<br />
public slots:<br />
void acceptConnection();<br />
void startRead();<br />
private:<br />
QTcpServer server;<br />
QTcpSocket* client;<br />
};<br />
<br />
// server.cc<br />
#include "server.h"<br />
#include <iostream><br />
using namespace std;<br />
<br />
Server::Server(QObject* parent): QObject(parent)<br />
{<br />
connect(&server, SIGNAL(newConnection()), this, SLOT(acceptConnection()));<br />
<br />
server.listen(QHostAddress::Any, 888;<br />
}<br />
<br />
Server::~Server()<br />
{<br />
server.close();<br />
}<br />
<br />
void Server::acceptConnection()<br />
{<br />
client = server.nextPendingConnection();<br />
<br />
connect(client, SIGNAL(readyRead()), this, SLOT(startRead()));<br />
}<br />
<br />
void Server::startRead()<br />
{<br />
char buffer[1024] = {0};<br />
client->read(buffer, client->bytesAvailable());<br />
cout << buffer << endl;<br />
client->close();<br />
}<br />
<br />
// main.cc<br />
#include "server.h"<br />
#include <QApplication><br />
<br />
int main(int argc, char** argv)<br />
{<br />
QApplication app(argc, argv);<br />
Server server;<br />
return app.exec();<br />
}<br />
</code><br />
<br />
P.S.You should add <b>QT += network</b> in the project file created by <i>qmake -project</i>.<br />
<br />
===========================<br />
<br />
Added on 12.1.2009<br />
<br />
<a href="http://qt.nokia.com/doc/4.6/qudpsocket.html">QUdpSocket</a> is the encapsulation class for UDP communication in Qt. Following steps are generally used:<br />
a) call <i>QUdpSocket.bind()</i> to listen on a specified address and port, which performs like QTcpServer.listen();<br />
b) call <i>QUdpSocket.writeDatagram()</i> to send UDP messages;<br />
c) when datagrams arrive, <i>QUdpSocket.readyRead()</i> will be emitted, and one can call <i>QUdpSocket.readDatagram()</i> to receive UDP messages.<br />
<br />
Due to the lazy nature of human being, no example on UDP will be available.Xizhi Zhuhttp://www.blogger.com/profile/11132645470363367082noreply@blogger.com3tag:blogger.com,1999:blog-1750396291995171919.post-92195377921416808752008-10-03T15:44:00.002+03:002010-04-14T15:44:37.650+03:00You’re watched on TOM-SkypeSecurity experts from University of Toronto Citizen Lab <a href="http://citizenlab.org/2008/10/breaching-trust/">report</a> that TOM-Skype, Skype’s China venture with TOM, text messages sent between TOM-Skype users and between Skype users and TOM-Skype users, are scanned for phrases like “Taiwan independence” or “Falun Gong” or for opposition to the Communist Party of China. When these keywords are found, the messages and information, such as usernames of subscribers, are stored on publicly accessible Web servers along with an encryption key that could be used to unlock the data.<br />
<br />
Jennifer Caukin, a spokewoman of Skype <a href="http://www.reuters.com/article/idUSN0226624920081002">admitted</a> the breach.Xizhi Zhuhttp://www.blogger.com/profile/11132645470363367082noreply@blogger.com0