I am hoping someone can put me out of my misery here. I rewrote a LotusScript function in JavaScript and it is not working as it should be. I can't look at this thing anymore. I"m hoping someone can help me figure this out.
The function takes a name of a group and an address book db object. It fetches and returns all the members of that group including nested groups. It works great in the Lotusscript version but not in the Javascript version. It's something to do with the recursive function and the index into the array's.
If you create two groups. Put 10 names in the first group and 5 names in the second group. Note, Name the second group with a leading # to make it sort to the top of the first group
group-A
1group-A
bla
bla2
bla3
bla4
bla5
bla6
bla7
bla8
bla9
bla10
1group-A
other1
other2
other3
other4
other5
In the Javascript version when you pass the function group-A it returns 10 names. Five from the second group and the second five from the first group.
Here is the code for the lotusscript version
Function LibGetGroupMembers( groupName As String, addressBook As NotesDatabase ) As Variant
' This Function takes a passed in group name and gets all the members of that group.
' Not a big whoop until you consider nested group names. This is a recursive routine.
'
' Inputs : Name of the group to fetch the members of.
'
' Uses : Global objects
'
' Outputs : Returns an array of members
'
' History:
' 02.19.2001 - Steven Rieger : Created Function.
Dim groupView As NotesView
Dim groupMainDoc As NotesDocument
Dim groupMembers As Variant
Dim nestedGroupMembers As Variant
Dim arrayOfMembers() As String
Dim mainIndex As Integer
Dim nestedIndex As Integer
Dim resultIndex As Integer
On Error Goto ErrorHandling
gLibObjectName = CStr( GetThreadInfo(1) ) & " - " & gLibDatabaseNamePath
gLibErrorMessage = "Begin " & gLibObjectName
Call LibLogErrorPushCallingPgm ( gLibErrorMessage )
Print( gLibErrorMessage )
gLibAdditionalErrorMessage = "Fetching Group View From NAB"
Set groupView = addressBook.GetView( "($VIMGroups)" )
If( groupView Is Nothing ) Then
Call LibLogError( "Error: Un-able to get view from address book", gLibErrorMessage )
Exit Function
End If
gLibAdditionalErrorMessage = "Fetching Group Main Document " & groupName
Set groupMainDoc = groupView.GetDocumentByKey( groupName, True )
resultIndex = 0
Redim arrayOfMembers( 0 )
' Did we find a matching group document?
If Not( groupMainDoc Is Nothing ) Then
If Not( Iselement ( gListOfGroupNames( Lcase( groupName ) ) ) ) Then
' Print( "Processing Group: " & groupName )
gListOfGroupNames( Lcase( groupName ) ) = " "
groupMembers=groupMainDoc.GetItemValue( "Members" )
For mainIndex = Lbound( groupMembers ) To Ubound( groupMembers)
nestedGroupMembers= LibGetGroupMembers( groupMembers( mainIndex ), addressBook )
If( nestedGroupMembers(0) = "" ) Then
If( groupMembers( mainIndex ) <> "" ) Then
Redim Preserve arrayOfMembers( Ubound( arrayOfMembers ) + 1)
arrayOfMembers( resultIndex ) = groupMembers( mainIndex )
resultIndex = resultIndex + 1
End If
Else
Redim Preserve arrayOfMembers( Ubound( nestedGroupMembers ) + resultIndex )
For nestedIndex = Lbound( nestedGroupMembers ) To Ubound( nestedGroupMembers )
arrayOfMembers( resultIndex ) = nestedGroupMembers( nestedIndex )
resultIndex = resultIndex + 1
Next
End If
Next
If( arrayOfMembers( Ubound( arrayOfMembers ) ) = "" And Ubound( arrayOfMembers ) > 0 ) Then
Redim Preserve arrayOfMembers( Ubound( arrayOfMembers ) - 1 )
End If
Else
groupName = "*** Circular Group: " & groupName & " ***"
End If
End If
LibGetGroupMembers = arrayOfMembers
Goto Bye
ErrorHandling :
Call LibLogError( "Error: " & Err( ) & ": " & Error( ) & Chr( 13 ) & Chr( 13 ) & "Occured in Module " & CStr( GetThreadInfo(1) ) & " at Line Number: " & Erl(), CStr( GetThreadInfo(1) & " - " & gLibDatabaseNamePath ) )
Resume Bye
Bye:
gLibAdditionalErrorMessage = "End " & CStr( GetThreadInfo(1) & " - " & gLibDatabaseNamePath )
' This will pop the last entry of the stack!
Call libLogErrorPopCallingPgm()
Print( gLibAdditionalErrorMessage )
End Function
HERE IS THE CODE FOR THE JAVASCRIPT FUNCTION
function jsLibGetGroupMembers( groupName:string, addressBook:NotesDatabase )
{
// This Function takes a passed in group name and gets all the members of that group.
// Not a big whoop until you consider nested group names. This is a recursive routine.
//
// Inputs : Name of the group to fetch the members of.
//
// Uses : Global objects
//
// Outputs : Returns an array of members
//
// History:
// 02.19.2001 - Steven Rieger : Created Function.
var groupView:NotesView;
var groupMainDoc:NotesDocument;
var groupMembers:java.util.Vector;
var nestedGroupMembers = new Array();
var arrayOfMembers = new Array();
var mainIndex:Integer;
var nestedIndex:Integer;
var resultIndex:Integer;
print( "Begin jsLibGetGroupMembers - Passed in Name: " + groupName );
groupView = addressBook.getView( "($VIMGroups)" )
if( groupView == null )
{
print( "group document not found!" );
return nestedGroupMembers;
}
// gLibAdditionalErrorMessage = "Fetching Group Main Document " & groupName
groupMainDoc = groupView.getDocumentByKey( groupName, true )
resultIndex = 0
// Did we find a matching group document?
if( groupMainDoc != null )
{ // is the group name already in the global list of groups?
if( !(groupName.toLowerCase() in gListOfGroupNames ) )
{
// Add the group name to the globla list of groups to prevent processing duplicate groups
gListOfGroupNames[ groupName.toLowerCase() ] = " "
groupMembers = groupMainDoc.getItemValue( "Members" );
for( groupMemberIndex = 0; groupMemberIndex < groupMembers.length; groupMemberIndex++ )
{
// Fetch any nested group members if the current member is a group name
nestedGroupMembers = jsLibGetGroupMembers( groupMembers[groupMemberIndex], addressBook );
if ( typeof nestedGroupMembers[0] === 'undefined' || nestedGroupMembers[0] === null )
{
// If no group was found and we have an actual member name add it to the list.
if( groupMembers[groupMemberIndex].length > 0 )
{
print( "adding user to array: " + groupMembers[groupMemberIndex] + " resultIndex = " + resultIndex );
arrayOfMembers[resultIndex] = groupMembers[groupMemberIndex];
resultIndex += 1;
}
else
{
print( "No User to Add!");
}
}
else
{
// If this was a nested group we found add the members of that group to the list
for( nestedGroupMemberIndex = 0; nestedGroupMemberIndex < nestedGroupMembers.length; nestedGroupMemberIndex++ )
{
print( "adding nested user to array: " + nestedGroupMembers[nestedGroupMemberIndex] + " resultIndex = " + resultIndex );
arrayOfMembers[ resultIndex ] = nestedGroupMembers[nestedGroupMemberIndex];
resultIndex += 1;
}
}
}
}
else
print( "Duplicate Group!");
}
else
{
print( "no group doc found!" );
}
print( "exiting jsLibGetGroupMembers: " + "\n" + arrayOfMembers );
return arrayOfMembers;
}
This answer will no doubt seem ironic given my recent blog post, but here's an SSJS implementation that will return a sorted list of all members of a group hierarchy:
var AtFunctions = (function() {
function getGroupNames (groupRecord, serverName) {
var result = new java.util.TreeSet();
if (groupRecord) {
for (var eachMember in groupRecord.getItemValue("Members")) {
var nestedGroupRecord = getGroupRecord(eachMember, serverName);
if (nestedGroupRecord) {
result.addAll(getGroupNames(nestedGroupRecord, serverName));
nestedGroupRecord.recycle();
} else {
result.add(eachMember);
}
}
}
return result;
}
function getGroupRecord (groupName, serverName) {
var result = null;
try {
serverName = (serverName || session.getServerName());
var NAB = session.getDatabase(serverName, "names.nsf");
var groupView = NAB.getView("($VIMGroups)");
result = groupView.getDocumentByKey(groupName, true);
} catch (e) {
print("Error getting group record: " + e.toString());
}
return result;
}
var API = {
expandNameList: function(groupName, serverName) {
var result = new java.util.TreeSet();
if (groupName) {
var groupRecord = getGroupRecord(groupName, serverName);
if (groupRecord) {
result.addAll(getGroupNames(groupRecord, serverName));
groupRecord.recycle();
}
}
return result;
}
};
return API;
})();
var #ExpandNameList = AtFunctions.expandNameList;
The variable alias at the end will allow you to treat this as a custom #Function, if desired, so you can call this one of two ways:
var groupMembers = #ExpandNameList("All Employees");
var groupMembers = AtFunctions.expandNameList("All Employees");
// in either syntax, you can optionally pass a server name as a second argument
NOTE: it's using the Java TreeSet class instead of JavaScript arrays, which has the following benefits:
It's automatically sorted. You might not want this, but for this
type of operation, it's often useful.
It automatically ignores duplicates, so you should only get one instance of each name even if the same member exists in multiple subgroups.
Syntactically, it's just so much easier to manipulate than an array.
Enjoy. :)
Related
I have the below Code which works, except for if there is a number in the text field so a single speech mark does not get added around say 1 but would be around one.
As an aside I don't want speechmarks on the first column (the ID value)
SEP = ", "
QUOTE = "\'"
NEWLINE = System.getProperty("line.separator")
KEYWORDS_LOWERCASE = com.intellij.database.util.DbSqlUtil.areKeywordsLowerCase(PROJECT)
KW_INSERT_INTO = KEYWORDS_LOWERCASE ? "insert into " : "INSERT INTO "
KW_VALUES = KEYWORDS_LOWERCASE ? ") values (" : ") VALUES ("
KW_NULL = KEYWORDS_LOWERCASE ? "null" : "NULL"
def record(columns, dataRow) {
OUT.append(KW_INSERT_INTO)
if (TABLE == null) OUT.append("MY_TABLE")
else OUT.append(TABLE.getParent().getName()).append(".").append(TABLE.getName())
OUT.append(" (")
columns.eachWithIndex { column, idx ->
OUT.append(column.name()).append(idx != columns.size() - 1 ? SEP : "")
}
OUT.append(KW_VALUES)
columns.eachWithIndex { column, idx ->
def value = dataRow.value(column)
def stringValue = value != null ? FORMATTER.format(dataRow, column) : KW_NULL
if (DIALECT.getDbms().isMysql())
stringValue = stringValue.replace("\\", "\\\\")
OUT.append(skipQuote ? "": QUOTE).append(stringValue.replace(QUOTE, QUOTE + QUOTE))
.append(skipQuote ? "": QUOTE).append(idx != columns.size() - 1 ? SEP : "")
}
OUT.append(");").append(NEWLINE)
}
ROWS.each { row -> record(COLUMNS, row) }
Not 100% sure what and why you are trying to achieve, but I would write down something like that in idiomatic groovy:
LinkedHashMap.metaClass.value = { delegate.get it } // mock value()
TABLE = [ parent:[ name:'OTHER_TABLE' ] ] // fake TABLE
KEYWORDS_LOWERCASE = true // false
KW_INSERT_INTO = 'INSERT INTO'
KW_VALUES = 'VALUES'
if( KEYWORDS_LOWERCASE ){
KW_INSERT_INTO = KW_INSERT_INTO.toLowerCase()
KW_VALUES = KW_VALUES.toLowerCase()
}
COLUMNS = [ 'a', 'nullllll', 'c', 'numberString' ]
String record(columns, dataRow) {
List values = columns.collect{
def v = dataRow.value it
switch( v ){
case Number:
case ~/\d+/: return v
case String: return "'$v'"
default: return 'null'
}
}
"$KW_INSERT_INTO ${TABLE?.parent?.name ?: 'MY_TABLE'} (${columns.join( ', ' )}) $KW_VALUES (${values.join( ', ' )});\n"
}
String res = record( COLUMNS, [ a:'aa', c:42, numberString:'84' ] )
assert res == "insert into OTHER_TABLE (a, nullllll, c, numberString) values ('aa', null, 42, 84);\n"
In switch statement the values are getting formatted.
You can try out yourself at https://groovyconsole.appspot.com/script/5151418931478528
So below you will see the code im using to iterate through a excel spreadsheet and find every row that contains x. For some reason not only does the operation STOP at the very last row and not finish the operation, allowing me to save my edits and close the handle to excel, but also seems to be skipping rows. It will go through, say 25k rows that need to be deleted, yet only delete 12.5k. Im sure im doing something simple wrong here, so im hoping a few sets of eyes on it can spot my mistake. My code:
void startOperation()
{
Console.WriteLine("Beginning start operations..." + searchText);
Console.WriteLine("Opening Workbook: " + filePath);
// create excel-instance:
Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
// open the concrete file:
Workbook xlWorkbook = xlApp.Workbooks.Open(#filePath);
//MessageBox.Show(filePath);
// select worksheet. NOT zero-based!!:
_Worksheet xlWorksheet = xlWorkbook.Sheets[1];
//MessageBox.Show(Convert.ToString(xlWorksheet.Name));
Microsoft.Office.Interop.Excel.Range range;
int numRows = xlWorksheet.UsedRange.Rows.Count;
numRowsDeleted = 0;
nullCounter = 0;
var percentageComp = new Decimal(.001);
//Parallel.For(1, numRows, new ParallelOptions { MaxDegreeOfParallelism = 1 }, i =>
for (currRow = 1; currRow <= numRows; currRow++)
{
percentageComp = ((decimal)currRow / (decimal)numRows) * 100;
Console.Clear();
Console.WriteLine("Number of Rows: " + numRows);
Console.WriteLine("Checking Row #: " + currRow);
Console.WriteLine("Number of Rows Deleted: " + numRowsDeleted);
Console.WriteLine("Percentage Comp: " + percentageComp.ToString("#.##"));
//Create Worksheet Range
range = (Microsoft.Office.Interop.Excel.Range)xlWorksheet.Cells[currRow, 2];
//MessageBox.Show(cellValue);
if (currRow == numRows)
{
closeOperation(xlApp, xlWorkbook);
break;
}
if (Convert.ToString(range.Value) != null) //if (cellValue != null || cellValue != "")
{
cellValue = Convert.ToString(range.Value);
//nullCounter = 0;
//MessageBox.Show("Cell Value: " + cellValue);
if (cellValue.Contains("MESSAGE NOT CONFIGURED"))
{
//MessageBox.Show("Cell Value: " + cellValue);
xlWorksheet.Rows[currRow].Delete(XlDeleteShiftDirection.xlShiftUp);
numRowsDeleted++;
//currRow++;
}
else
{
//currRow++;
}
}
else
{
//nullCounter++;
//currRow++;
}
//currRow++;
}
}
Again, your help is appreciated. Thanks!
I am able to read the table cells, But I wanted also to read the applied style name of each cell of a row in a table. How can I achieve this?
EDIT
Following is the code snip which I have tried. By this I am able to read cell text also the applied pstyle(para style), but not able to read the rstyles.
private static void processDoc(String path) throws Exception {
POIFSFileSystem fis = new POIFSFileSystem(new FileInputStream(path));
HWPFDocument wdDoc = new HWPFDocument(fis);
// list all style names and indexes in stylesheet
/*for (int j = 0; j < wdDoc.getStyleSheet().numStyles(); j++) {
if (wdDoc.getStyleSheet().getStyleDescription(j) != null) {
System.out.println(j + ": " + wdDoc.getStyleSheet().getStyleDescription(j).getName());
} else {
// getStyleDescription returned null
System.out.println(j + ": " + null);
}
}*/
// set range for entire document
Range range = wdDoc.getRange();
for (int i = 0; i < range.numParagraphs(); i++) {
Paragraph p = range.getParagraph(i);
// check if style index is greater than total number of styles
if (wdDoc.getStyleSheet().numStyles() > p.getStyleIndex()) {
//System.out.println(wdDoc.getStyleSheet().numStyles() + " -> " + p.getStyleIndex());
StyleDescription style = wdDoc.getStyleSheet().getStyleDescription(p.getStyleIndex());
String styleName = style.getName();
// write style name and associated text
System.out.println(styleName + " -> " + p.text().replaceAll("[\u0000-\u001f]", ""));
} else {
System.out.println("\n" + wdDoc.getStyleSheet().numStyles() + " ----> " + p.getStyleIndex());
}
}
}
recently, i tried to do some pig script with groovy, here is my code
def appID = ['pub000000', 'pub000004', 'pub000001', 'pub000004'] as Object[]
before :appInfo = new Object[4]
now: **def appInfo = ['info1','info2','info3','info4']**
for (int i = 0; i < appInfo.size(); i++) {
//Load all the related appInfo tables
pigServer.registerQuery("${appInfo[i]} = LOAD'hbase://Information.${appID[i]}' " +
"USING org.apache.pig.backend.hadoop.hbase.HBaseStorage('meta:number1 " +
"meta:number2') " +
"AS (number1:chararray, number2:chararray);")
}
pigServer.registerQuery("totalAppinfo = UNION ${appInfo[0]},${appInfo[1]},${appInfo[2]},${appInfo[3]};")
I worked it out finally, just to give the array the value.
Complete guess (never used piglatin), but does this work?
def appID = ['pub000000', 'pub000004', 'pub000001', 'pub000004']
appID.each { id ->
pigServer.registerQuery( "${id} = LOAD'hbase://Information.${id}' " +
"USING org.apache.pig.backend.hadoop.hbase.HBaseStorage('meta:number1 " +
"meta:number2') " +
"AS (number1:chararray, number2:chararray);")
}
pigServer.registerQuery("totalAppinfo = UNION ${appId.join(',')};")
Edit after update to question:
def appID = ['pub000000', 'pub000004', 'pub000001', 'pub000004']
def appInfo = ['info1','info2','info3','info4']
[appInfo,appID].transpose().each { info, id ->
pigServer.registerQuery( "${info} = LOAD'hbase://Information.${id}' " +
"USING org.apache.pig.backend.hadoop.hbase.HBaseStorage('meta:number1 " +
"meta:number2') " +
"AS (number1:chararray, number2:chararray);")
}
pigServer.registerQuery("totalAppinfo = UNION ${appInfo.join(',')};")
How is a password encoded or decoded in order to retrieve a password from an Adobe Dreamweaver *.ste file, or to dynamically create a *.ste file designed to be imported into Dreamweaver?
This Javascript function can be used to encode the password:
function encodePassword(input)
{
var top = 0;
var output = '';
for(var i = 0; i < input.length; i++){
var currentChar = input.charCodeAt(i);
if(currentChar < 0 || currentChar > 0xFFFF){return(false);}
if(top != 0){
if(0xDC00 <= currentChar && currentChar <= 0xDFFF){
output += dec2hex(0x10000 + ((top - 0xD800) << 10) + (currentChar - 0xDC00) + i) + '';
top = 0;
continue;
// Insert alert for below failure
}else{return(false);}
}
if(0xD800 <= currentChar && currentChar <= 0xDBFF){top = currentChar;}
else{output += dec2hex(currentChar + i) + '';}
}
return(output);
}
function dec2hex(input){return(input+0).toString(16).toUpperCase();}
And this function can be used to decode the password:
function decodePassword(input)
{
var output = "";
if(input.length == 0){return("");}
for(var i = 0; i < input.length / 2; i++){
var currentHex = parseInt(input.substr(i * 2, 2), 16);
if(currentHex <= 0xFFFF){
output += String.fromCharCode(currentHex - i);
}else if(currentHex <= 0x10FFFF){
currentHex -= 0x10000
output += String.fromCharCode(0xD800 | (currentHex >> 10)) + String.fromCharCode(0xDC00 | (currentHex & 0x3FF) - i);
}else{
//Insert alert for below failure
return(false);
}
}
return(output);
}
You can also do this online without any code using this tool: http://blog.affirmix.com/2009/05/05/live-ste-dreamweaver-password-encoder-and-decoder/
To decode the Dreamweaver password you break the password into pairs of hexadecimal (0-9, A-F) digits then subtract from each hex digit based on it's position in the string, starting with 0, then convert back to ascii.
The encrypted password of 5470714865787F would be...
54-0 = 54 => T
70-1 = 6F => o
71-2 = 6F => o
48-3 = 45 => E
65-4 = 61 => a
78-5 = 73 => s
7F-6 = 79 => y
So 5470714865787F => 'TooEasy'
We have a working example of this on our website which allows you to decode your password. You can also copy/paste your entire .ste file and it will output the needed FTP details to connect, save some time...
http://www.mywebsitespot.com/dreamweaver-password-decode
Sorry to wake up an old thread but thought I'd post my solution. It's a single HTML5 page that can load and parse Dreamweaver STE files, decoding the password as part of that. I wanted something simple, offline/local (so details aren't transmitted when decoding) that I could to just load an STE file in to and it would give me all the FTP details:
Blog Post:
http://bobmckay.com/web/dreamweaver-password-ste-file-decoder
Decoder Page:
http://bobmckay.com/dreamweaver-password-decoder/
Hope it's useful to someone!
Bob
Waking an old thread, but in addition to the accepted JavaScript answer, I just wanted to leave two PHP functions for anyone interested:
To encode a password:
function dwste_encode( $pw ){
$output = '';
$split = str_split( $pw );
foreach( $split as $key => $value ){
$char = ord( $value );
$char = ( $char + $key );
$char = dechex( $char );
$output .= strtoupper( $char );
}
return $output;
}
To decode a password:
function dwste_decode( $pw ){
$output = '';
$split = str_split( $pw, 2 );
foreach( $split as $key => $value ){
$char = hexdec( $value );
$char = ( $char - $key );
$char = chr( $char );
$output .= $char;
}
return $output;
}
I needed to create many DW ste files for a client today. I used the following VBA to do it straight from Excel. I used the code from #andrew-odri as the basis.
Function decodeDreamWeaverPass(sHash$)
Dim sPass$, i&, lHash&, lChar&, sChars$
lHash = Len(sHash) - 1
For i = 0 To lHash Step 2
sChars = Mid(sHash, i + 1, 2)
lChar = CLng("&H" & sChars)
lChar = lChar - (i / 2)
sPass = sPass & Chr(CLng(lChar))
Next
decodeDreamWeaverPass = sPass
End Function
Function encodeDreamWeaverPass(sPassword$)
Dim lTop&, i&, sOutput$
Dim lPassword&, sChar$, lChar&
lTop = 0
lPassword = Len(sPassword) - 1
For i = 0 To lPassword
lChar = Asc(Mid(sPassword, i + 1, 1))
sChar = Chr(lChar)
If ((lChar < 0) Or (lChar > 65535)) Then
encodeDreamWeaverPass = ""
End If
If lTop > 0 Then
If (lChar >= 56320) And (lChar <= 57343) Then
sOutput = sOutput & Hex(65536 + ((lTop - 55296) Xor 10) + (lChar - 56320) + i)
lTop = 0
Else
encodeDreamWeaverPass = ""
End If
End If
If (lChar >= 55296) And (lChar <= 56319) Then
lTop = lChar
Else
sOutput = sOutput & Hex(lChar + i)
End If
Next
encodeDreamWeaverPass = sOutput
End Function