martedì 22 marzo 2011

SQLServer - istruzione POWER

Recentemente mi e' capitato di dover cercare in una tabella "users" di SQLServer gli utenti con delle autorizzazioni specifiche (esempio 3 e 4).

Ad esempio,
la tabella users potrebbe essere cosi' configurata:

id int: id utente
name varchar(255): nome utente
auth int: autorizzazione


...e con il seguente contenuto:

idnameauth
1Mario3(00001000)
2Luigi4(00010000)
3Toad5(00100000)

In questi casi e' da evitare la select di tutti i record (select * from users) e il successivo controllo dei singoli bit via codice.
La soluzione invece piu' razionale prevede una select in grado di estrarre i soli record che hanno i bit che ci interessano impostati a 1.

In questi casi lo statement POWER e' l'istruzione che fa al caso nostro e la seguente istruzione sql e' quella che ci serve:

SELECT id, name, auth FROM users WHERE (POWER(2, ISNULL(auth, 0)) & 24 != 0)


Una volta eseguita visualizzera' il seguente risultato:

idnameauth
1Mario3
2Luigi4

Istruzioni per creare la tabella:
CREATE TABLE [dbo].[users]( [id] [int] IDENTITY(1,1) NOT NULL, [name] [varchar](50) NOT NULL, [auth] [int] NULL, CONSTRAINT [PK_users] PRIMARY KEY CLUSTERED ( [id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY]

LeadingZero - aggiungere degli zeri in testa ad una stringa

Questa funzione aggiunge degli zeri "0" in testa ad un stringa fino al raggiungimento di una lunghezza prefissata:


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Push "12345"
; Push 8
; Call LeadingZero
; Pop $0
; DetailPrint "result: $0" ; 00012345
Function LeadingZero
Exch $R2 ; zero
Exch
Exch $R1 ; number
Push $R0 ; result
Exch 2
Push $R3
StrCpy $R0 $R1

Loop:
StrLen $R3 $R0
${If} $R3 >= $R2
GoTo Exit
${ElseIf} $R3 > 32 ; exit if is more of 32 len
GoTo Exit
${EndIf}
StrCpy $R0 "0$R0"
GoTo Loop

Exit:
Pop $R3
Pop $R2
Pop $R1
Exch $R0
FunctionEnd

!macro LeadingZero Res Num Zero
Push "${Num}"
Push "${Zero}"
Call LeadingZero
Pop "${Res}"
!macroend

!define LeadingZero "!insertmacro LeadingZero"

venerdì 18 marzo 2011

Editare un pdf

Cosa fare quando ci viene chiesto di scaricare un modulo pdf di compilarlo e di spedirlo via email. Ma questo una volta aperto con Acrobat Reader non ci permette di fare alcuna modifica?

Non ho ne stampante e ne scanner, che fare?
In questi casi Open Office ha un'estensione gratuita che si chiama PDF Import, questa una volta installata permette di convertire un pdf nel formato odt (word di openoffice).

Quindi quello che dobbiamo fare e' installare l'ultima versione di OpenOffice e procedere con l'installazione dell'estensione pdfimport.

Questi sono i link:
OpenOffice: OpenOffice
PDF Import: PDF Import extension

A questo punto non ci rimane che importare il pdf che apparira' in Draw (Word di OpenOffice) come un documento editabile, una volta modificato sara' possibile salvarlo nuovamente come pdf!

mercoledì 12 gennaio 2011

Conversione numerica da/a qualsiasi base

Riporto il codice autocostruito per NSIS al fine di eseguire delle conversioni numeriche da base decimale a qualsiasi altra base compresa tra 2 e 36.


Function DecToBX
Exch $R2 ; base
Exch
Exch $R1 ; number
Push $R0
Exch 2
Push $R3
StrCpy $R0 "" ; result

Loop:
System::Int64Op $R1 % $R2
Pop $R3

StrCpy $R3 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" 1 $R3
StrCpy $R0 "$R3$R0"

System::Int64Op $R1 / $R2
Pop $R1

StrCmp $R1 0 0 Loop

Pop $R3
Pop $R2
Pop $R1
Exch $R0
FunctionEnd

!macro DecToBX Res Num Base
Push "${Num}"
Push "${Base}"
Call DecToBX
Pop "${Res}"
!macroend

!define DecToBX "!insertmacro DecToBX"


Di seguito il codice per fare l'operazione inversa, ovvero convertire un numero da qualsiasi base numerica in decimale:


Function BXToDec
Exch $R2 ; base
Exch
Exch $R1 ; number
Push $R0 ; result
Exch 2
Push $R3
StrCpy $R0 0

Loop:
StrCpy $R3 $R1 1 0
${IndexOf} $R3 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" $R3
System::Int64Op $R0 * $R2
Pop $R0 ; vale -1 in caso di errore
System::Int64Op $R0 + $R3
Pop $R0
StrCpy $R1 $R1 "" 1
StrCmp $R1 "" 0 Loop

Pop $R3
Pop $R2
Pop $R1
Exch $R0
FunctionEnd

!macro BXToDec Res Num Base
Push "${Num}"
Push "${Base}"
Call BXToDec
Pop "${Res}"
!macroend

!define BXToDec "!insertmacro BXToDec"


La funzione BXToDec fa uso della macro IndexOf il cui codice si puo' recuperare dal seguente link: IndexOf source code

Esempio di utilizzo:

${DecToBX} $R0 0xF58DE 36 ; return LK2M
DetailPrint "result: $R0"

${BXToDec} $R0 "LK2M" 36 ; return 1005790 (0xF58DE)
DetailPrint "result: $R0"


Incrociano le due funzioni e' possibile fare una conversione da qualsiasi base numerica, ad esempio da base 16 a base 36:

${BXToDec} $R0 "F58DE" 16 ; return 1005790
${DecToBX} $R0 $R0 36 ; return LK2M
DetailPrint "result: $R0"


Entrambe le funzione non fanno alcun controllo sui parametri, ad esempio che la base sia nel range compreso tra 2 e 36.

Per verificare il risultato potete usare questo link: http://www.translatorscafe.com/cafe/units-converter/numbers/calculator/decimal-to-base-36

martedì 11 gennaio 2011

Aggiungere il supporto SourceSafe a PhpED

Deciso! Metto tutto su SourceSafe cosi' non mi rompo piu' le scatole a sincronizzare le modifiche dei sorgenti php. Il problema e' riuscire ad integrare SS con PhpED, l'ide che al momento e' in cima ai miei preferiti, anche se c'e' stato qualche vano tentativo di passare ad Eclipse.

Accedere alle variabili di ambiente di Windows e aggiungere alla PATH delle "Enviroment Variables -> System Variable" il percorso di installazione di SourceSafe, dove all'interno del folder dovra' essere presente il comando ss.exe:
C:\Program Files (x86)\Microsoft Visual SourceSafe;

Sempre nelle "Enviroment Variables -> System Variable" di Windows creare la voce SSDIR ed assegnarvi il percorso del file "srcsafe.ini", nel mio caso si trovava su un server in rete, quindi nel mio caso ho fovuto assegnarvi un indirizzo di questo tipo:
\\server_sourcesafe\Progetti\VSS

NB: e' possibile che prima di utilizzare PhpED per fare il CheckOut/CheckIn dei file di progetto si debba accedere alla cartella (SSDIR) via file system inserendo le credenziali se richieste.

Una volta preparate le due variabili di ambiente non ci rimane che aggiungere le voci di menu all'interno di PhpED:
- Selezionare Tools -> Settings -> Integration
- Premere il pulsante Add Menu, quindi editare il nome che si vuole dare alla nuova voce di menu contestuale. Per il checkout ho utilizzato "Check Out".
- Selezionare la voce di menu "Check Out" e premere Edit, quindi selezionare la voce Shell nella 'Execute with' e inserire come command line:
ss Checkout "$/SourceSafeProjectPath@RelFName@" -GL@Path@, dove '$/SourceSafeProjectPath' si riferisce al path del progetto in SS (valore adiacente alla label 'name' nelle proprieta' del progetto SS)
- Infine nelle opzioni selezionare 'Show this command in Workplace popup' e 'for files'

Proseguire aggiungendo le altre voci di menu "Check In" e "Undo Check Out" ripetendo i passi precedenti e evendo cura di modificare il comando di shell a seconda dei casi.
Qui sotto sono brevemente elencati i comandi SourceSafe in base alle funzionalita':

Check Out
ss Checkout "$/SourceSafeProjectPath@RelFName@" -GL@Path@

Check In
ss Checkin "$/SourceSafeProjectPath@RelFName@" -GL@Path@ -C

Undo Check Out
ss Undocheckout "$/SourceSafeProjectPath@RelFName@" -GL@Path@


Per conoscere i comandi riconosciuti da ss.exe fare riferimento al seguente link:
http://msdn.microsoft.com/en-us/library/003ssz4z%28v=vs.80%29.aspx

Mentre per le variabili contestuali utilizzabili nelle macro di PhpED, aprire l'help e andare alla seguente pagina:
Contents -> Customized PhpED -> Type of handlers and macros

mercoledì 29 dicembre 2010

Creare una feature per il deploy delle liste SharePoint

Ci sono diversi metodi per fare il deploy di una lista:
- salvare la lista come list template direttamente dall'interfaccia di SharePoint.
- scrivere una feature affinche' costruisca la lista interamente via codice.
- realizzare una feature definita "list definition".

Per un lavoro veloce le list defintion sono da preferirsi, non occorre scrive codice e non presentano il problema legato alla perdita dei riferimenti alle liste di lookup, come invece accade con le list template.

Per generare la feature possiamo utilizzare il tool "SharePoint Solution Generator", installato con il package "Visual Studio 2008 Extensions v1.3".



quindi selezionare l'icona 'List Definition', il site dove si trovano le liste, le liste che vogliamo esportare e infine confermare il salvataggio.


Il salvataggio crea per ogni lista una cartella, alcuni dei file contenuti in queste cartelle dovranno essere modificati per adattarli alle nostre esigente, questi sono: schema.xml e listdefinition.xml

Una delle modifiche prevede la riassegnazione delle liste di lookup, quindi dobbiamo aprire il file schema.xml e sostituire tutti gli attributi List dei Field di tipo Lookup o LookupMulti (rapresentati da dei guid) con il path della lista di lookup, ad esempio:

<Field Type="Lookup" List="Lists/LOOKUP_LIST"
<Field Type="LookupMulti" List="Lists/LOOKUP_LIST"


Un'altra modifica prevede l'assegnazione di un codice numerico univoco alla proprietà Type dello schema.xml e del file ListDefinition.xml, ad esempio: 10000.

Per chi fosse interessato alla descrizione degli elementi presenti nel file schema.xml puo' dare un'occhiata al seguente link: List Schema Elements


Se avete la necessita' di fare il deploy di una lista con il suo contenuto, potete usare il tool SPListInstanceGenerator che ho realizzato per esigenze personali (in fondo all'articolo e' possibile farne il download). Questo tool crea il file ListInstance.xml che andra' poi sostituito a quello presente nella cartella della lista corrispondente.
Il file xml generato dal tool non e' ben formattato, per cui prima di procedere consiglio sempre di riformattarne il contenuto. Procedere quindi caricando l'xml in Visual Studio, riformattare il file utilizzando la combinazione di tasti CTRL+A (per selezionare l'intero contenuto), CTRL+K e CTRL+F e infine salvare il file senza cambiarne il nome.
Se poi il contenuto dell'xml dovesse contenere dei caratteri speciali dovrete aver cura di incapsularli tra i seguenti tag:

<![CDATA[
...
]]>



Ci siamo quasi, una volta che le liste sono state definite non ci resta che aggiungere il file feature.xml al progetto, questo file infatti dice cosa e dove andrà installata la feature, e infine compilare il pacchetto wsp.

Il pacchetto wsp da utilizzarsi per il deploy puo' essere generato a mano editando un file ddf, il manifest e infine costruendo il file cab con il tool makecab, questo file non e' altro che un wsp.
In alternativa e' possibile installare il tool WSPBuilder e creare il progetto della feature direttamente da Visual Studio 2008.


Download:
Visual Studio 2008 Extensions v1.3
WSPBuilder
SPListInstanceGenerator

sabato 25 dicembre 2010

Accedere agli oggetti SharePoint con i privilegi alzati

Alzare i privilegi di SharePoint da codice per poter eseguire delle operazioni altrimenti non consentite in forma anonima è possibile utilizzando il seguente codice C#:

SPSecurity.RunWithElevatedPrivileges(() =>
{
using (SPSite site = new SPSite(siteUrl))
{
using (SPWeb web = site.OpenWeb())
{
// Qui si possono usare gli oggetti site e web con i privilegi alzati
...
}
}
});


Se si vuole aprire il root web utilizzare invece questa istruzione:

using (SPWeb rootWeb = site.OpenWeb(site.RootWeb.ID))


Nell'esempio si è creato l'SPSite e si è aperto il SPWeb utilizzando l'istruzione using in modo da avere il dispose automatico una volta usciti dallo scope.

Il codice sopra usa una lambda expression (=>), se invece si desidera utilizzare il metodo standard la sintassi è la seguente:

SPSecurity.RunWithElevatedPrivileges(delegate()
// ....
});


non credo che ci siano sostanziali differenze tra i due metodi, è comunque consigliato farne l'abitudine visto che con SharePoint 2010 verranno utilizzate le espression lambda al posto delle query CAML per leggere dalle liste.

Per utilizzare il metodo lambda basta includere il seguente namespace:

Microsoft.SharePoint.Linq namespace