Everything about Domino, PHP and other programming languages

CMS MS: Newsletter Made Simple, export user status

Ferdi Verlaan  September 28 2015 11:55:41
Following up a feature request from one of our customers in the Newletter Made Simple (NMS) module for CMS Made Simple.
Our customer wanted to export the status of the newletter users, but by default, only the email and username fields are exported.
We've found a similar request on

Since we don't have the time to create another sponsorship for CMS MS and wait until calguy1000 has time to change the code, since he is very busy with CMS MS 2.0. Please look at the following:
Change the following file:

around line 56 add the green fields for the headers:

$cols = array('email','username','disabled','confirmed');

around line 131 add the green fields for the export:

 // export everything
 while( !$u_dbr->EOF ) {
   $row = $u_dbr->fields;
   $uid = $row['userid'];
   $fields = array();
   $fields[] = $row['email'];
   $fields[] = $row['username'];

   $fields[] = $row['disabled'];

   $fields[] = $row['confirmed'];

    Bookmark and Share

Removing files and subdirectories from filesystem with lotusscript

Ferdi Verlaan  October 27 2014 12:09:26
We are working on a PHP / Domino hybrid mobile web application. We will post some more information about it in the near future. We need PHP since we are sending out POST commands via the HTML5 file API. A Notes Agent is not capable of understanding these requests (via the normal session.request_content for example), and therefor we need PHP. It would also be possible by xPages and JAVA I assume, but PHP easier for us.

The PHP script is called asynchronous and uploads resized images to c:\php\files\<UniqueID>. A webQuerySave agent processes the newly saved NotesDocument and fetches all documents from this subfolder and attachs them to the RichTextItem.

The cleanup of these files is done by a cleanup Agent, not in the WQS agent, to have some fallback in case of errors. We run this agent every weekend to remove all uploaded files.

Cleanup Agent code:


globalPath As string
       globalPath =
Call ScanDirs( globalPath )
' ==========================================================

' @FUNCTION: ScanDirs

' @AUTHOR: f.verlaan@aashq.nl
' @DATE: 27-10-2014


' Loops through the given path and removes all files

' and subfolders.

' based upon:
' ==========================================================

ScanDirs(path As String)
On Error GoTo catch
On Error 5 Resume next
Dim sess As New NotesSession
Dim DirList As Variant
Dim filename As String
Dim filepath As String
Dim sep As String
If path <> "" Then

If InStr(sess.Platform, "Windows") > 0 Then
                       sep =
                       sep =
End If
ReDim DirList(0)
If InStr(path, sep) > 0 Then
                       filepath =
StrLeftBack(path, sep)
End If
               filename =
Dir(path & "*", 16)
While filename <> ""
If filename <> "." And filename <> ".." Then
If (GetFileAttr(filepath & sep & filename)= 16) Then
                                       DirList =
ArrayAppend(DirList,filepath & sep & filename & sep)
' remove file
Kill filepath & sep & filename
End If
End If
                       filename =
                       ' if filename is empty and filepath is not the starting folder, delete subfolder
If filename = "" Then
If filepath <> StrLeftBack(globalPath, sep) Then
RmDir filepath        
End If
End If
               DirList =
ForAll dirpath In DirList

End ForAll
End If
Exit sub

Print "Error " & Err & " in " & GetThreadInfo(1) & " on line " & Erl & " - " & Error
Exit sub

Make sure that the security setting for the agent is set to 3 to allow restricted operations.

    Bookmark and Share

CMS Made Simple: get the Newsletter Made Simple (NMS) module to send out attachments

Ferdi Verlaan  August 27 2014 18:15:38
We have a customer who sends out newsletters as an PDF attachment. NMS is capable of sending these attachments within the module itselve, but only from the root. In this case we would like to use the /uploads/pdf folder.

My workaround for the attachment dir bug;

Open /modules/CGExtensions/CGExtensions.module.php:

locate the function 'CreateFileDropdown' and change the code to:

 * A convenience function to create a file dropdown
function CreateFileDropdown($id,$name,$selectedfile='',$dir = '',$extensions =
'',$allownone = '',$allowmultiple = false,$size = 3)
  $config = cmsms()->GetConfig();

  if( startswith( $dir, '.' ) ) $dir = '';
  if( $dir == '' ) $dir = $config['image_uploads_path'];
  if( !is_dir($dir) ) $dir = cms_join_path($config['uploads_path'],$dir);

if( $extensions == '' ) $extensions =

  $tmp = cge_dir::get_file_list($dir,$extensions);
  $tmp2 = array();
  if( !empty($allownone) ) $tmp2[$this->Lang('none')] = '';
  $filelist = array_merge($tmp2,$tmp);

  if( $allowmultiple ) {
    if( !endswith($name,'[]') ) $name .= '[]';
    return $this->CreateInputSelectList($id,$name,$filelist,array(),$size);
  return $this->CreateInputDropdown($id,$name,$filelist,-1,$selectedfile);

In /modules/NMS/action.compose.message.php; locate the string 'case:
'attachment'' and replace complete section with:

case 'attachment':
              // a file selector dropdown?
              $content = '';
              if( isset($blockvalues[$safe_name]) ) {
                  $content = $blockvalues[$safe_name];
              if( isset($params[$obj->name]) ) {
                  $content = trim($params[$obj->name]);
              //$cgextensions = $this->GetModuleInstance('CGExtensions');
//$obj->control =
                                  $dir = '';
              if( isset($keyval['dir']) ) {
                   $dir = $keyval['dir'];
                   $obj->dir = $dir;
              $cgextensions = $this->GetModuleInstance('CGExtensions');
$obj->control =


Now the dir function works, only relative to the /uploads folder, but works
nevertheless. Make sure in the CGExtensions module that the extension is allowed
to be uploaded/used.
And to make it work with sending the newsletter don't forget the following in /modules/NMS/NMS.modules.php locate the code:

  foreach( $this->attached_files as $onefile ) {
                echo $onefile;
      $fn = cms_join_path($config['uploads_path'],$onefile);

I've just manually changed the path to the path i need, for example:

  foreach( $this->attached_files as $onefile ) {
                echo $onefile;
      $fn = cms_join_path($config['uploads_path'].'/PDF',$onefile);

    Bookmark and Share

Import folders with files into your Domino webapplication with the Package Explorer

Ferdi Verlaan  August 8 2014 12:40:18
If you are working with web/mobile frameworks like jQuery and jQuery Mobile, it would be great if you could just import the whole tree of files into the Domino Designer for your web application. Otherwise you will have to change the .css filepaths to images or fonts for example. There is a neat little trick in the Domino Designer for that:

In your Domino go to Window > Show Eclipse Views > Package Explorer
Image:Import folders with files into your Domino webapplication with the Package Explorer

You can see a tree-like overview of your database, goto the folder 'WebContent' and then right-click on the WebContent folder and select 'Import'
Image:Import folders with files into your Domino webapplication with the Package Explorer

In the dialog select 'File System' and press 'Next'

Image:Import folders with files into your Domino webapplication with the Package Explorer

Select the folder which you want to import, select 'Create selected folders only' and 'Press Finish'
Image:Import folders with files into your Domino webapplication with the Package Explorer

You will now have a nice folder structure available for your Domino webapplication.

Image:Import folders with files into your Domino webapplication with the Package Explorer
    Bookmark and Share

CMS Made Simple: append search body to results

Ferdi Verlaan  April 16 2014 12:02:24
Besides Domino work, we do a lot of other programming languages. One of them is creating websites with PHP, with CMS Made Simple. A very completed, yet easy to use, Content Management System. In this post we will explain how to display search results with the body of the page.

We use the embedded 'Search' module of CMS Made Simple.

'Extensions > Search -> Result template'

Image:CMS Made Simple: append search body to results

We change the code to:

<h3>Search results for &quot;{$phrase}&quot;</h3>

{if $itemcount > 0}

 {foreach from=$results item=entry}

       <p><b>{$entry->title} ({$entry->weight}%)</b>

{getSearchBody url=$entry->url length=50}
       <br/><a href="{$entry->url}">{$entry->urltxt}</a>



<p>{$timetaken}: {$timetook}</p>




the 'getSearchBody' is a UDT, a user defined tag. We create this at 'Extensions > User Defined Tags'.

Create a new one with the name 'getSearchBody' and put the following code in:

/** Get page ID from Page URL -Create Search Body

* @params string $params['url']
* @params string $params['length']

$gCms = cmsms();

$contentops =& $gCms->GetContentOperations();

$db = $gCms->GetDb();

foreach ($contentops->GetAllContent() as $page) {

       if ($page->GetURL() == $params['url']) {
               $cid = $contentops->GetPageIDFromAlias( $page->Alias() );

               $rid = $db->GetOne('select content from '.cms_db_prefix().'content_props where content_id='.$cid.' and prop_name = "page"');

               if ($rid == "") {

                       $string = $db->GetOne('select content from '.cms_db_prefix().'content_props where content_id='.$cid.' and prop_name = "content_en"');

               } else {

                       $string = $db->GetOne('select content from '.cms_db_prefix().'content_props where content_id='.$rid.' and prop_name = "content_en"');


               if($string == "<p><br /><!-- Add code here that should appear in the content block of all new pages --></p>

                       <p> </p>") {

                       $string = $db->GetOne('select content from '.cms_db_prefix().'content_props where content_id='.$cid.' and prop_name = "content_en"');


               $string = strip_tags($string);

               $words = explode(' ', $string);

               if ($length ="") {

                       $length = 45;


               if (count($words) > $length) {

                       return implode(' ', array_slice($words, 0, $length))."...";
               } else {

                       return $string;


The end result is something similar like:

Image:CMS Made Simple: append search body to results

    Bookmark and Share