Search Results: "xam"

11 August 2014

Juliana Louback: JSCommunicator - Setup and Architecture

Preface During Google Summer of Code 2014, I got to work on the Debian WebRTC portal under the mentorship of Daniel Pocock. Now I had every intention of meticulously documenting my progress at each step of development in this blog, but I was a bit late in getting the blog up and running. I ll now be publishing a series of posts to recap all I ve done during GSoC. Better late than never. Intro JSCommunicator is a SIP communication tool developed in HTML and JavaScript. The code was designed to make integrating JSCommunicator with a website or web app as simple as possible. It s quite easy, really. However, I do think a more detailed explanation on how to set things up and a guide to the JSCommunicator architecture could be of use, particularly for those wanting to modify the code in any way. Setup To begin, please fork the JSCommunicator repo. If you are new to git, feel free to follow the steps in section Setup and Clone in this post. If you read the README file (which you always should), you ll see that JSCommunicator needs a SIP proxy that supports SIP over Websockets transport. Some options are: I didn t find a tutorial for Kamailio setup, I did find one for repro setup. And bonus, here you have a great tutorial on how to setup and configure your SIP proxy AND your TURN server. In your project s root directory, you ll see a file named config-sample.js. Make a copy of that file named config.js. The config-sample.js file has comments that are very instructive. In sum, the only thing you have to modify is the turn_servers property and the websocket property. In my case, debrtc.org was the domain registered for testing my project, so my config file has:
turn_servers: [
	  server:"turn:debrtc.org"       
],
Note that unlike the sample, I didn t set a username and password so SIP credentials will be used. Now fill in the websocket property here we use sip5060.net.
websocket:  
    servers: 'wss://ws.sip5060.net',
    connection_recovery_min_interval: 2,
    connection_recovery_max_interval: 30,
   ,
I m pretty sure you can set the connection_recovery properties to whatever you like. Everything else is optional. If you set the user property, specifically display_name and uri, that will be used to fill in the Login form and takes preference over any Remember me data. If you also set sip_auth_password, JSCommunicator will automatically log in. All the other properties are for other optional functionalities and are well explained. You ll need some third-party javascript that is not included in the JSCommunicator git repo. Namely jQuery version 1.4 or higher and ArbiterJS version 1.0. Download jQuery here and ArbiterJS here and place the .js files in your project s root directory. Do make sure that you are including the correct filename in your html file. For example, in phone-dev.shtml, a file named jquery.js is included. The file you downloaded will likely have version numbers in it s file name. So rename the downloaded file or change the content of src in your includes. This is uber trivial, but I ve made the mistake several times. You ll also need JsSIP.js which can be downloaded here. Same naming care must be taken as is the case for jQuery and ArbiterJS. The recently added Instant Messaging component and some of the new features need jQuery-UI - so far version 1.11.* is known to work. From the downloaded .zip all you need is the jquery-ui-...js file and the jquery-ui-...css file, also to be placed in the project s root directory. If you ll be using the internationalization support you ll also need jquery.i18n.properties.js. To try out JSCommunicator, deploy the website locally by copying your project directory to the apache document root directory (provided you are using apache, which is a good idea.). You ll likely have to restart your server before this works. Now the demo .shtml pages only have a header with all the necessary includes, then a Server Side Include for the body of the page, with all the JSCommunicator html. The html content is in the file jscommunicator.inc. You can enable SSI on apache, OR you can simply copy and paste the content of jscommunicator.inc into phone-dev.shmtl. Start up apache, open a browser and navigate to localhost/jscommunicator/phone-dev.shmtl and you should see: jscommunicatorRaw Actually, pending updates to JSCommunicator, you should see a brand new UI! But all the core stuff will be the same. Architecture Disclaimer: I m explaining my view of the JSCommunicator architecture, which currently may not be 100% correct. But so far it s been enough for me to make my modifications and additions to the code, so it could be of use. One I get a JSCommunicator Founding Father s stamp of approval, I ll be sure to confirm the accuracy. Now to explain how the JSCommunicator code interacts, the use of each code item is described, ignoring all the html and css which will vary according to how you choose to use JSCommunicator. I m also not going to explain jQuery which is a dependency but not specific to WebRTC. The core JSCommunicator code is the following: Each of these files will be presented in what I hope is an intuitive order. The next three files could be considered utils : These two are where the magic happens: Now for some extras: Third party code: Here s a diagram of sorts to help you visualize how the code interacts: jscommArch In sum, 1 - JSCommUI.js handles what is displayed in the UI and feeds data to JSCommManager.js; 2 - JSCommManager.js actually does stuff, feeding data to be displayed to JSCommUI.js; 3 - JSCommManager.js calls functions from the three utils , parseuri.js, webrtc-check.js and jssip-helpher.js which organizes the data from config.js; 4 - JSCommManager.js initializes a SIP User Agent based on the implementation in Arbiter.js. When making any changes to JSCommunicator, you will likely only be working with JSCommUI.js and JSCommManager.js.

Juliana Louback: JSCommunicator - Setup and Architecture

Preface During Google Summer of Code 2014, I got to work on the Debian WebRTC portal under the mentorship of Daniel Pocock. Now I had every intention of meticulously documenting my progress at each step of development in this blog, but I was a bit late in getting the blog up and running. I ll now be publishing a series of posts to recap all I ve done during GSoC. Better late than never. Intro JSCommunicator is a SIP communication tool developed in HTML and JavaScript. The code was designed to make integrating JSCommunicator with a website or web app as simple as possible. It s quite easy, really. However, I do think a more detailed explanation on how to set things up and a guide to the JSCommunicator architecture could be of use, particularly for those wanting to modify the code in any way. Setup To begin, please fork the JSCommunicator repo. If you are new to git, feel free to follow the steps in section Setup and Clone in this post. If you read the README file (which you always should), you ll see that JSCommunicator needs a SIP proxy that supports SIP over Websockets transport. Some options are: I didn t find a tutorial for Kamailio setup, I did find one for repro setup. And bonus, here you have a great tutorial on how to setup and configure your SIP proxy AND your TURN server. In your project s root directory, you ll see a file named config-sample.js. Make a copy of that file named config.js. The config-sample.js file has comments that are very instructive. In sum, the only thing you have to modify is the turn_servers property and the websocket property. In my case, debrtc.org was the domain registered for testing my project, so my config file has:
turn_servers: [
	  server:"turn:debrtc.org"       
],
Note that unlike the sample, I didn t set a username and password so SIP credentials will be used. Now fill in the websocket property here we use sip5060.net.
websocket:  
    servers: 'wss://ws.sip5060.net',
    connection_recovery_min_interval: 2,
    connection_recovery_max_interval: 30,
   ,
I m pretty sure you can set the connection_recovery properties to whatever you like. Everything else is optional. If you set the user property, specifically display_name and uri, that will be used to fill in the Login form and takes preference over any Remember me data. If you also set sip_auth_password, JSCommunicator will automatically log in. All the other properties are for other optional functionalities and are well explained. You ll need some third-party javascript that is not included in the JSCommunicator git repo. Namely jQuery version 1.4 or higher and ArbiterJS version 1.0. Download jQuery here and ArbiterJS here and place the .js files in your project s root directory. Do make sure that you are including the correct filename in your html file. For example, in phone-dev.shtml, a file named jquery.js is included. The file you downloaded will likely have version numbers in it s file name. So rename the downloaded file or change the content of src in your includes. This is uber trivial, but I ve made the mistake several times. You ll also need JsSIP.js which can be downloaded here. Same naming care must be taken as is the case for jQuery and ArbiterJS. The recently added Instant Messaging component and some of the new features need jQuery-UI - so far version 1.11.* is known to work. From the downloaded .zip all you need is the jquery-ui-...js file and the jquery-ui-...css file, also to be placed in the project s root directory. If you ll be using the internationalization support you ll also need jquery.i18n.properties.js. To try out JSCommunicator, deploy the website locally by copying your project directory to the apache document root directory (provided you are using apache, which is a good idea.). You ll likely have to restart your server before this works. Now the demo .shtml pages only have a header with all the necessary includes, then a Server Side Include for the body of the page, with all the JSCommunicator html. The html content is in the file jscommunicator.inc. You can enable SSI on apache, OR you can simply copy and paste the content of jscommunicator.inc into phone-dev.shmtl. Start up apache, open a browser and navigate to localhost/jscommunicator/phone-dev.shmtl and you should see: jscommunicatorRaw Actually, pending updates to JSCommunicator, you should see a brand new UI! But all the core stuff will be the same. Architecture Disclaimer: I m explaining my view of the JSCommunicator architecture, which currently may not be 100% correct. But so far it s been enough for me to make my modifications and additions to the code, so it could be of use. One I get a JSCommunicator Founding Father s stamp of approval, I ll be sure to confirm the accuracy. Now to explain how the JSCommunicator code interacts, the use of each code item is described, ignoring all the html and css which will vary according to how you choose to use JSCommunicator. I m also not going to explain jQuery which is a dependency but not specific to WebRTC. The core JSCommunicator code is the following: Each of these files will be presented in what I hope is an intuitive order. The next three files could be considered utils : These two are where the magic happens: Now for some extras: Third party code: Here s a diagram of sorts to help you visualize how the code interacts: jscommArch In sum, 1 - JSCommUI.js handles what is displayed in the UI and feeds data to JSCommManager.js; 2 - JSCommManager.js actually does stuff, feeding data to be displayed to JSCommUI.js; 3 - JSCommManager.js calls functions from the three utils , parseuri.js, webrtc-check.js and jssip-helpher.js which organizes the data from config.js; 4 - JSCommManager.js initializes a SIP User Agent based on the implementation in Arbiter.js. When making any changes to JSCommunicator, you will likely only be working with JSCommUI.js and JSCommManager.js.

10 August 2014

Ian Donnelly: How-To: kdb merge

Hi Everybody, As you may know, part of my Google Summer of Code project involved the creation of merge tools for Elektra. The one I am going to focus on today is kdb merge. The kdb tool allows users to access and perform functions on the Elektra Key Database from the command line. We added a new command to this very useful tool, the merge command. This command allows a user to perform a three-way merge of KeySets from the kdb tool.
The command to use this tool is:
kdb merge [options] ourpath theirpath basepath resultpath

The standard naming scheme for a three-way merge consists of ours, theirs, and base: This works very similarly for KeySets, especially ones that consist of mounted conffiles. For mounted conffiles: If the user is just trying to accomplish is a three-way merge using any two arbitrary keysets that share a base,
it doesn t matter which ones are defined as ours or theirs as long as they use the correct base KeySet.
In kdb merge, ourpath, theirpath, and basepath work just like ours, theirs, and base except each one represents the
root of a KeySet. Resultpath is pretty self-explanatory, it is just where you want the result of the merge to be saved under.
It s worth noting, resultpath should be empty before attempting a merge, otherwise there can be unintended consquences. As for the options, there are a few basic options:

-i --interactive which attempts the merge in an interactive way
-t --test which tests the proposed merge and informs you about possible conflicts
-f --force which overwrites any Keys in resultpath
Additionally there is an option to specify a merge strategy, which is very important. The other option, strategy is:
s --strategy which is used to specify a strategy to use in case of a conflict

The current list of strategies are:
preserve the merge will fail if a conflict is detected
ours the merge will use our version during a conflict
theirs the merge will use their version during a conflict
base the merge will use the base version during a conflict
If no strategy is specified, the merge will default to the preserve strategy as to not risk making the wrong decision. If any of the other strategies are specified, when a conflict is detected, merge will use the Key specified by the strategy (ours, theirs, or base) for the resulting Key. An example of using the kdb merge command:
kdb merge -s ours system/hosts/ours system/hosts/theirs system/hosts/base system/hosts/result
For more in depth examples, please see the full tutorial on our GitHub Documentation. -Ian S. Donnelly

8 August 2014

Ian Donnelly: The Line Plug-In

Hi Everybody, As you may have noticed I wrote a new plug-in for Elektra called line . I used it for a lot of examples in my tutorial, How-To: Write a Plug-In. The line plug-in is a very simple storage plug-in for Elektra. This plug-in stores files into the Elektra Key Database creating a new Key for each line and setting the string value of the Key to the string value of the line of that file. So if we have a file called hello.txt :

Hello
World!

And we mount it to kdb like so: kdb mount ~/line.txt system/hello_line line. The output of kdb ls system/hello_line the output would be:

system/hello_line/#1
system/hello_line/#
2

With the getString values of #1 and #2 being Hello and World! respectively. If this seems like a very simple plug-in, that s because it is. Obviously, this plug-in isn t a great showcase for the robustness of Elektra, any data structure could store a file line by line relatively easy, so why did we add a line plug-in at all? The answer is that we included a line plug-in to allow any line-based file to use functions of Elektra, particularly the new Merge function. My Google Summer of Code project is to allow for automatic three-way merge of Debian conffiles during package upgrades as opposed to the current prompt and manual merging a user must do if a conffile is edited. Using Elektra and the new mergecode we can mount a conffile with the best plug-in for it, (the ini plug-in for Samba s smb.conf for instance) and that allows for a very powerful merging ability with a lot more success than a simple diff merge. However, there are a lot of conffiles that don t use any particular standard (such as ini, xml, or JSON) to store data. That is where the line plug-in comes in. We can still mount these files using the line plug-in and attempt a merge. Of course it is much more likely to have conflicts, and this type of merge is still susceptible to many of the same flaws as regular file merges (such as not being able to detect when a line has been moved), but it simple cases, the merge may succeed which would reduce the overall number of times a user would be prompted during an upgrade. Basically, I wrote a line plug-in for Elektra as a fallback for conffile merges when we can t mount the conffile in any more meaningful way. While merges using KeySets that were mounted using line are more likely to fail than other, more specialized plug-ins, there are cases that these merges will succeed and the user will not have to deal with a confusing prompt. The whole point of my Google Summer of Code project is to make upgrading packages and dealing with conffiles much smoother and easier than it is now by including a three-way mere and this line plug-in will help with this goal. Sincerely,
Ian S. Donnelly

Sune Vuorela: Fun and joy with .bat files

Occasionally, one gets in touch with kind of foreign technologies and needs to get stuff working anyways. Recently, I had to do some various hacking with and around .bat files. Bat files are a kind of script files for Microsoft Windows. Calling external commands Imagine need to call some other command, let s say git diff. So from a cmd thing, you would write
git diff
similar to writing shell scripts on unixes. But there is a catch. If the thing you want to call is another bat-script, just calling it ensures it replaces the current script and never returns. So you need
call git diff
if the command you want to run is a bat file and you want to return to your script. Calling an external helper next to your script
If you for some reason needs to call some external helper placed next to your script, there is a helpful thing to do that as well. Imagine your helper is called helper.bat
call %~dp0helper.bat
is the very self-explanatory way of doing that. Stopping execution of your script If you somehow encounter some condition in your script that requires you to stop your script, there is a command exit handy. It even takes a argument for what error code there is.
exit 2
stops your script with return code 2. But it also have the nice added feature that if you do it in a script you run by hand in a terminal, it also exits the terminal. Luckily there is also a fix for that:
exit /b 2
and it doesn t exit your interactive terminal, and it sets the %ERRORLEVEL% variable to the exit code. Fortunately, the fun doesn t stop here. If the script is run non-interactively, exit /b doesn t set the exit code for for example perl s system() call. You need to use exit without /b for that. So now you need two scripts. one for interactive use that calls exit /b and a similar one using exit for use by other apps/scripts. Or, we can combine some of our knowledge and add a extra layer of indirection. and then success. Oh. and on a unrelated note. Windows can t schedule tasks for users that aren t logged in and don t have a password set. The response Access Denied is the only clue given.

Ian Donnelly: How-To: Write a Plug-In (Part 3, Coding)

Hi Everybody! Hope you have been enjoying my tutorial on writing plug-ins so far. In Part 1 we covered the basic overview of a plug-in. Part 2 covered a plug-in s contract and the best way to write one. Now, for Part 3 we are going to cover the meat of a plug-in, the actual coding. As you should know from reading Part 1, there are five main functions used for plug-ins, elektraPluginOpen, elektraPluginGet, elektraPluginSet, ELEKTRA_PLUGIN_EXPORT(Plugin), where Plugin should be replaced with the name of your plug-in. We are going to start this tutorial by focusing on the elektraPluginGet because it usually is the most critical function. As we discussed before, elektraPluginGet is the function responsible for turning information from a file into a usable KeySet. This function usually differs pretty greatly between each plug-in. This function should be of type int, it returns 0 on success or another number on an error. The function will take in a Key, usually called parentKey which contains a string containing the path to the file that is mounted. For instance, if you run the command kdb mount /etc/linetest system/linetest line then keyString(parentKey) should be equal to /etc/linetest . At this point, you generally want to open the file so you can begin saving it into keys. Here is the trickier part to explain. Basically, at this point you will want to iterate through the file and create keys and store string values inside of them according to what your plug-in is supposed to do. I will give a few examples of different plug-ins to better explain. My line plug-in was written to read files into a KeySet line by line using the newline character as a delimiter and naming the keys by their line number such as (#1, #2, .. #_22) for a file with 22 lines. So once I open the file given by parentKey, every time a I read a line I create a new key, let s call it new_key using dupKey(parentKey). Then I set new_keys s name to lineNN (where NN is the line number) using keyAddBaseName and store the string value of the line into the key using keySetString. Once the key is initialized, I append it to the KeySet that was passed into the elektraPluginGet function, let s call it returned for now, using ksAppendKey(return, new_key). Now the KeySet will contain new_key with the name lineNN properly saved where it should be according to the kdb mount command (in this case, system/linetest/lineNN), and a string value equal to the contents of that line in the file. MY plug-in repeats these steps as long as it hasn t reached end of file, thus saving the whole file into a KeySet line by line. The simpleini plug-in works similarly, but it parses for ini files instead of just line-by-line. At their most simple level, ini files are in the format of name=value with each pair taking one line. So for this plug-in, it makes a lot of sense to name each Key in the KeySet by the string to the left of the = sign and store the value into each key as a string. For instance, the name of the key would be name and keyGetString(name) would return value .
As you may have noticed, simpleini and line plug-ins work very similarly. However, they just parse the files differently. The simpleini plug-in parses the file in a way that is more natural to ini file (setting the key s name to the left side of the equals sign and the value to the right side of the equals sign.) The elektraPluginGet function is the heart of a storage plug-in, its what allows Elektra to store configurations in it s database. This function isn t just run when a file is first mounted, but whenever a file gets updated, this function is run to update the Elektra Key Database to match. We also gave a brief overview of elektraPluginSet function. This function is basically the opposite of elektraPluginGet. Where elektraPluginGet reads information from a file into the Elektra Key Database, elektraPluginSet writes information from the database back into the mounted file. First have a look at the signature of elektraLineSet: elektraLineSet(Plugin *handle ELEKTRA_UNUSED, KeySet *toWrite, Key *parentKey) Lets start with the most important parameters, the KeySet and the parentKey. The KeySet supplied is the KeySet that is going to be persisted in the file. In our case it would contain the Keys representing the lines. The parentKey is the topmost Key of the KeySet at serves several purposes. First, it contains the filename of the destination file as its value. Second, errors and warnings can be emitted via the parentKey. We will discuss error handling in more detail later. The Plugin handle can be used to persist state information in a threadsafe way with elektraPluginSetData. As our plugin is not stateful and therefore does not use the handle, it is marked as unused in order to supress compiler warnings. Basically the implementation of elektraLineSet can be described with the following pseudocode:

open the file
if (error)

ELEKTRA_SET_ERROR(74, parentKey, keyString(parentKey));

for each key

write the key value together with a newline

close the file
The fullblown code can be found at https://github.com/ElektraInitiative/libelektra/blob/master/src/plugins/line/line.c As you can see, all elektraLineSet does is open a file, take each Key from the KeySet (remember they are named #1, #2 #_22) in order, and write each key as it s own line in the file. Since we don t care about the name of the Key in this case (other than for order), we just write the value of keyString for each Key as a new line in the file. That s it. Now, each time the mounted KeySet is modified, elektraPluginSet will be called and the mounted file will be updated. We haven t discussed ELEKTRA_SET_ERROR yet. Because Elektra is a library, printing errors to stderr wouldn t be a good idea. Instead, errors and warnings can be appended to a key in the form of metadata. This is what ELEKTRA_SET_ERROR does. Because the parentKey always exists even if a critical error occurres, we append the error to the parentKey. The first parameter is an id specifying the general error that occurred. A listing of existing errors together with a short description and a categorization can be found at https://github.com/ElektraInitiative/libelektra/blob/master/src/liberror/specification. The third parameter can be used to provide additional information about the error. In our case we simply supply the filename of the file that caused the error. The kdb tools will interprete this error and print it in a pretty way. Notice that this can be used in any plugin function where the parentKey is available. The elektraPluginOpen and elektraPluginClose functions are not commonly used for storage plug-ins, but they can be useful and are worth reviewing. elektraPluginOpen function runs before elektraPluginGet and is useful to do initialization if necessary for the plug-in. On the other hand elektraPluginClose is run after other functions of the plug-in and can be useful for freeing up resources. The last function, one that is always needed in a plug-in, is ELEKTRA_PLUGIN_EXPORT. This functions is responsible for letting Elektra know that the plug-in exists and which methods it implements. The code from my line function is a good example and pretty self-explanatory:

Plugin *ELEKTRA_PLUGIN_EXPORT(line)

return elektraPluginExport("line",
ELEKTRA_PLUGIN_GET, &elektraLineGet,
ELEKTRA_PLUGIN_SET, &elektraLineSet,
ELEKTRA_PLUGIN_END);

There you have it! This is the last part of my tutorial on writing a storage plug-in for Elektra. Hopefully you now have a good understanding of how Elektra plug-ins work and you ll be able to add some great functionality into Elektra through development of new plug-ins. I hope you enjoyed this tutorial and if you have any questions just leave a comment! Happy coding!
Ian S. Donnelly

7 August 2014

Jordi Mallach: A pile of reasons why GNOME should be Debian jessie s default desktop environment

GNOME has, for some reason or another, always been the default desktop environment in Debian since the installer is able to install a full desktop environment by default. Release after release, Debian has been shipping different versions of GNOME, first based on the venerable 1.2/1.4 series, then moving to the time-based GNOME 2.x series, and finally to the newly designed 3.4 series for the last stable release, Debian 7 wheezy . During the final stages of wheezy s development, it was pointed out that the first install CD image would not longer hold all of the required packages to install a full GNOME desktop environment. There was lots of discussion surrounding this bug or fact, and there were two major reactions to it. The Debian GNOME team rebuilt some key packages so they would be compressed using xz instead of gzip, saving the few megabytes that were needed to squeeze everything in the first CD. In parallel, the tasksel maintainer decided switching to Xfce as default desktop was another obvious fix. This change, unannounced and two days before the freeze, was very contested and spurred the usual massive debian-devel threads. In the end, and after a few default desktop flip flops, it was agreed that GNOME would remain as the default for the already frozen wheezy release, and this issue would be revisited later on during jessie s development. And indeed, some months ago, Xfce was again reinstated as Debian s default desktop for jessie as announced:
Change default desktop to xfce.
This will be re-evaluated before jessie is frozen. The evaluation will
start around the point of DebConf (August 2014). If at that point gnome
looks like a better choice, it ll go back as the default.
Some criteria for that choice will include:
* Popcon numbers for gnome on jessie. If gnome installations continue to
  rise fast enough despite xfce being the default (compared with, say
  kde installations), then we ll know that users prefer gnome.
  Currently we have no data about how many users would choose gnome when
  it s not the default. Part of the reason for switching to xfce now
  is to get such data.
* The state of accessability support, particularly for the blind.
* How well the UI works for both new and existing users. Gnome 3
  seems to be adding back many gnome 2 features that existing users
  expect, as well as making some available via addons. If it feels
  comfortable to gnome 2 (and xfce) users, that would go a long way
  toward switching back to it as the default. Meanwhile, Gnome 3 is also
  breaking new ground in its interface; if the interface seems more
  welcoming to new users, or works better on mobile devices, etc, that
  would again point toward switching back.
* Whatever size constraints exist for CD or other images at the time.
--
Hello to all the tech journalists out there. This is pretty boring.
Why don t you write a story about monads instead?
Joey Hess in dfca406eb694e0ac00ea04b12fc912237e01c9b5.
Suffice to say that the Debian GNOME team participants have never been thrilled about how the whole issue is being handled, and we ve been wondering if we should be doing anything about it, or just move along and enjoy the smaller amount of bug reports against GNOME packages that this change would bring us, if it finally made it through to the final release. During our real life meet-ups in FOSDEM and the systemd+GNOME sprint in Antwerp, most members of the team did feel Debian would not be delivering a graphical environment with the polish we think our users deserve, and decided we at least should try to convince the rest of the Debian project and our users that Debian will be best suited by shipping GNOME 3.12 by default. Power users, of course, can and know how to get around this default and install KDE, Xfce, Cinnamon, MATE or whatever other choice they have. For the average user, though, we think we should be shipping GNOME by default, and tasksel should revert the above commit again. Some of our reasons are: In short, we think defaulting to GNOME is the best option for the Debian release, and in contrast, shipping Xfce as the default desktop could mean delivering a desktop experience that has some incomplete or rough edges, and not on par with Debian quality standards for a stable release. We believe tasksel should again revert the change and be uploaded as soon as possible, in order to get people testing images with GNOME the sooner the better, with the freeze only two months away. We would also like that in the future, changes of this nature will not be announced in a git commit log, but widely discussed in debian-project and the other usual development/decision channels, like the change of init system happened recently. We will, whichever the final decision is, continue to package GNOME with great care to ensure our users get the best possible desktop experience Debian can offer.

Ian Donnelly: How-To: Write a Plug-In (Part 2, The Contract)

Hi Everybody! This is the second installment of my tutorial, How-To: Write a Plug-In. Previously, in Part 1, I went over the basic interface of an Elektra Storage Plug-In. For this installment, I will be focusing on one of the most important aspects of a plug-in, its contract. The contract describes how a plug-in may behave. The main part of the contract describes to Elektra how it will modify the KeySet returned. This is what allows Elektra to work with various types of plug-ins. This guide will focus on one type of plug-in: the storage plug-in. We already have a published specification for plug-ins on our repository but I will reiterate the details here. The first part of the contract you will need is the system/elektra/modules/plugin (where plugin represents the name of your plug-in). All this key does is let elektra know that your plug-in exists. The next key is system/elektra/modules/plugin/exports. This key lets Elektra know that your plug-in exports symbols to Elektra. Below this key you need to create keys for each function you want to export, in my line plug-in I implemented functions for get and set so I will create two keys as follows:
keyNew ("system/elektra/modules/line/exports/get",
KEY_FUNC, elektraLineGet, KEY_END),
keyNew ("system/elektra/modules/line/exports/set",
KEY_FUNC, elektraLineSet, KEY_END),
So far we have told Elektra that our plugin exists and will be exporting functions for getting and setting keys. The next set of keys are the system/elektra/Plugin/infos keys. These are pretty self-explanatory. The first three children of this key, author, license, and description are pretty self explanatory. The infos/provides key tells Elektra the type of plug-in that is being used, this will be storage for any storage plug-in (which is what this tutorial focuses on). To be precise, it tells Elektra which abstract functionality is provided. This allows other plugins to reference abstract functionality instead of declaring a hard dependency to one specific plugin. For example plugins could state that they want to be placed before any other plugin doing the abstract functionality conversion instead of referencing for example the keytometa plugin directly. The info/placements key tells Elektra which functions of the plug-in it should call. Since I implemented get and set in the line plug-in, I would set this key to getstorage setstorage . Next is infos/needs and infos/recommends, infos/needs should contain a list of plug-ins or providers that your plug-in needs to work (see the info/provides key above). Otherwise this key needs to be set to be blank . infos/recommends works exactly like needs except that a plug-in that needs another plug-in won t form a valid backend if the other plug-in doesn t exist but if it only recommends having the other plug-in, it will still work in the others absence. Since Elektra 0.8.7, the best practice for creating a plug-in involves storing the info keys at the very top of a file named REAMDE.md in the same directory as the plugin source. For instance, in my line plugin, the first few lines of README.md are as follows:
- infos = Information about LINE plugin is in keys below
- infos/author = Ian Donnelly <ian.s.donnelly@gmail.com>
- infos/licence = BSD
- infos/needs =
- infos/provides = storage
- infos/placements = getstorage setstorage
- infos/description = Very simple storage plug-in which stores each line from a file as a key
The rest of the README.md file should contain an English description of the plug-in. You can include an introduction to the plug-in, its purpose, any shortcomings it may have, and examples of how to use it. This README.md file is standard for GitHub which will automatically be displayed when a user is browsing your plug-in s directory in the repo. It is written in Markdown. In order to generate the contract from this file you must edit the CMakeLists.txt file in your plug-in source directory to include the following lines:
generate_readme (plugin)
add_includes (elektra-full $ CMAKE_CURRENT_BINARY_DIR )
include_directories ($ CMAKE_CURRENT_BINARY_DIR )

where you substitute plugin with the name of you plugin. This will generate a file called readme_plugin.c (once again, substitute plugin), in your plugin s build directory when you run the make command. The best way to declare the contract is within it s own function, elektraPluginContract. This makes it easier to manage the contract and is much more readable. This is the contract declaration for my line plug-in:

static inline KeySet *elektraLineContract()

return ksNew (30,
keyNew ("system/elektra/modules/line",
KEY_VALUE, "line plugin waits for your orders", KEY_END),
keyNew ("system/elektra/modules/line/exports", KEY_END),
keyNew ("system/elektra/modules/line/exports/get",
KEY_FUNC, elektraLineGet, KEY_END),
keyNew ("system/elektra/modules/line/exports/set",
KEY_FUNC, elektraLineSet, KEY_END),
#include "readme_line.c"
keyNew ("system/elektra/modules/line/infos/version",
KEY_VALUE, PLUGINVERSION, KEY_END),
KS_END);

Next, you will need to make sure to actually set the contract. This is always done in the elektraPluginGet function since this is technically the only REQUIRED function in a plug-in. We just create a new KeySet, set it to our contract, and append it to the returned KeySet. You can see how this is done for line (note that this code is at the very beginning of elektraLineGet):

if (!strcmp (keyName(parentKey), "system/elektra/modules/line"))

KeySet *moduleConfig = elektraLineContract();
ksAppend(returned, moduleConfig);
ksDel(moduleConfig);
return 1;


Note that the plugin contract is nothing special, but just a KeySet interpreted by the resolver forming an Elektra backend. Elektra will request the keys below system/elektra/modules/plugin (where plugin is the pluginname) as soon as it wants to know something about that plugin. Notice also the line #include "readme_line.c". This line, pulls in the contents of readme_line.c in my plug-in s build directory, which due to the lines we added in CMakeLists.txt will contain the contract as defined at the top of README.md. Any changes to the keys in README.md will be reflected in the plug-in next time it is built. Part 2 of this tutorial focuses on the plug-in contract by explaining what each element does and explaining how to implement a contract. For more information about plug-ins and more detailed examples I highly suggest reading Markus Thesis for Elektra. Chapter 4, which starts on page 61 goes into much more detail on Plug-Ins and explains the various features of the contracts. Look for Part 3 soon!

5 August 2014

Steve Kemp: Free (orange) SMS alerts

In the past I used to pay for an email->SMS gateway, which was used to alert me about some urgent things. That was nice because it was bi-directional, and at one point I could restart particular services via sending SMS messages. These days I get it for free, and for my own reference here is how you get to receive free SMS alerts via Orange, which is my mobile phone company. If you don't use Orange/EE this will probably not help you. The first step is to register an Orange email-account, which can be done here: Once you've done that you'll have an email address of the form example@orange.net, which is kinda-sorta linked to your mobile number. You'll sign in and be shown something that looks like webmail from the early 90s. The thing that makes this interesting is that you can look in the left-hand menu and see a link called "SMS Alerts". Visit it. That will let you do things like set the number of SMSs you wish to receive a month (I chose "1000"), and the hours during which delivery will be made (I chose "All the time"). Anyway if you go through this dance you'll end up with an email address example@orange.net, and when an email arrives at that destination an SMS will be sent to your phone. The content of the SMS will be the subject of the mail, truncated if necessary, so you can send a hello message to yourself like this:
echo "nop"   mail -s "Hello, urgent message is present" username@orange.net
Delivery seems pretty reliable, and I've scheduled the mailbox to be purged every week, to avoid it getting full:
Hostnamepop.orange.net
UsernameYour mobile number
PasswordYour password
If you wished to send mail from this you can use smtp.orange.net, but I pity the fool who used their mobile phone company for their primary email address.

4 August 2014

Russ Allbery: Review: Parasite

Review: Parasite, by Mira Grant
Series: Parasitology #1
Publisher: Orbit
Copyright: October 2013
ISBN: 0-316-21893-6
Format: Kindle
Pages: 504
It's 2027, and a company named Symbogen has revolutionized medicine and health. They manufacture a genetically-engineered parasite based on a tapeworm that can stabilize and protect the health of just about anyone. It can synthesize medication, fix chronic medical problems, and be adapted to different conditions. (Yes, I know biological systems don't work this way. That's not going to be the only suspension of disbelief problem.) This has made Symbogen one of the most powerful corporations in the country, aided by the skill at marketing and self-promotion shown by one of the founders. Sal, the protagonist of the novel, is one of Symbogen's most famous success stories. Sally was the victim of a horrible car crash that put her into an apparently irreversible coma. But as her family was debating whether to turn off life support, she woke up. She had no memory of her previous life at all, and had to relearn fine motor control, reading, and many other skills. She was essentially a new person. But she was alive; her symbiont had saved her. When the story proper starts, Sal is still a ward of her parents. She has generally adult skills despite still struggling with reading, but she still has occasional attacks and is under intensive monitoring by Symbogen. That means periodic mandatory appointments with Symbogen, which she hates, but she's otherwise started building a life for herself: a job in an animal shelter, an interest in exotic predatory plants, and, most notably, a boyfriend. There are things about her life she doesn't like, and she wants to be free of Symbogen, but she doesn't have a bad life. But then a mysterious illness begins sweeping through the population, causing people to go blank, apparently lose their minds, and then start attacking those near them. Some of you have doubtless already figured out the key plot revelation. It's not hard; even if you didn't from the summary, you will probably figure it out shortly into the book. And therein lies a large problem with this novel: it's hopelessly predictable. Creepy evil corporation that supposedly has your best interests at heart, check. Plucky mad scientist opposition who understands exactly what's going on, check. Well-meaning but heavy-handed government agents who try to get involved but mostly make everything worse, check. (Although it's unusual to have those agents as part of the protagonist's family, and I thought that added some additional depth.) Mostly clueless protagonist sucked into the plot and becoming critical to its resolution, check. Very few readers are going to be surprised by this story. This is not, by itself, a fatal flaw. Predictable story structures can carry satisfying variations, or introduce the reader to enjoyable characters. And I think Grant manages both here. Seanan McGuire, both as herself and under her Mira Grant pseudonym, tends to write damaged and struggling characters. Both her Newsflesh and October Daye series feature protagonists that have been hurt badly, but are coping and muddling through in their own ways. In Parasite, I think she takes a more daring and intriguing approach: a protagonist that other people in the story perceive as damaged and struggling, but who actually isn't. Sal is not a badly injured Sally, and she's quite a bit healthier than those around her think she is. Her thought processes don't work quite the same as those around her, but that's not because she's hurt. That's because she's a different person. This makes Parasite partly a novel about identity, about Sal claiming ownership of her own life. Grant drags this out longer than I wish she had, but I liked the idea. In Sal, she strikes a good balance between gratitude and genuine affection for her family and the need to become her own person unconstrained by other people's expectations. As with the Newsflesh series, Grant uses quotes and excerpts from interviews to fill in the world background: a few at the start of each chapter, and more around each part boundary. I like this technique, and Grant uses it well. By the end of the book, the Rolling Stone interview with the head of Symbogen has added a lot of insight into how Symbogen manages its public relations. Grant also throws in a few of her trademark dangerously off-beat characters: hyper-competent, wise-cracking, but eerily skewed. I loved those in Blackout and I loved Tansy and Dr. Cale here. (Adam was much less successful.) A whole book from Tansy's perspective wouldn't work, since she needs Sal as a straight woman, but I thought she stole every scene she was in. However, I agree wholeheartedly with Tansy on another point: Sal is remarkably, irritatingly dim about what is apparently intended to be the critical revelation of the book. I won't state it outright; given its significant presence in the final scene, apparently it is intended to be a spoiler. But I figured it out about 50 pages into the book. Grant telegraphs this revelation heavily, and Tansy considers it painfully obvious (with quite a bit of justification). But Sal doesn't figure it out for the entire book, ignores all the signs, and is apparently willfully blind. In a book written from the first-person perspective by an otherwise-reliable narrator, this is highly annoying. It significantly undermined my enjoyment of the book. I spent much of the novel ahead of the narrator in my understanding of the plot and waiting, in vain, for her to get on with it already. That unfortunately makes Parasite a mixed bag. I really liked many of the characters, and I think Grant did some interesting things with family dynamics and with claiming one's own identity. But this is undermined by a very predictable plot, the protagonist deciding to be dumber than a sack of hammers about a critical plot point, and some rather dubious world logic. (For example, why is Sal terrified of bad driving? It makes sense as a post-traumatic stress reaction... except it's a critical point to her characterization that she never went through that stress.) Sometimes I wanted to like this book and sometimes I wanted to shake it, and sometimes I felt both reactions at the same time. I like Grant's writing and characterization well enough that I will probably read the sequel, but this is more like the later books in the Newsflesh series than it is like the spectacular Feed. Worth reading, at least for me, but it could have been better. Rating: 7 out of 10

3 August 2014

Holger Levsen: 20140803-torbrowser-launcher

About torbrowser-launcher in all current Debian distros plus some thoughts and scripts for running it more securely So, torbrowser-launcher 0.1.2-1 is now in sid (only that version has the script examples discussed below), and 0.1.1-2(~bpo70+1) are in jessie and wheezy-backports. Originally Jacob Appelbaum packaged torbrowser-launcher, then Ulrike Uhlig stepped in and fixed some major bugs, I sponsored her uploads and somehow the idea emerged to team maintain the package, so pkg-anonymity-tools was founded. So far it's only used for having a mailing list which is used for the Maintainer: field of the torbrowser-launcher package. But we invite all maintainers of anonymity related packages to join the team! Currently there ain't even a Debian teams wiki page about it (it would be great if YOU could fix that!), so that will probably be the next thing that will happen. As for version control we intend to use the collab-maint project on alioth. So joining the team is not done by joining the alioth project (technically you can do this, but it's rather pointless), but rather by putting the pkg-anonymity-tools mailing list into the Maintainer: field of your package (and you and other people into the Uploaders: field) and subscribing to that very mailing list. Once more packages are maintained that way we'll need to see whether we'll need more mailing lists (eg one specific for commit notifications) or if we rely on client side filtering only or what else should be done. The example scripts (available in /usr/share/doc/torbrowser-launcher/examples in the package from sid or in git) show how to run torbrowser-launcher, confined with AppArmor, in Xephyr (a virtual Xserver running on another Xserver) as another user. This, using AppArmor and Xephyr, shall have two effects: Does that really help? Feedback welcome. Full quote of /usr/share/doc/torbrowser-launcher/examples/README:
torbrowser-launcher launcher scripts
====================================
These scripts are intended to run torbrowser-launcher (and thus torbrowser) as
another user in an Xephyr window server running inside your normal Xorg
session.
They assume the following packages are installed:
- torbrowser-launcher
- apparmor
- xserver-xephyr, awesome
- sudo, slay, psmisc
AppArmor should be enabled, but doesn't have to. I followed the HowTo from
https://wiki.debian.org/AppArmor, which can be summed up as just adding one
parameter to the kernel to enable it, followed by a reboot.
Using Apparmor has the advantage that the browser process cannot most of the
filesystem, eg saving downloads only works in ~/.torbrowser/tbb/x86_64/tor-browser_en-US/Desktop/
On wheezy, I'm using backports for torbrowser-launcher and apparmor.
The scripts assume they have been copied to /usr/local/bin/ and that there is
a user called "foo" (for running the actuall torbrowser(-launcher) process,
and that the current user has sudo rights for the following commands:
- sudo -i -u foo /usr/local/bin/tbb-l-wrapper
- sudo slay foo
There are two scripts, tbb-in-xephyr and tbb-l-wrapper. Only tbb-in-xephyr is
to be called directly and will result in torbrowser running in Xephyr.
Known problems:
---------------
- dbus is not started, so some input methods won't work. (Personally I don't
  want/need dbus though, so I'm awaiting a solution to
  https://trac.torproject.org/projects/tor/ticket/10014)
- not everybody likes awesome as the window manager being used ;)
Ideas, questions and ToDo:
--------------------------
- maybe all of this functionality could be integrated into.
  torbrowser-launcher itself, just writing this in shell was so easy.
- or for the time being, merge these two scripts into one, doing both,
  depending on how its called. Also make them run from everywhere.
- run this in an unprivileged LXC container, which is also apparmor confined.
- (when) does this double confinement make sense?
- use a more sensible named default user (instead of foo).
- there should really be an option, so torbrowser-launcher doesn't detach
  itself, so that this "while;ps fax grep" hack can go away.
- ship an usable sudoers.d example too.
- support for more users / instances
Feedback welcome, especially accompanied by patches! 

1 August 2014

Ian Donnelly: How-To: Write a Plug-In (Part 1, The Basics)

Hi Everybody! For the first part of my Plug-In tutorial, I am going to cover the basic overview of an elektra plug-in. This post just explains the basic format and functions of an Elektra plug-in, specifically a storage plug-in (this will be the focus of my tutorial). All plug-ins use the same basic interface. This interface consists of five basic functions, elektraPluginOpen, elektraPluginGet, elektraPluginSet, elektraPluginError, and elektraPluginClose. The developer replaces Plugin with the name of their plugin. So in the case of my plugin, the names of these functions would be elektraLineOpen(), elektraLineGet(), elektraLineSet(), elektraLineError(), and elektraLineClose(). Additionally, there is one more function called ELEKTRA_PLUGIN_EXPORT(plugin), where once again Plugin should be replaced with the name of the plug-in, this time in lower-case. So for my line plugin this function would be ELEKTRA_PLUGIN_EXPORT(line). The KDB relies on the first five functions for interacting with configuration files stored in the key database. Calls for kdbGet() and kdbClose() will call the functions elektraPluginGet() and elektraPluginClose() respectively for the plugin that was used to mount the configuration data. kdbSet() calls elektraPluginSet() but also elektraPluginError() when an error occurs. elektraPluginOpen() is called before the first call to elektraPluginGet() or elektraPluginSet(). These functions serve different purposes that allow the plug-in to work: Most simply put: most plug-ins consist of five major functions, elektraPluginOpen(), elektraPluginClose(), elektraPluginGet(), elektraPluginSet(), and ELEKTRA_EXPORT_PLUGIN(Plugin). Because remembering all these functions can be cumbersome, we provide a skeleton plugin in order to easily create a new plugin. The skeleton plugin is called template and a new plugin can be created by calling the copy-template script. For example for my plugin I called

../../scripts/copy-template line

from within the plugins directory. Afterwards two important things are left to be done:
  1. remove all functions (and their exports) from the plugin that are not needed. For example not every plugin actually makes use of the elektraPluginOpen() function.
  2. provide a basic contract as described above
After these two steps your plugin is ready to be compiled, installed and mounted for the first time. Have a look at the mount tutorial for details on howto do this. So Part 1 of the tutorial covers the implementation details for a plug-in. Next up will be Part 2, which will cover the theory behind contracts in Elektra as well as how to implement them. Sincerely,
Ian S. Donnelly

31 July 2014

Russell Coker: Links July 2014

Dave Johnson wrote an interesting article for Salon about companies ripping off the tax system by claiming that all their income is produced in low tax countries [1]. Seb Lee-Delisle wrote an insightful article about how to ask to get paid to speak [2]. I should do that. Daniel Pocock wrote an informative article about the reConServer simple SIP conferencing server [3]. I should try it out, currently most people I want to conference with are using Google Hangouts, but getting away from Google is a good thing. Fran ois Marier wrote an informative post about hardening ssh servers [4]. S. E. Smith wrote an interesting article I Am Tired of Hearing Programmers Defend Gender Essentialism [5]. Bert Archer wrote an insightful article about lazy tourism [6]. His initial example of love locks breaking bridges was a bit silly (it s not difficult to cut locks off a bridge) but his general point about lazy/stupid tourism is good. Daniel Pocock wrote an insightful post about new developments in taxis, the London Taxi protest against Uber, and related changes [7]. His post convinced me that Uber is a good thing and should be supported. I checked the prices and unfortunately Uber is more expensive than normal taxis for my most common journey. Cory Doctorow wrote an insightful article for The Guardian about the moral issues related to government spying [8]. The Verge has an interesting review of the latest Lytro Lightbox camera [9]. Not nearly ready for me to use, but interesting technology. Prospect has an informative article by Kathryn Joyce about the Protestant child sex abuse scandal in the US [10]. Billy Graham s grandson is leading the work to reform churches so that they protect children instead of pedophiles. Prospect also has an article by Kathryn Joyce about Christians home-schooling kids to try and program them to be zealots and how that hurts kids [11]. The Daily Beast has an interesting article about the way that the extreme right wing in the US are trying to kill people, it s the right wing death panel [12]. Jay Michaelson wrote an informative article for The Daily Beast about right-wing hate groups in the US who promote the extreme homophobic legislation in Russia and other countries [13]. It also connects to the Koch brothers who seem to be associated with most evil. Elias Isquith wrote an insightful article for Salon about the current right-wing obsession with making homophobic discrimination an issue of religious liberty will hurt religious people [14]. He also describes how stupid the right-wing extremists are in relation to other issues too. EconomixComix.com has a really great comic explaning the economics of Social Security in the US [15]. They also have a comic explaining the TPP which is really good [16]. They sell a comic book about economics which I m sure is worth buying. We need to have comics explaining all technical topics, it s a good way of conveying concepts. When I was in primary school my parents gave me comic books covering nuclear physics and other science topics which were really good. Mia McKenzie wrote an insightful article for BlackGirlDangerous.com about dealing with racist white teachers [17]. I think that it would be ideal to have a school dedicated to each minority group with teachers from that group.

Craig Small: Linux Capabilities

I was recently updating some code that uses fping. Initially it used exec() that was redirected to a temporary file but I changed it to use popen. While it had been a while since I ve done this sort of thing, I do recall there was an issue with running popen on setuid binary. A later found it is mainly around setuid scripts which are very problematic and there are good reasons why you don t do this. Anyhow, the program worked fine which surprised me. Was fping setuid root to get the raw socket?
$ ls -l /usr/bin/fping
-rwxr-xr-x 1 root root 31464 May  6 21:42 /usr/bin/fping
It wasn t which at first all I thought ok, so that s why popen is happy . The way that fping and other programs work is they bind to a raw socket. This socket sits below the normal type sockets such as the ones used for TCP and UDP and normal users cannot use them by default. So how did fping work it s magic and get access to this socket? It used Capabilities. Previously getting privileged features had a big problem; it was an all or nothing thing. You want access to a raw socket? Sure, be setuid but that means you also could, for example, read any file on the system or set passwords. Capabilites provide a way of giving programs some better level of access, but not a blank cheque. The tool getcap is the way of determining what capabilities are found on a file. These capabilities are attributes on the file which, when the file is run, turn into capabilities or extra permissions. fping has the capability cap_net_raw+ep applied to it. This gives access to the RAW and PACKET sockets which is what fping needs. The +ep after the capability name means it is an Effective and Permitted capability, which describes what happens with child processes and dropping privileges. I hadn t seen these Capabilities before. They are a nice way to give your programs the access they need, but limiting the risk of something going wrong and having a rouge program running as root.

29 July 2014

Ian Campbell: Debian Installer ARM64 Dailies

It's taken a while but all of the pieces are finally in place to run successfully through Debian Installer on ARM64 using the Debian ARM64 port. So I'm now running nightly builds locally and uploading them to http://www.hellion.org.uk/debian/didaily/arm64/. If you have CACert in your CA roots then you might prefer the slightly more secure version. Hopefully before too long I can arrange to have them building on one of the project machines and uploaded to somewhere a little more formal like people.d.o or even the regular Debian Installer dailies site. This will have to do for now though. Warning The arm64 port is currently hosted on Debian Ports which only supports the unstable "sid" distribution. This means that installation can be a bit of a moving target and sometimes fails to download various installer components or installation packages. Mostly it's just a case of waiting for the buildd and/or archive to catch up. You have been warned! Installing in a Xen guest If you are lucky enough to have access to some 64-bit ARM hardware (such as the APM X-Gene, see wiki.xen.org for setup instructions) then installing Debian as a guest is pretty straightforward. I suppose if you had lots of time (and I do mean lots) you could also install under Xen running on the Foundation or Fast Model. I wouldn't recommend it though. First download the installer kernel and ramdisk onto your dom0 filesystem (e.g. to /root/didaily/arm64). Second create a suitable guest config file such as:
name = "debian-installer"
disk = ["phy:/dev/LVM/debian,xvda,rw"]
vif = [ '' ] 
memory = 512
kernel = "/root/didaily/arm64/vmlinuz"
ramdisk= "/root/didaily/arm64/initrd.gz"
extra = "console=hvc0 -- "
In this example I'm installing to a raw logical volume /dev/LVM/debian. You might also want to use randmac to generate a permanent MAC address for the Ethernet device (specified as vif = ['mac=xx:xx:xx:xx:xx:xx']). Once that is done you can start the guest with:
xl create -c cfg
From here you'll be in the installer and things carry on as usual. You'll need to manually point it to ftp.debian-ports.org as the mirror, or you can preseed by appending to the extra line in the cfg like so:
mirror/country=manual mirror/http/hostname=ftp.debian-ports.org mirror/http/directory=/debian
Apart from that there will be a warning about not knowing how to setup the bootloader but that is normal for now. Installing in Qemu To do this you will need a version of http://www.qemu.org which supports qemu-system-aarch64. The latest release doesn't yet so I've been using v2.1.0-rc3 (it seems upstream are now up to -rc5). Once qemu is built and installed and the installer kernel and ramdisk have been downloaded to $DI you can start with:
qemu-system-aarch64 -M virt -cpu cortex-a57 \
    -kernel $DI/vmlinuz -initrd $DI/initrd.gz \
    -append "console=ttyAMA0 -- " \
    -serial stdio -nographic --monitor none \
    -drive file=rootfs.qcow2,if=none,id=blk,format=qcow2 -device virtio-blk-device,drive=blk \
    -net user,vlan=0 -device virtio-net-device,vlan=0
That's using a qcow2 image for the rootfs, I think I created it with something like:
qemu-img create -f qcow2 rootfs.qcow2 4G
Once started installation proceeds much like normal. As with Xen you will need to either point it at the debian-ports archive by hand or preseed by adding to the -append line and the warning about no bootloader configuration is expected. Installing on real hardware Someone should probably try this ;-).

Russell Coker: Happiness and Lecture Questions

I just attended a lecture about happiness comparing Australia and India at the Australia India Institute [1]. The lecture was interesting but the questions were so bad that it makes a good case for entirely banning questions from public lectures. Based on this and other lectures I ve attended I ve written a document about how to recognise worthless questions and cut them off early [2]. As you might expect from a lecture on happiness there were plenty of stupid comments from the audience about depression, as if happiness is merely the absence of depression. Then they got onto stupidity about suicide. One question claimed that Australia has a high suicide rate, Wikipedia however places Australia 49th out of 110 countries, that means Australia is slightly above the median for suicide rates per country. Given some of the dubious statistics in the list (for example the countries claiming to have no suicides and the low numbers reported by some countries with extreme religious policies) I don t think we can be sure that Australia would be above the median if we had better statistics. Another question claimed that Sweden had the highest suicide rate in Europe, while Greenland, Belgium, Finland, Austria, France, Norway, Denmark, Iceland, and most of Eastern Europe are higher on the list. But the bigger problem in regard to discussing suicide is that the suicide rate isn t about happiness. When someone kills themself because they have a terminal illness that doesn t mean that they were unhappy for the majority of their life and doesn t mean that they were any unhappier than the terminally ill people who don t do that. Some countries have a culture that is more positive towards suicide which would increase the incidence, Japan for example. While people who kill themselves in Japan are probably quite unhappy at the time I don t think that there is any reason to believe that they are more unhappy than people in other countries who only keep living because suicide is considered to be wrong. It seems to me that the best strategy when giving or MCing a lecture about a potentially contentious topic is to plan ahead for what not to discuss. For a lecture about happiness it would make sense to rule out all discussion of suicide, anti-depressants, and related issues as they aren t relevant to the discussion and can t be handled in an appropriate manner in question time.

28 July 2014

Chris Lamb: start-stop-daemon: --exec vs --startas

start-stop-daemon is the classic tool on Debian and derived distributions to manage system background processes. A typical invokation from an initscript is as follows:
start-stop-daemon \
    --quiet \
    --oknodo \
    --start \
    --pidfile /var/run/daemon.pid \
    --exec /usr/sbin/daemon \
    -- -c /etc/daemon.cfg -p /var/run/daemon.pid
The basic operation is that it will first check whether /usr/sbin/daemon is not running and, if not, execute /usr/sbin/daemon -c /etc/daemon.cfg -p /var/run/daemon.pid. This process then has the responsibility to daemonise itself and write the resulting process ID to /var/run/daemon.pid. start-stop-daemon then waits until /var/run/daemon.pid has been created as the test of whether the service has actually started, raising an error if that doesn't happen. (In practice, the locations of all these files are parameterised to prevent DRY violations.)
Idempotency By idempotence we are mostly concerned with repeated calls to /etc/init.d/daemon start not starting multiple versions of our daemon. This might not seem to be particularly big issue at first but the increased adoption of stateless configuration management tools such as Ansible (which should be completely free to call start to ensure a started state) mean that one should be particularly careful of this apparent corner case. In its usual operation, start-stop-daemon ensures only one instance of the daemon is running with the --exec parameter: if the specified pidfile exists and the PID it refers to is an "instance" of that executable, then it is assumed that the daemon is already running and another copy is not started. This is handled in the pid_is_exec method (source) - the /proc/$PID/exe symlink is resolved and checked against the value of --exec.
Interpreted scripts However, one case where this doesn't work is interpreted scripts. Lets look at what happens if /usr/sbin/daemon is such a script, eg. a file that starts:
#!/usr/bin/env python
# [..]
The problem this introduces is that /proc/$PID/exe now points to the interpreter instead, often with an essentially non-deterministic version suffix:
$ ls -l /proc/14494/exe
lrwxrwxrwx 1 www-data www-data 0 Jul 25 15:18
                              /proc/14494/exe -> /usr/bin/python2.7
When this process is examined using the --exec mechanism outlined above it will be rejected as an instance of /usr/sbin/daemon and therefore another instance of that daemon will be incorrectly started.
--startas The solution is to use the --startas parameter instead. This omits the /proc/$PID/exe check and merely tests whether a PID with that number is running:
start-stop-daemon \
    --quiet \
    --oknodo \
    --start \
    --pidfile /var/run/daemon.pid \
    --startas /usr/sbin/daemon \
    -- -c /etc/daemon.cfg -p /var/run/daemon.pid
Whilst it is therefore less reliable (in that the PID found in the pidfile could actually be an entirely different process altogether) it's probably an acceptable trade-off against the case of running multiple instances of that daemon. This danger can be ameliorated by using some of start-stop-daemon's other matching tests, such as --user or even --name.

Daniel Pocock: Secure that Dictaphone

2014 has been a big year for dictaphones so far. First, it was France and the secret recordings made by Patrick Buisson during the reign of President Sarkozy. Then, a US court ordered the release of the confidential Boston College tapes, part of an oral history project. Originally, each participant had agreed their recording would only be released after their death. Sinn Fein leader Gerry Adams was arrested and questioned over a period of 100 hours and released without charge. Now Australia is taking its turn. In #dictagate down under, a senior political correspondent from a respected newspaper recorded (most likely with consent) some off-the-record comments of former conservative leader Ted Baillieu. Unfortunately, this journalist misplaced the dictaphone at the state conference of Baillieu's arch-rivals, the ALP. A scandal quickly errupted. Secure recording technology There is no question that electronic voice recordings can be helpful for people, including journalists, researchers, call centers and many other purposes. However, the ease with which they can now be distributed is only dawning on people. Twenty years ago, you would need to get the assistance of a radio or TV producer to disseminate such recordings so widely. Today there is email and social media. The Baillieu tapes were emailed directly to 400 people in a matter of minutes. Just as technology brings new problems, it also brings solutions. Encryption is one of them. Is encryption worthwhile? Coverage of the Snowden revelations has revealed that many popular security technologies are not one hundred percent safe. In each of these dictaphone cases, however, NSA-level expertise was not a factor. Even the most simplistic encryption would have caused endless frustration to the offenders who distributed the Baillieu tape. How can anybody be sure encryption is reliable? Part of the problem is education. Everybody using the technology needs to be aware of the basic concepts, for example, public key cryptography. Another big question mark is back doors. There is ongoing criticism of Apple iPhone/iPod devices and the many ways that their encryption can be easily disabled by Apple engineers and presumably many former staff, security personnel and others. The message is clear: proprietary, closed-source solutions should be avoided. Free and open source technologies are the alternative. If a company does not give you the source code, how can anybody independently audit their code for security? With encryption software, what use is it if nobody has verified it? What are the options? However, given that the majority of people don't have a PhD in computer science or mathematics, are there convenient ways to get started with encryption? Reading is a good start. The Code Book by Simon Singh (author of other popular science books like Fermat's Last Theorem) is very accessible, not classified and assumes no formal training in mathematics. Even for people who do know these topics inside out, it is a good book to share with friends and family. The Guardian Project (no connection with Guardian Media of Edward Snowden fame) aims to provide a secure and easy to use selection of apps for pocket devices. This project has practical applications in business, journalism and politics alike. How should a secure dictaphone app work? Dictaphone users typically need to take their dictaphones in the field, so there is a risk of losing it or having it stolen. A strong security solution in this situation may involve creating an RSA key pair on a home/office computer, keeping the private key on the home computer and putting the public key on the dictaphone device. Configured this way, the dictaphone will not be able to play back any of the recordings itself - the user will always have to copy them to the computer for decryption.

25 July 2014

Richard Hartmann: Release Critical Bug report for Week 30

I have been asked to publish bug stats from time to time. Not exactly sure about the schedule yet, but I will try and stick to Fridays, as in the past; this is for the obvious reason that it makes historical data easier to compare. "Last Friday of each month" may or may not be too much. Time will tell. The UDD bugs interface currently knows about the following release critical bugs: Graphical overview of bug stats thanks to azhag:

Juliana Louback: Extending an xTuple Business Object

xTuple is in my opinion incredibly well designed; the code is clean and the architecture ahderent to a standardized structure. All this makes working with xTuple software quite a breeze. I wanted to integrate JSCommunicator into the web-based xTuple version. JSCommunicator is a SIP communication tool, so my first step was to create an extension for the SIP account data. Luckily for me, the xTuple development team published an awesome tutorial for writing an xTuple extension. xTuple cleverly uses model based business objects for the various features available. This makes customizing xTuple very straightforward. I used the tutorial mentioned above for writing my extension, but soon noticed my goals were a little different. A SIP account has 3 data fields, these being the SIP URI, the account password and an optional display name. xTuple currently has a business object in the core code for a User Account and it would make a lot more sense to simply add my 3 fields to this existing business object rather than create another business object. The tutorial very clearly shows how to extend a business object with another business object, but not how to extend a business object with only new fields (not a whole new object). Now maybe I m just a whole lot slower than most people, but I had a ridiculously had time figuring this out. Mind you, this is because I m slow, because the xTuple documentation and code is understandable and as self-explanatory as it gets. I think it just takes a bit to get used to. Either way, I thought this just might be useful to others so here is how I went about it. Setup First you ll have to set up your xTuple development environment and fork the xtuple and xtuple-extesions repositories as shown in this handy tutorial. A footnote I d like to add is please verify that your version of Vagrant (and anything else you install) is the one listed in the tutorial. I think I spent like two entire days or more on a wild goose (bug) chase trying to set up my environment when the cause of all the errors was that I somehow installed an older version of Vagrant - 1.5.4 instead of 1.6.3. Please don t make the same mistake I did. Actually if for some reason you get the following error when you try using node:
<<ERROR 2014-07-10T23:52:46.948Z>> Unrecoverable exception. Cannot call method 'extend' of undefined
    at /home/vagrant/dev/xtuple/lib/backbone-x/source/model.js:37:39
    at Object.<anonymous> (/home/vagrant/dev/xtuple/lib/backbone-x/source/model.js:1364:3)
    ...
chances are, you have the wrong version. That s what happened to me. The Vagrant Virtual Development Environment automatically installs and configures everything you need, it s ready to go. So if you find yourself installing and updating and apt-gets and etc, you probably did something wrong. Coding So by now we should have the Vagrant Virtual Development Environment set up and the web app up and running and accessible at localhost:8443. So far so good. Disclaimer: You will note that much of this is similar - or rather, nearly identical - to xTuple s tutorial but there are some small but important differences and a few observations I think might be useful. Other Disclaimer: I m describing how I did it, which may or may not be up to snuff . Works for me though. Schema First let s make a schema for the table we will create with the new custom fields. Be sure to create the correct directory stucture, aka /path/to/xtuple-extensions/source/<YOUR EXTENSION NAME>/database/source or in my case /path/to/xtuple-extensions/source/sip_account/database/source, and create the file create_sa_schema.sql, sa is the name of my schema. This file will contain the following lines:
do $$
  /* Only create the schema if it hasn't been created already */
  var res, sql = "select schema_name from information_schema.schemata where schema_name = 'sa'",
  res = plv8.execute(sql);
  if (!res.length)  
    sql = "create schema sa; grant all on schema sa to group xtrole;"
    plv8.execute(sql);
   
$$ language plv8;
Of course, feel free to replace sa with your schema name of choice. All the code described here can be found in my xtuple-extensions fork, on the sip_ext branch. Table We ll create a table containing your custom fields and a link to an existing table - the table for the existing business object you want to extend. If you re wondering why make a whole new table for a few extra fields, here s a good explanation, the case in question is adding fields to the Contact business object. You need to first figure out what table you want to link to. This might not be uber easy. I think the best way to go about it is to look at the ORMs. The xTuple ORMs are a JSON mapping between the SQL tables and the object-oriented world above the database, they re .json files found at path/to/xtuple/node_modules/xtuple/enyo-client/database/orm/models for the core business objects and at path/to/xtuplenyo-client/extensions/source/<EXTENSION NAME>/database/orm/models for exension business objects. I ll give two examples. If you look at contact.json you will see that the Contact business object refers to the table cntct . Look for the type : Contact on the line above, so we know it s the Contact business object. In my case, I wanted to extend the UserAccount and UserAccountRelation business objects, so check out user_account.json. The table listed for UserAccount is xt.usrinfo and the table listed for UserAccountRelation is xt.usrlite. A closer look at the sql files for these tables (usrinfo.sql and usrlite.sql) revealed that usrinfo is in fact a view and usrlite is A light weight table of user information used to avoid punishingly heavy queries on the public usr view . I chose to refer to xt.usrlite - that or I received error messages when trying the other table names. Now I ll make the file /path/to/xtuple-extensions/source/sip_account/database/source/usrlitesip.sql, to create a table with my custom fields plus the link to the urslite table. Don t quote me on this, but I m under the impression that this is the norm for naming the sql file joining tables: the name of the table you are referring to ( usrlite in this case) and your extension s name. Content of usrlitesip.sql:
select xt.create_table('usrlitesip', 'sa');
select xt.add_column('usrlitesip','usrlitesip_id', 'serial', 'primary key', 'sa');
select xt.add_column('usrlitesip','usrlitesip_usr_username', 'text', 'references xt.usrlite (usr_username)', 'sa');
select xt.add_column('usrlitesip','usrlitesip_uri', 'text', '', 'sa');
select xt.add_column('usrlitesip','usrlitesip_name', 'text', '', 'sa');
select xt.add_column('usrlitesip','usrlitesip_password', 'text', '', 'sa');
comment on table sa.usrlitesip is 'Joins User with SIP account';
Breaking it down, line 1 creates the table named usrlitesip (no duh), line 2 is for the primary key (self-explanatory). You can then add any columns you like, just be sure to add one that references the table you want to link to. I checked usrlite.sql and saw the primary key is usr_username, be sure to use the primary key of the table you are referencing. You can check what you made by executing the .sql files like so:
$ cd /path/to/xtuple-extensions/source/sip_account/database/source
$ psql -U admin -d dev -f create_sa_schema.sql
$ psql -U admin -d dev -f usrlitesip.sql
After which you will see the table with the columns you created if you enter:
$ psql -U admin -d dev -c "select * from sa.usrlitesip;"
Now create the file /path/to/xtuple-extensions/source/sip_account/database/source/manifest.js to put the files together and in the right order. It should contain:
 
  "name": "sip_account",
  "version": "1.4.1",
  "comment": "Sip Account extension",
  "loadOrder": 999,
  "dependencies": ["crm"],
  "databaseScripts": [
    "create_sa_schema.sql",
    "usrlitesip.sql",
    "register.sql"
  ]
 
I think the name has to be the same you named your extension directory as in /path/to/xtuple-extensions/source/<YOUR EXTENSION NAME>. I think the comment can be anything you like and you want your loadOrder to be high so it s the last thing installed (as it s an add on.) So far we are doing exactly what s instructed in the xTuple tutorial. It s repetitive, but I think you can never have too many examples to compare to. In databaseScripts you will list the two .sql files you just created for the schema and the table, plus another file to be made in the same directory named register.sql. I m not sure why you have to make the register.sql or even if you indeed have to. If you leave the file empty, there will be a build error, so put a ; in the register.sql or remove the line register.sql from manifest.js as I think for now we are good without it. Now let s update the database with our new extension:
$ cd /path/to/xtuple
$ ./scripts/build_app.js -d dev -e ../xtuple-extensions/source/sip_account
$ psql -U admin -d dev -c "select * from xt.ext;"
That last command should display a table with a list of extensions; the ones already in xtuple like crm and billing and some others plus your new extension, in this case sip_account . When you run build_app.js you ll probably see a message along the lines of <Extension name> has no client code, not building client code and that s fine because yeah, we haven t worked on the client code yet. ORM Here s where things start getting different. So ORMs link your object to an SQL table. But we DON T want to make a new business object, we want to extend an existing business object, so the ORM we will make will be a little different than the xTuple tutorial. Steve Hackbarth kindly explained this new business object/existing business object ORM concept here. First we ll create the directory /path/to/xtuple-extensions/source/sip_account/database/orm/ext, according to xTuple convention. ORMs for new business objects would be put in /path/to/xtuple-extensions/source/sip_account/database/orm/models. Now we ll create the .json file /path/to/xtuple-extensions/source/sip_account/database/orm/ext/user_account.jscon for our ORM. Once again, don t quote me on this, but I think the name of the file should be the name of the business object you are extending, as is done in the turorial example extending the Contact object. In our case, UserAccount is defined in user_account.json and that s what I named my extension ORM too. Here s what you should place in it:
 1 [
 2    
 3     "context": "sip_account",
 4     "nameSpace": "XM",
 5     "type": "UserAccount",
 6     "table": "sa.usrlitesip",
 7     "isExtension": true,
 8     "isChild": false,
 9     "comment": "Extended by Sip",
10     "relations": [
11        
12         "column": "usrlitesip_usr_username",
13         "inverse": "username"
14        
15     ],
16     "properties": [
17        
18         "name": "uri",
19         "attr":  
20           "type": "String",
21           "column": "usrlitesip_uri",
22           "isNaturalKey": true
23          
24        ,
25        
26         "name": "displayName",
27         "attr":  
28           "type": "String",
29           "column": "usrlitesip_name"
30          
31        ,
32        
33         "name": "sipPassword",
34         "attr":  
35           "type": "String",
36           "column": "usrlitesip_password"
37          
38        
39     ],
40     "isSystem": true
41    ,
42    
43     "context": "sip_account",
44     "nameSpace": "XM",
45     "type": "UserAccountRelation",
46     "table": "sa.usrlitesip",
47     "isExtension": true,
48     "isChild": false,
49     "comment": "Extended by Sip",
50     "relations": [
51        
52         "column": "usrlitesip_usr_username",
53         "inverse": "username"
54        
55     ],
56     "properties": [
57        
58         "name": "uri",
59         "attr":  
60           "type": "String",
61           "column": "usrlitesip_uri",
62           "isNaturalKey": true
63          
64        ,
65        
66         "name": "displayName",
67         "attr":  
68           "type": "String",
69           "column": "usrlitesip_name"
70          
71        ,
72        
73         "name": "sipPassword",
74         "attr":  
75           "type": "String",
76           "column": "usrlitesip_password"
77          
78        
79     ],
80     "isSystem": true
81    
82 ]
Note the context is my extension name, because the context + nameSpace + type combo has to be unique. We already have a UserAccount and UserAccountRelation object in the XM namespace in the xtuple context in the original user_account.json, now we will have a UserAccount and UserAccountRelation object in the XM namespace in the sip_account conext. What else is important? Note that isExtension is true on lines 7 and 47 and the relations item contains the column of the foreign key we referenced. This is something you might want to verify: column (lines 12 and 52) is the name of the attribute on your table. When we made a reference to the primary key usr_usrname from the xt.usrlite table we named that column usrlitesip_usr_usrname. But the inverse is the attribute name associated with the original sql column in the original ORM. Did I lose you? I had a lot of trouble with this silly thing. In the original ORM that created a new UserAccount business object, the primary key attribute is named username , as can be seen here. That is what should be used for the inverse value. Not the sql column name (usr_username) but the object attribute name (username). I m emphasizing this because I made that mistake and if I can spare you the pain I will. If we rebuild our extension everything should come along nicely, but you won t see any changes just yet in the web app because we haven t created the client code. Client Create the directory /path/to/xtuple-extensions/source/sip_account/client which is where we ll keep all the client code. Extend Workspace View I want the fields I added to show up on the form to create a new User Account, so I need to extend the view for the User Account workspace. I ll start by creating a directory /path/to/xtuple-extensions/source/sip_account/client/views and in it creating a file named workspace.js containing this code:
XT.extensions.sip_account.initWorkspace = function ()  
	var extensions = [
  	 kind: "onyx.GroupboxHeader", container: "mainGroup", content: "_sipAccount".loc() ,
  	 kind: "XV.InputWidget", container: "mainGroup", attr: "uri"  ,
  	 kind: "XV.InputWidget", container: "mainGroup", attr: "displayName"  ,
  	 kind: "XV.InputWidget", container: "mainGroup", type:"password", attr: "sipPassword"  
	];
	XV.appendExtension("XV.UserAccountWorkspace", extensions);
 ;
So I m initializing my workspace and creating an array of items to add (append) to view XV.UserAccountWorkspace. The first item is this onyx.GroupboxHeader which is a pretty divider for my new form fields, the kind you find in the web app at Setup > User Accounts, like Overview . I have no idea what other options there are for container other than mainGroup , so let s stick to that. I ll explain content: _sipAccount .loc() in a bit. Next I created three input fields of the XV.InputWidget kind. This also confused me a bit as there are different kinds of input to be used, like dropdowns and checkboxes. The only advice I can give is snoop around the webapp, find an input you like and look up the corresponding workspace.js file to see what was used. What we just did is (should be) enough for the new fields to show up on the User Account form. But before we see things change, we have to package the client. Create the file /path/to/xtuple-extensions/source/sip_account/client/views/package.js. This file is needed to package groups of files and indicates the order the files should be loaded (for more on that, see this). For now, all the file will contain is:
enyo.depends(
"workspace.js"
);
You also need to package the views directory containing workspace.js, so create the file Create the file /path/to/xtuple-extensions/source/sip_account/client/package.js and in it show that the directory views and its contents must be part of the higher level package:
enyo.depends(
"views"
);
I like to think of it as a box full of smaller boxes. This will sound terrible, but apparently you also need to create the file /path/to/xtuple-extensions/source/sip_account/client/core.js containing this line:
XT.extensions.icecream =  ;
I don t know why. As soon as I find out I ll be sure to inform you. As we ve added a file to the client directory, be sure to update /path/to/xtuple-extensions/source/sip_account/client/package.js so it included the new file:
enyo.depends(
"core.js",
"views"
);
Translations Remember _sipAccount .loc() in our workspace.js file? xTuple has great internationalization support and it s easy to use. Just create the directory and file /path/to/xtuple-extensions/source/sip_account/client/en/strings.js and in it put key-value pairs for labels and their translation, like this:
(function ()  
  "use strict";
  var lang = XT.stringsFor("en_US",  
    "_sipAccount": "Sip Account",
    "_uri": "Sip URI",
    "_displayName": "Display Name",
    "_sipPassword": "Password"
   );
  if (typeof exports !== 'undefined')  
    exports.language = lang;
   
 ());
So far I included all the labels I used in my Sip Account form. If you write the wrong label (key) or forget to include a corresponding key-value pair in strings.js, xTuple will simply name your lable _lableName , underscore and all. Now build your extension and start up the server:
$ cd /path/to/xtuple 
$ ./scripts/build_app.js -d dev -e ../xtuple-extensions/source/sip_account
$ node node-datasource/main.js
If the server is already running, just stop it and restart it to reflect your changes. Now if you go to Setup > User Accounts and click the + button, you should see a nice little addition to the form with a Sip Account divider and three new fields. Nice, eh? Extend Parameters Currently you can search your User Accounts list using any of the User Account fields. It would be nice to be able to search with the Sip account fields we added as well. To do that, let s create the directory /path/to/xtuple-extensions/source/sip_account/client/widgets and there create the file parameter.js to extend XV.UserAccountListParameters. One again, you ll have to look this up. In the xTuple code you ll find the application s parameter.js in /path/to/xtuple/enyo-client/application/source/widgets. Search for the business object you are extending (for example, XV.UserAccount) and look for some combination of the business object name and Parameters . If there s more than one, try different ones. Not a very refined method, but it worked for me. Here s the content of our parameter.js:
XT.extensions.sip_account.initParameterWidget = function ()  
  var extensions = [
     kind: "onyx.GroupboxHeader", content: "_sipAccount".loc() ,
     name: "uri", label: "_uri".loc(), attr: "uri", defaultKind: "XV.InputWidget" ,
     name: "displayName", label: "_displayName".loc(), attr: "displayName", defaultKind: "XV.InputWidget" 
  ];
  XV.appendExtension("XV.UserAccountListParameters", extensions);
 ;
Node that I didn t include a search field for the password attribute for obvious reasons. Now once again, we package this new code addition by creating a /path/to/xtuple-extensions/source/sip_account/client/widgets/package.js file:
enyo.depends(
"parameter.js"
);
We also have to update /path/to/xtuple-extensions/source/sip_account/client/package.js:
enyo.depends(
"core.js",
"widgets"
"views"
);
Rebuild the extension (and restart the server) and go to Setup > User Accounts. Press the magnifying glass button on the upper left side of the screen and you ll see many options for filtering the User Accounts, among them the SIP Uri and Display Name. Extend List View You might want your new fields to show up on the list of User Accounts. There s a bit of an issue here because unlike what we did in workspace.js and parameter.js, we can t append new things to the list of UserAccounts with the funciton XV.appendExtension(args). First I tried overwriting the original UserAccountList, which works but it s far from ideal as this could result in a loss of data from the core implementation. After some discussion with the xTuple dev community, now there s a better alternative: Create the file /path/to/xtuple-extensions/source/sip_account/client/views/list.js and add the following:
1 var oldUserAccountListCreate = XV.UserAccountList.prototype.create;
2 
3 XV.UserAccountList.prototype.create = function ()  
4   oldUserAccountListCreate.apply(this, arguments);
5   this.createComponent(
6    kind: "XV.ListColumn", container: this.$.listItem, components: [
7         kind: "XV.ListAttr", attr: "uri" 
8    ] )
9  ;
To understand what I m doing, check out the XV.UserAccountList implementation in /path/to/xtuple/enyo-client/application/source/views/list.js the entire highlighted part. What we are doing is extending XV.UserAccountList through prototype-chaining ; this is how inheritance works with Enyo. In line 1 we create a prototype and in line 4 we inherit the features including original components array which the list is based on. We then create an additional component immitating the setup shown in XV.UserAccountList: An XV.ListColumn containing an XV.ListAttr, which should be placed in the XV.ListItem components array as is done with the existing columns (refer to implementation). Components can or should (?) have names which are used to access said components. You d refer to a specific component by the this.$.componentName hash. The components in XV.UserAccountList don t have names, so Enyo automatically names them (apparently) based on the kind name, for example something of the kind ListItem is named listItem. I found this at random after a lot of trial and error and it s not a bullet proof solution. Can be bettered. It s strange because if you encapsulate that code with
XT.extensions.sip_account.initList = function ()  
 //Code here
 ;
as is done with parameter.js and workspace.js (and in the xTuple tutorial you are supposed to do that with a new business object), it doesn t work. I have no idea why. This might be wrong or against xTuple coding norms; I will find out and update this post ASAP. But it does work this way. * shrugs * That said, as we ve created the list.js file, we need to ad it to our package by editing /path/to/xtuple-extensions/source/sip_account/client/views/package.js:
enyo.depends(
"list.js",
"workspace.js"
);
That s all. Rebuild the app and restart your server and when you select Setup > User Accounts in the web app you should see the Sip URI displayed on the User Accounts that have the Sip Account data. Add a new User Account to try this out.

Next.

Previous.