venerdì 12 dicembre 2008

Response.Redirect in UpdatePanel Ajax

A volte può capitare di dover utilizzare la funzione Response.Redirect in un UpdatePanel... Spesso, però, questa funzione restituisce un errore. Questo (di solito) significa che in manca una parte della configurazione nel file web.config
Basterà infatti aggiungere

<httpModules>

<add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>

</httpModules>


e tutto funzionerà.

venerdì 5 dicembre 2008

Svuotare automaticamente le cartelle "Spam" e "Trash" su MDaemon

Accountpruner tool piuttosto potente di MDaemon, ma non sempre è quello piu facile da usare. Tenendolo a mente, qui ci sono alcune righe del mio file \MDaemon\App\midnight.bat che potrebbero essere utili. Questo file batch viene eseguito da MDaemon ogni notte a mezzanotte. (Se questo file non è presente, può tranquillamente essere creato a mano e MDaemon lo eseguirà).

c:\MDaemon\App\AccountPrune.exe /m /d=10 /p=”Spam.IMAP”
c:\MDaemon\App\AccountPrune.exe /m /d=10 /p=”Junk Mail.IMAP”
c:\MDaemon\App\AccountPrune.exe /m /d=10 /p=”Junk E-mail.IMAP”
c:\MDaemon\App\AccountPrune.exe /m /d=2 /p=”Trash.IMAP”
c:\MDaemon\App\AccountPrune.exe /m /d=2 /p=”Deleted Items.IMAP”
c:\MDaemon\App\AccountPrune.exe /m /d=2 /p=”Deleted Messages.IMAP”


Ovviamente se MDaemon è stato installato in un'altra directory, utilizzate nello script il percorso corretto.

Il risultato è che ogni notte a mezzanotte l'accountpruner di MDaemon verificherà in tutte le cartelle “Spam”, “Junk Mail” e “Junk E-Mail” di tutti gli utenti ed eliminerà tutti i messaggi più vecchi di 10 giorni.

Nelle cartelle “Trash”, “Deleted Items” e “Deleted Messages” verranno cancellati i messaggi più vecchi di 2 giorni. Combinando questo con le opzioni proprie dell'Accountpruner per eliminare anche i messaggi contrassegnati come eliminati, si avrà una soluzione completa, anche se il client email usa una cartella trash "dedicata", usa il flag di eliminazione di IMAP o usa entrambi i metodi.

Usare un NAS basato su Windows (NTFS) con VMware ESX

Qui sotto c'è la procedura competa per utilizzare un NAS basato su Windows (NTFS) come NFS per VMware ESX server.

I principali passaggi di questo processo sono:

  1. Installare Windows Services for UNIX (WSFU)

  2. Copiare i file delle password e dei gruppi da ESX Server a Windows

  3. Configurare WSFU in modo che accetti le connessioni da ESX Server

  4. Condividere la cartella di Windows con compatibilità NFS

  5. Configurare l'ESX Server per utilizzare la condivisione Window NFS come Datastore



1. Installare Windows Services for UNIX (WSFU)

Scaricare l'installazione di "Windows Services for UNIX" da:
http://www.microsoft.com/windowsserversystem/sfu/downloads/default.mspx

Installare WSFU sulla macchina che farà da NAS aggiungendo, se non già selezionate, le opzioni:
"NFS" e "Server for NFS"
"Authentication tools for NFS" e "User name mapping"
Dopo l'installazione, aprire la pagina dei servizi di windows e cambiare le impostazioni di "User Name Mapping" in modo da farlo partire automaticamente e startarlo (se non è già in esecuzione)


2. Copiare i file delle password e dei gruppi da ESX Server a Windows

Con un programmma come "WinSCP" o con un procedimento simile, copiare i seguenti file dal server ESX al server su cui è stato appena installato WSFU.
WinSCP è scaricabile da:
http://winscp.net/eng/download.php#download2
Traferire il file /ect/password ed il file /ect/group in C:\SFU (oppure nella cartella dove è stato installato WSFU)


3. Configurare WSFU in modo che accetti le connessioni da ESX Server

Andare su Start, Programmi, Windows Services for UNIX, Services for UNIX Administration
Andare su "User name mappings" e poi su "configuration"
Cliccare "password and group files"
Dalla finestra cercare ed indicare al programma i file di password e gruppi appena copiati.
Cliccare su "Apply" in altro a destra.
Andare su "maps"
Cliccare su "Show User Maps"
Poi "List Windows users" and "List Unix users"
Selezionare un utente amministratore locale sulla sinistra, sulla destra selezionare l'account di root.
Fatto questo, cliccare sul bottone "Add" per mappare i due utenti.
Alla fine cliccare su "Apply" (in alto a destra)



4. Condividere la cartella di Windows con compatibilità NFS

Tasto destro sulla cartella da condividere via NFS (se la cartella è già stata condivisa, probabilmente sarà necessario togliere la condivisione esistente).
Scegliere "Proprietà" e poi "NFS sharing".
Dare un nome alla condivisione, per esempio NFS-VMFS01
Rimuovere la spunta da "Allow anonymous access".
Cliccare "Permission"
Cambiare il tipo di accesso a "Read+Write" e poi mettere la spunta su "Allow root access".


5. Configurare l'ESX Server per utilizzare la condivisione Window NFS come Datastore

Aprire il Virtual Center client e selezionare l'host su cui creare il Datastore
Nella tab "Configure" scegliere "Networking"
Aggiungere una nuova configurazione per VMKernel e selezionare uno vSwitch, infine dare alla nuova interfaccia configurata un indirizzo che sia raggiungibile dal NAS.
Aprire, per questo host, le opzioni di storage.
Cliccare su "Add storage" e selezionare "Network File System".
Nel campo "Server" inserire il nome o l'indirizzo ip del server NAS a cui ci si deve collegare.
Nel campo "Folder"inserire il nome precedentemente assegnato alla condivisione, nell'esempio /NFS-VMFS01.
Infine, inserire il nome del Datastore (a piacimento).

Ora è possibile iniziare a creare le macchine virtuali sul nostro host utilizzando le risorse disco disponibili sul nas.

sabato 8 novembre 2008

Aggiungere utenti in Team Foundation Server

Dopo l'installazione di Team Foundation Server è necessario aggiungere utenti per poter operare sul server. Per impostazione predefinita, l'account utente utilizzato durante l'installazione viene aggiunto di default.

Tutte le edizioni di Team Foundation Server richiedono che gli utenti siano membri di un gruppo di Team Foundation Server a livello di progetto o server. Il livello e il gruppo dipendono dalle funzionalità che si desidera attivare per l'utente. Se ad esempio si desidera che un utente sia in grado di creare un progetto Team, l'utente deve disporre dell'autorizzazione Crea nuovi progetti impostata su Consenti, deve essere assegnato al ruolo di Gestione contenuto in SQL Server Reporting Services e al ruolo di Amministratore per Windows SharePoint Services. Non è tuttavia necessario che sia membro del gruppo di amministratori locali nel computer. Per ulteriori informazioni su utenti e ruoli, vedere l'argomento "Autorizzazioni di Team Foundation Server" nella guida dell'amministratore di Team Foundation Server.


Per aggiungere utenti a Team Foundation Server:
  1. Accedere come amministratore di Team Foundation, aprire Team Explorer e connettersi al server Team Foundation Server a cui si desidera aggiungere un utente.

  2. Scegliere Impostazioni di Team Foundation Server dal menu Team, quindi Appartenenza a gruppo.

  3. Nella finestra di dialogo Gruppi globali scegliere Utenti con licenza Team Foundation, quindi Proprietà.

  4. Nella finestra di dialogo delle proprietà Gruppo Team Foundation Server scegliere Utente o gruppo Windows, quindi Aggiungi.

  5. Nella finestra di dialogo Selezione utenti o gruppi digitare gli account utente che si desidera aggiungere, quindi scegliere OK.

  6. Scegliere Chiudi.


Note
Non è possibile utilizzare la finestra di dialogo del gruppo Sicurezza globale per aggiungere utenti al gruppo. È possibile aggiungere singoli account utente, ma non un account di gruppo.
ProtezionePer eseguire questa procedura, è necessario essere membro del gruppo Administrators di Team Foundation

Con questa procedura, però, l'utente sarà solo in grado di connettersi al server, ma non potrà né accedere a progetti esistenti né crearne di nuovi. Per terminare correttamente la configurazione è possibile ricorrere al programma TFS Admin Tool. È un programma che permette ad un amministratore TFS di aggiungere velocemente utenti alle tre piattaforme utilizzate dal Team Foundation Suite (Team Foundation Server, Sharepoint e SQL Reporting Services) attraverso una singola interfaccia comune. Il programma permette anche di cambiare i permessi assegnati agli utenti e di identificare gli eventuali errori.


Il programma è scritto in C# ed è pubblicato su CodePlex.

    martedì 4 novembre 2008

    Asterisk / Trixbox: ascolto chiamate in corso

    Con Asterisk o Trixbox è possibile ascoltare le chiamate in corso effettuate o ricevute da altri client.

    In "extensions.conf" in un contesto di vostro piacimento inserite questa riga. Se usate Trixbox o @home mettetelo in "extensions_custom.conf "sotto a [from-internal-custom]

    per esempio:

    exten => _61XXX,1,ChanSpy(SIP/${EXTEN:2},q)

    con tante X quante sono le cifre o i caratteri componenti i "nomi" dei vostri interni (in questo caso 3)

    Un bel reload, e poi bastera digitare sulla tastiera del telefono 61206 per ascoltare le telefonate dell’interno 206

    Asterisk / Trixbox: registrazione chiamate

    Con Asterisk o Trixbox è possibile registrare le chiamate effettuate da client.
    Per farlo basta inserire queste righe nel file "extesion.conf" su Asterisk oppure in "exstension_custom.conf" su Trixbox. (PS: su Trixbox è possibile abilitare questa funzione anche da interfaccia grafica)

    exten => _61XXX,1,Monitor(wav,rec${EXTEN:2},m)
    exten => _61XXX,2,ChanSpy(SIP/${EXTEN:2},q)
    exten => _61XXX,3,Hangup

    in /var/spool/asterisk/monitor troveremo le registrazioni in formato wav con nome rec"numinterno"

    E' anche possibile visualizzarle da web facendo un link simbolico della dir in var/www/dove volete

    giovedì 16 ottobre 2008

    Select Distinct su DataSet in Vb.Net

    Le funzioni sotto riportate permettono di effettuare da codice una query con "Select Distinct" su un DataSet.

    FieldNames è un array di string con in campi su cui fare la select distinct.



    Public Function SelectDistinct(ByVal SourceTable As DataTable, _
        ByVal ParamArray FieldNames() As String) As DataTable

        Dim lastValues() As Object
        Dim newTable As DataTable

        If FieldNames Is Nothing OrElse FieldNames.Length = 0 Then
            Throw New ArgumentNullException("FieldNames")
        End If

        lastValues = New Object(FieldNames.Length - 1) {}
        newTable = New DataTable

        For Each field As String In FieldNames
            newTable.Columns.Add(field, SourceTable.Columns(field).DataType)
        Next

        For Each Row As DataRow In SourceTable.Select("", String.Join(", ", FieldNames))
            If Not fieldValuesAreEqual(lastValues, Row, FieldNames) Then
                newTable.Rows.Add(createRowClone(Row, newTable.NewRow(), FieldNames))
                setLastValues(lastValues, Row, FieldNames)
            End If
        Next

        Return newTable
    End Function



    Private Function fieldValuesAreEqual(ByVal lastValues() As Object, _
        ByVal currentRow As DataRow, ByVal fieldNames() As String) As Boolean

        Dim areEqual As Boolean = True

        For i As Integer = 0 To fieldNames.Length - 1
            If lastValues(i) Is Nothing OrElse Not lastValues(i).Equals(currentRow(fieldNames(i))) Then
                areEqual = False
                Exit For
            End If
        Next

        Return areEqual
    End Function



    Private Function createRowClone(ByVal sourceRow As DataRow, _
        ByVal newRow As DataRow, ByVal fieldNames() As String) As DataRow

        For Each field As String In fieldNames
            newRow(field) = sourceRow(field)
        Next

        Return newRow
    End Function



    Private Shared Sub setLastValues(ByVal lastValues() As Object, _
        ByVal sourceRow As DataRow, ByVal fieldNames() As String)

        For i As Integer = 0 To fieldNames.Length - 1
            lastValues(i) = sourceRow(fieldNames(i))
        Next
    End Sub

    lunedì 6 ottobre 2008

    Configurazione Cisco SOHO 97 per NGI con 8 ip statici

    Avendo la necessità di configurare un router Cisco SOHO 97 per un'Adsl di NGI con 8 IP statici, mi sono fatto un giro per internet ma non ho trovato nulla che facesse al caso mio. Mi spiego:

    Degli 8 indirizzi pubblici statici assegnati, in realta solo 5 sono utilizzabili, in quanto il primo, il secondo e l'ultimo della subnet sono indirizzi di "servizio".

    La mia necessita era di riuscire a fare il NAT 1:1 degli indirizzi pubblici su indirizzi privati in modo che da permettere la gestione di quest'ultimi attraverso il mio server PFSense. Praticamente la struttura della rete è questa:

    Router <--> PFSense <--> Rete interna (MZ e DMZ)

    Praticamente, una persona dal "mondo" fa una richiesta all'indirizzo pubblico, il router lo passa al PFSense come indirizzo privato sull'interfaccia WAN del PFSense, il PFSense lo traduce in un indirizzo di un server sull'interfaccia LAN o DMZ.

    Siccome la configurazione del Router mi ha fatto "dannare" un po', la posto di seguito:


    no service pad
    service timestamps debug datetime msec
    service timestamps log datetime msec
    enable secret
    !
    hostname NomeDelRouter
    !
    boot-start-marker
    boot-end-marker
    !
    enable password PasswordDiEnable
    !
    no aaa new-model
    !
    resource policy
    !
    !
    !
    ip cef
    ip domain name ngi.it.
    ip name-server 88.149.128.12
    ip name-server 88.149.128.22
    !
    username UserAR password 0 PasswordAR
    !
    !
    !
    !
    interface Ethernet0
     ip address 192.168.0.254 255.255.255.0
     ip nat inside
    !
    interface ATM0
     no ip address
     ip nat outside
     no ip mroute-cache
     no atm ilmi-keepalive
     dsl operating-mode auto
     hold-queue 224 in
     pvc 8/35
      encapsulation aal5snap
      protocol ppp dialer
      dialer pool-member 1
     !
    !
    interface Dialer0
     ip address negotiated
     ip nat outside
     encapsulation ppp
     dialer pool 1
     dialer-group 1
     ppp pap sent-username UserADSL password 0 PassADSL
    !
    ip route 0.0.0.0 0.0.0.0 Dialer0
    no ip http server
    !
    ip nat inside source static 192.168.0.1 interface Dialer0
    ip nat inside source static 192.168.0.10 IpPubblico1
    ip nat inside source static 192.168.0.11 IpPubblico2
    ip nat inside source static 192.168.0.12 IpPubblico3
    ip nat inside source static 192.168.0.13 IpPubblico4
    ip nat inside source static 192.168.0.14 IpPubblico5
    !
    !
    control-plane
    !
    !
    line con 0
     no modem enable
    line aux 0
    line vty 0 4
     login local
    !
    scheduler max-task-time 5000
    end

    Dove UserAR e PasswordAR sono rispettivamente il nome utente e la password per l'accesso da remoto (console o telnet), UserADSL e PassADSL sono utente e password della connessione.
    192.168.0.254 è l'indirizzo di rete del router.
    192.168.0.1 è l'indirizzo dell'interfaccia WAN del PFSense.
    192.168.0.10-14 sono gli indirizzi su cui natto gli indirizzi pubblici.

    Degno di nota il fatto che NGI, come si vede, non assegna un indirizzo ip statico di punto-punto (interfaccia Dialer0 del router) ma lo da via DHCP, anche se in realtà l'indirizzo assegnato appunto via DHCP sarà sempre il II nel pool di indirizzi assegnato.

    venerdì 26 settembre 2008

    Scompattare con SharpZipLib e VB.net un file zip con sottocartelle

    Routine di scompattazione di un file Zip con l'utilizzo della dll rilasciata da ICSharpCode (IC#Code), open source, che si chiama SharpZipLib (#ZipLib) scaricabile liberamente QUI


    Imports ICSharpCode.SharpZipLib.Zip
    ......
    If File.Exists(fileName) Then

        destPath = fileName.Substring(0, fileName.Length - 4)

        If Not Directory.Exists(destPath) Then
            Directory.CreateDirectory(destPath)
        Else
            For Each s As String In Directory.GetFiles(destPath)
                File.Delete(s)
            Next
        End If

        Dim inStream As New ZipInputStream(File.OpenRead(fileName))
        Dim outStream As FileStream
        Dim entry As ZipEntry
        Dim buff(2047) As Byte
        Dim bytes As Integer

        Do While True
            Try
                entry = inStream.GetNextEntry()
                If entry Is Nothing Then
                    Exit Do
                End If

                If entry.Name.Last() = "/" Then
                    Directory.CreateDirectory(destPath & "\" & _
                    entry.Name.Replace("/", "\"))
                Else
                    Try
                        outStream = File.Create(destPath & _
                        "\" & entry.Name, 2048)
                        Do While True
                            bytes = inStream.Read(buff, 0, 2048)
                            If bytes = 0 Then
                                Exit Do
                            End If
                            outStream.Write(buff, 0, bytes)
                        Loop
                        outStream.Close()
                    Catch
                    End Try
                End If
            Catch
    ex As ZipException
                rtn += ex.Message & vbCrLf
            End Try
        Loop

        inStream.Close()
    Else
        rtn = "File '" & fileName & "' non trovato."
    End If

    giovedì 18 settembre 2008

    Copia ricorsiva di File e Cartelle in VB.Net

    Sembra banale, ma a volte la semplice copia dei file e delle sottodirectory contenute in una cartella può mettere in crisi un programmatore, proprio per la sua banalità.
    Proprio per evitare questo, posto un esempio di copia ricorsiva.

    Private Sub Copia(ByVal PathOrigine As String, _
                ByVal PathDestinazione As String)
        Dim Files() As String

        If PathDestinazione.Chars(PathDestinazione.Length - 1) <>
                Path.DirectorySeparatorChar Then
            PathDestinazione += Path.DirectorySeparatorChar
        End If

        If Not Directory.Exists(PathDestinazione) Then
            Directory.CreateDirectory(PathDestinazione)
        End If

        Files = Directory.GetFileSystemEntries(PathOrigine)

        Dim Elemento As String

        For Each Elemento In Files
            'Sotto cartelle
            If Directory.Exists(Elemento) Then
                Copia(Elemento, PathDestinazione +
                    Path.GetFileName(Elemento))
                ' File nella cartella
            Else
                File.Copy(Elemento, PathDestinazione +
                    Path.GetFileName(Elemento), True)
            End If
        Next Elemento
    End Sub