How can I combine my customize module with Omnet++INET's simple module - c++

As all the simple modules' behavior like 80211 mac layer has been defined in the INET module. If I want to add a customize layer between mac layer and network layer to handle network coding. How can I combine the customize module and INET's simple module ?

To add a new module between network layer and MAC layer I suggest creating a modified host in a new project. For OMNeT++ 4.6 and INET 3.2.4 do the following:
Create a new OMNeT++ empty project with src and simulation directories.
In the new project open Properties | Project References and select inet.
Right click on src and select New | Simple module. Call it DummyLayer.ned.
Open DummyLayer.ned and add:
#namespace(inet);
import inet.linklayer.contract.INic;
simple DummyLayer like INic {
parameters:
#display("i=block/buffer");
// here you can add others parameter
gates:
input ifIn;
output ifOut;
input upperLayerIn;
output upperLayerOut;
}
Modify DummyLayer.h and DummyLayer.cc (this module just passes every message from up and down, as well as increments counters):
// DummyLayer.h
#include <omnetpp.h>
namespace inet {
class DummyLayer: public cSimpleModule {
protected:
virtual void initialize();
virtual void handleMessage(cMessage *msg);
private:
int upNumber;
int downNumber;
};
} //namespace
//----------------------------------------------
// DummyLayer.cc
#include "DummyLayer.h"
namespace inet {
Define_Module(DummyLayer);
void DummyLayer::initialize() {
upNumber = 0;
downNumber = 0;
}
void DummyLayer::handleMessage(cMessage *msg) {
if (msg->arrivedOn("upperLayerIn")) {
send(msg, "ifOut");
downNumber++;
} else if (msg->arrivedOn("ifIn")) {
send(msg, "upperLayerOut");
upNumber++;
} else {
error("Incorrect gate");
}
char buf[128];
sprintf(buf, "up: %d, down: %d", upNumber, downNumber);
getDisplayString().setTagArg("t", 0, buf);
}
} //namespace
Create a new compound module for own host, call it WirelessHostEx.ned:
import inet.common.lifecycle.NodeStatus;
import inet.linklayer.contract.IWiredNic;
import inet.linklayer.contract.IWirelessNic;
import inet.linklayer.loopback.LoopbackInterface;
import inet.mobility.contract.IMobility;
import inet.networklayer.contract.IRoutingTable;
import inet.networklayer.common.InterfaceTable;
import inet.networklayer.contract.INetworkLayer;
import inet.power.contract.IEnergyStorage;
import inet.power.contract.IEnergyGenerator;
import inet.applications.contract.IPingApp;
import inet.applications.contract.ISCTPApp;
import inet.applications.contract.ITCPApp;
import inet.applications.contract.IUDPApp;
import inet.transportlayer.contract.ISCTP;
import inet.transportlayer.contract.ITCP;
import inet.transportlayer.contract.IUDP;
import inet.node.inet.INetworkNode;
module WirelessHostEx like INetworkNode
{
parameters:
#networkNode;
#display("i=device/wifilaptop");
#labels(wireless-node);
bool hasStatus = default(false);
int numExtInterfaces = default(0);
int numRadios = 1;
int numTunInterfaces = default(0);
string mobilityType = default(numRadios > 0 ? "StationaryMobility" : "");
string networkLayerType = default("IPv4NetworkLayer");
string routingTableType = default("IPv4RoutingTable");
bool forwarding = default(true);
bool multicastForwarding = default(false);
string energyStorageType = default("");
string energyGeneratorType = default("");
routingTable.forwarding = forwarding;
routingTable.multicastForwarding = multicastForwarding;
*.interfaceTableModule = default(absPath(".interfaceTable"));
*.routingTableModule = default(routingTableType != "" ? absPath(".routingTable") : "");
*.energySourceModule = default(energyStorageType != "" ? absPath(".energyStorage") : "");
*.mobilityModule = default(mobilityType != "" ? absPath(".mobility") : "");
int numTcpApps = default(0);
int numUdpApps = default(0);
int numPingApps = default(0);
bool hasTcp = default(numTcpApps > 0);
bool hasUdp = default(numUdpApps > 0);
string tcpType = default(firstAvailableOrEmpty("TCP", "TCP_lwIP", "TCP_NSC")); // tcp implementation (e.g. ~TCP, ~TCP_lwIP, ~TCP_NSC) or ~TCPSpoof
string udpType = default(firstAvailableOrEmpty("UDP"));
forwarding = default(false); // disable routing by default
networkLayer.proxyARP = default(false);
gates:
input radioIn[numRadios] #directIn;
inout pppg[] #labels(PPPFrame-conn);
inout ethg[] #labels(EtherFrame-conn);
submodules:
status: NodeStatus if hasStatus {
#display("p=50,50");
}
energyStorage: <energyStorageType> like IEnergyStorage if energyStorageType != "" {
parameters:
#display("p=50,100;i=block/plug;is=s");
}
energyGenerator: <energyGeneratorType> like IEnergyGenerator if energyGeneratorType != "" {
parameters:
#display("p=50,150;i=block/plug;is=s");
}
mobility: <mobilityType> like IMobility if mobilityType != "" {
parameters:
#display("p=53,200");
}
networkLayer: <networkLayerType> like INetworkLayer {
parameters:
#display("p=329,287;q=queue");
}
routingTable: <routingTableType> like IRoutingTable if routingTableType != "" {
parameters:
#display("p=53,250;is=s");
}
interfaceTable: InterfaceTable {
parameters:
#display("p=53,300;is=s");
}
lo0: LoopbackInterface {
#display("p=78,406");
}
wlan[numRadios]: <default("Ieee80211Nic")> like IWirelessNic {
parameters:
#display("p=216,406,row,60;q=queue");
}
eth[sizeof(ethg)]: <default("EthernetInterface")> like IWiredNic {
parameters:
#display("p=368,406,row,60;q=txQueue");
}
ppp[sizeof(pppg)]: <default("PPPInterface")> like IWiredNic {
parameters:
#display("p=558,406,row,60;q=txQueue");
}
tcpApp[numTcpApps]: <> like ITCPApp {
parameters:
#display("p=147,54,row,60");
}
tcp: <tcpType> like ITCP if hasTcp {
parameters:
#display("p=147,141");
}
udpApp[numUdpApps]: <> like IUDPApp {
parameters:
#display("p=329,54,row,60");
}
udp: <udpType> like IUDP if hasUdp {
parameters:
#display("p=329,141");
}
pingApp[numPingApps]: <default("PingApp")> like IPingApp {
parameters:
#display("p=635,141,row,60");
}
dummy: DummyLayer {
#display("p=273,350");
}
connections allowunconnected:
radioIn[0] --> { #display("m=s"); } --> wlan[0].radioIn;
// the order of connections is important here
wlan[0].upperLayerOut --> dummy.ifIn;
dummy.upperLayerOut --> networkLayer.ifIn++;
wlan[0].upperLayerIn <-- dummy.ifOut;
dummy.upperLayerIn <-- networkLayer.ifOut++;
networkLayer.ifOut++ --> lo0.upperLayerIn;
lo0.upperLayerOut --> networkLayer.ifIn++;
for i=0..sizeof(ethg)-1 {
ethg[i] <--> { #display("m=s"); } <--> eth[i].phys;
eth[i].upperLayerOut --> networkLayer.ifIn++;
eth[i].upperLayerIn <-- networkLayer.ifOut++;
}
for i=0..sizeof(pppg)-1 {
pppg[i] <--> { #display("m=s"); } <--> ppp[i].phys;
ppp[i].upperLayerOut --> networkLayer.ifIn++;
ppp[i].upperLayerIn <-- networkLayer.ifOut++;
}
for i=0..numTcpApps-1 {
tcpApp[i].tcpOut --> tcp.appIn++;
tcpApp[i].tcpIn <-- tcp.appOut++;
}
tcp.ipOut --> networkLayer.transportIn++ if hasTcp;
tcp.ipIn <-- networkLayer.transportOut++ if hasTcp;
for i=0..numUdpApps-1 {
udpApp[i].udpOut --> udp.appIn++;
udpApp[i].udpIn <-- udp.appOut++;
}
udp.ipOut --> networkLayer.transportIn++ if hasUdp;
udp.ipIn <-- networkLayer.transportOut++ if hasUdp;
for i=0..numPingApps-1 {
networkLayer.pingOut++ --> pingApp[i].pingIn;
networkLayer.pingIn++ <-- pingApp[i].pingOut;
}
}
An own host module is necessary because StandardHost from INET creates connection between MAC and network layer automatically and it is not possible to add own module between these layers.
Create a network (for test):
import inet.networklayer.configurator.ipv4.IPv4NetworkConfigurator;
import inet.physicallayer.ieee80211.packetlevel.Ieee80211ScalarRadioMedium;
import inet.node.wireless.AccessPoint;
network WirelessNetwork {
submodules:
configurator: IPv4NetworkConfigurator {
#display("p=33,81");
}
radioMedium: Ieee80211ScalarRadioMedium {
#display("p=33,30");
}
node0: WirelessHostEx {
#display("p=128,121");
}
node1: WirelessHostEx {
#display("p=384,115");
}
ap: AccessPoint {
#display("p=273,54");
}
}
Modify omnetpp.ini:
[General]
network = WirelessNetwork
// node0 will send ping to node1
**.node0.numPingApps = 1
**.node0.pingApp[0].destAddr = "node1" // using IP address here is allowed too
After starting the simulation one can see that in each host dummyLayer send messages forward.

Related

Problem encountered while trying to create dynamic modules in omnet++

I'm a beginner and I'm learning network simulation with Omnet++.
I have been trying to create dynamic modules (Clients) and connect it to a staticlly created module (Server) but I'm getting an error with the function getParentModule() saying:
use of undeclared identifier 'getParentModule'.
Here is my Server class:
#include "Server.h"
#include <string>
Define_Module(Server);
void create_grp(int num, int id) {
cModuleType *moduleType = cModuleType::get("c");
std::string name = "grp" + std::to_string(id);
//Here my error
cModule *module = moduleType->create(name, getParentModule());
module->setGateSize("in", 1);
module->setGateSize("out", 1);
module->finalizeParameters();
module->buildInside();
}
void Server::initialize() {
// TODO Auto-generated constructor stub
create_grp(3, 2);
}
And here is my .ned file
simple Server
{
gates:
inout g1[];
}
simple Admin
{
parameters:
int nbr_of_groups_to_create;
int nbr_of_nodes_in_each_group;
gates:
inout g2;
}
simple Client
{
gates:
inout g3;
}
network Network
{
#display("bgb=384,297");
submodules:
s: Server {
#display("i=device/server;p=173,89");
}
a: Admin {
#display("p=264,167;i=device/laptop");
}
c[10]: Client {
#display("i=device/pc;p=79,167");
}
connections:
a.g2 <--> s.g1++;
for i=0..9 {
s.g1++ <--> c[i].g3;
}
}
You have declared create_grp() as a standalone function so it cannot know what is getParentModule(). I recommend declaring create_grp inside your class Server.
EDIT
create() requires const char* as the first argument, but you provide std::string. You should use c_std() to convert std::string into const char*, for example:
cModule *module = moduleType->create(name.c_str(), getParentModule());

Check and Cast error on Omnet++ with INet

I'm trying to send an Udp message from a WirelessHost (Host1) to a StandardHost (Host3) through an AP and a Router, but I get this error message when i run the simulation (i called my network "poi"):
check_and_cast(): Cannot cast 'inet::physicallayer::INoise*' to type
'const inet::physicallayer::NarrowbandNoiseBase *' -- in module
(inet::physicallayer::Ieee80211Radio) poi.router.wlan[0].radio
(id=80), during network initialization
I started using omnet++ with Inet a few days ago, and based my code on tutorials and documentation, but i can't find a solution to this error. Any experience or solution ?
Thank you
This is the .ned code, without import:
network poi {
parameters:
#display("bgb=514,316;bgg=100,1,grey95");
#figure[title](type=label; pos=0,-1; anchor=sw; color=darkblue);
#figure[rcvdPkText](type=indicatorText; pos=380,20; anchor=w; font=,18; textFormat="packets received: %g"; initialValue=0);
#statistic[packetReceived](source=host3.app[0].packetReceived; record=figure(count); targetFigure=rcvdPkText);
submodules:
host1: WirelessHost {
#display("p=403,224");
numWlanInterfaces = 1;
numApps = 1;
}
router: Router {
#display("p=193,224");
numWlanInterfaces = 2;
numEthInterfaces = 2;
numApps = 4;
}
accessPoint: AccessPoint {
#display("p=303,217;r=2000");
}
host3: StandardHost {
#display("p=73,224");
numEthInterfaces = 1;
numApps = 1;
}
integratedCanvasVisualizer: IntegratedCanvasVisualizer {
#display("p=379,57");
}
configurator: Ipv4NetworkConfigurator {
#display("p=104,35");
}
unitDiskRadioMedium: UnitDiskRadioMedium {
#display("p=216,100;r=10000");
}
connections:
accessPoint.ethg++ <--> Eth10G { #display("ls=,0"); } <--> router.ethg[0];
router.ethg[1] <--> Eth10G { #display("ls=,0"); } <--> host3.ethg[0];
}
and the .ini file:
[General]
network = poi
*.host*.ipv4.arp.typename = "GlobalArp"
*.router.ipv4.arp.typename = "GlobalArp"
*.router.app[*].typename = "UdpBasicApp"
*.host1.app[0].typename = "UdpBasicApp"
*.host1.app[0].destAddresses = "accessPoint"
*.host1.app[0].messageLength = 500B
*.host1.app[0].sendInterval = uniform(1ms,10ms)
*.host1.app[0].packetName = "UDPData"
*.host1.wlan[*].radio.radioMediumModule = "unitDiskRadioMedium"
*.router.wlan[*].radio.radioMediumModule = "unitDiskRadioMedium"
*.accessPoint.wlan[*].radio.radioMediumModule = "unitDiskRadioMedium"
*.host*.wlan[*].radio.receiver.ignoreInterference = true
*.host3.app[*].typename = "UdpBasicApp"
*.host*.wlan[0].typename = "AckingWirelessInterface"
*.host*.wlan[0].mac.useAck = false
*.host*.wlan[0].mac.fullDuplex = true
*.host*.wlan[0].radio.transmitter.communicationRange = 500m
*.host*.wlan[0].mac.headerLength = 1B
*.host*.**.bitrate = 1Gbps
Add to your ini file:
**.wlan[*].radio.typename = "UnitDiskRadio"
Besides this you can set unassigned parameters in ini, for example:
**.app[0].destPort = 4000
**.app[0].messageLength= 100B
**.app[0].sendInterval= 1s
**.transmitter.communicationRange = 500m

How to redirect the incoming traffic to a module to its simple submodule in Omnet++?

I have this code where a module which extends WirelessHost module is composed of a simple module called node :
When I run the simulation, there's only mobility events, no communication events are displayed. I think this is due to not
linking Drone gates module with gates that receive incoming traffic. How can I do this please?
SaaS.ned
import inet.node.inet.WirelessHost;
import inet.visualizer.integrated.IntegratedVisualizer;
import inet.networklayer.configurator.ipv4.Ipv4NetworkConfigurator;
import inet.physicallayer.unitdisk.UnitDiskRadioMedium;
simple Node
{
gates:
input in[];
output out[];
}
module Drone extends WirelessHost
{
gates:
input in[];
output out[];
submodules:
myNode: Node;
connections allowunconnected:
for i=0..sizeof(in)-1 {
in++ --> myNode.in++;
}
for i=0..sizeof(out)-1 {
out++ <-- myNode.out++;
}
}
network SaaS
{
parameters:
int numDrones;
submodules:
visualizer: IntegratedVisualizer {
#display("p=94.376,433.728");
}
configurator: Ipv4NetworkConfigurator {
parameters:
config = xml("<config><interface hosts='*' address='145.236.x.x' netmask='255.255.0.0'/></config>");
#display("p=94.376,56.224;is=s");
}
radioMedium: UnitDiskRadioMedium {
#display("p=94.376,178.71199");
}
drone[numDrones]: Drone {
#display("i=misc/node_vs");
}
}
Node.cc
#include <string.h>
#include <omnetpp.h>
using namespace omnetpp;
class Node : public cSimpleModule
{
protected:
// The following redefined virtual function holds the algorithm.
virtual void initialize() override;
virtual void handleMessage(cMessage *msg) override;
};
// The module class needs to be registered with OMNeT++
Define_Module(Node);
using namespace std;
void Node::initialize()
{
int n = gateSize("out");
cMessage *msg = new cMessage("tictocMessage");
for (int i = 0; i < n ; i++)
send(msg, "out", i);
}
void Node::handleMessage(cMessage *msg)
{
int n = gateSize("out");
for (int i = 0; i < n ; i++)
send(msg, "out", i);
}
This is not, how a WirelessHost in INET is supposed to be configured.
You should implement an UDP application module and you must configure that application to be used in the WirelessHost.
*.drone[0].numApps = 1
*.drone[0].app[0].typename = "MyUDPApp"
There is no need to extend the WirelessHost as it already contains a module vector called app which can be configured with the various application modules. You should check the various examples how applications are configured in them.

Panic because parameters must be struct and not interface, in web.Router?

In testing the following code:
package logHandler
import (
"ezsoft/apiserver_sdk/context"
"github.com/hsoshiant/web"
)
// Build simply builds a log handler router
//
// Parameters:
//
// - `mainRouter` : the main Router
//
// Returns:
//
// - a sub Router made specifically for logging
func Build(mainRouter *web.Router) *web.Router {
return mainRouter.Subrouter(context.Context{}, "/log").
Post("/", doLog)
}
I hit a panic. context.Context is defined thus:
//BaseContext contains all the base context to be helpful when using the utilities
type BaseContext struct {
Session session.Store
ResponseWriter *web.ResponseWriter
RequestReader *web.Request
}
//Context contains all values needed when using the utilities
type Context struct {
BaseContext
JSONBody map[string]interface{}
tokenHandler *apiToken.APITokenHandlerSt
OAuthInstance *oAuth2.OAuth2St
}
and with testability/flexibility in mind, the developers wrote the middleware functions to take context.ContextIntf, which context.Context implements, which is defined as follows:
//ContextIntf is the interface to use when using the context interface functions.
type ContextIntf interface {
SetUniversalHeaders(header map[string]string) map[string]string
GetInfo() *Context
GetOAuth() *oAuth2.OAuth2St
}
Here's one such middleware func:
//AuthenticationMiddleware Middleware which handles all of the authentication.
func AuthenticationMiddleware(mw AuthenticationMiddlewareIntf, context context.ContextIntf, w web.ResponseWriter, r *web.Request, next web.NextMiddlewareFunc) {
//Check if the url should be public.
for _, url := range mw.GetInfo().nonAuthURLs {
if url.Method == r.Method && strings.Contains(r.URL.Path, url.DomainName) {
key := utilities.GetRemoteAdd(r) + ";" + r.URL.Path
if timeSince, ok := NonAuthSecurityMap[key]; ok {
var (
timeSinceTime, _ = time.Parse(time.UnixDate, timeSince)
timeSinceDuration = time.Since(timeSinceTime)
)
if timeSinceDuration < nonAuthTimeReset {
// will sleep for `nonAuthTimeReset` - `timeSinceDuration` > 0
time.Sleep(-(timeSinceDuration - nonAuthTimeReset))
}
}
NonAuthSecurityMap[key] = time.Now().Format(time.UnixDate)
next(w, r)
return
}
}
if errSt := CheckForAuthorization(mw, context, r, w); errSt != nil {
responses.Write(w, responses.Unauthorized(*errSt))
return
}
defer context.GetInfo().Session.SessionRelease(w)
next(w, r)
}
I am unsure which middleware business functions that package web is checking, let alone what business packages they reside in, and the call stack trace returns no such clues.
The error I get is thus:
* You are adding a handler to a router with context type 'Context'
*
*
* Your handler function can have one of these signatures:
*
* // If you don't need context:
* func YourFunctionName(rw web.ResponseWriter, req *web.Request)
*
* // If you want your handler to accept a context:
* func (c *Context) YourFunctionName(rw web.ResponseWriter, req *web.Request) // or,
* func YourFunctionName(c *Context, rw web.ResponseWriter, req *web.Request)
*
* Unfortunately, your function has this signature: func(context.ContextIntf, web.ResponseWriter, *web.Request)
*
************************************************************************************************************************
Why is this requesting a Context struct, instead of the ContextIntf that it implements?!
The stack trace
Looks like this:
goroutine 20 [running]:
testing.tRunner.func1(0xc04213e1e0)
C:/Go/src/testing/testing.go:742 +0x2a4
panic(0x7633c0, 0xc0421320a0)
C:/Go/src/runtime/panic.go:502 +0x237
github.com/hsoshiant/web.validateHandler(0x778420, 0x80d8f0, 0x13, 0x8405c0, 0x7b7960)
D:/dev2017/GO/src/github.com/hsoshiant/web/router_setup.go:286 +0x242
github.com/hsoshiant/web.(*Router).addRoute(0xc042106680, 0x7eeb93, 0x4, 0x7ee4bd, 0x1, 0x778420, 0x80d8f0, 0xc042051f80)
D:/dev2017/GO/src/github.com/hsoshiant/web/router_setup.go:223 +0x94
github.com/hsoshiant/web.(*Router).Post(0xc042106680, 0x7ee4bd, 0x1, 0x778420, 0x80d8f0, 0xc042106680)
D:/dev2017/GO/src/github.com/hsoshiant/web/router_setup.go:193 +0x6f
ezsoft/apiserver_sdk/logger/logHandler.Build(0xc0421064e0, 0xc042051f40)
D:/dev2017/GO/src/ezsoft/apiserver_sdk/logger/logHandler/handler.go:20 +0xcf
ezsoft/apiserver_sdk/logger/logHandler.TestBuild.func1(0xc04213e1e0)
D:/dev2017/GO/src/ezsoft/apiserver_sdk/logger/logHandler/handler_test.go:16 +0x91
testing.tRunner(0xc04213e1e0, 0x80d8e0)
C:/Go/src/testing/testing.go:777 +0xd7
created by testing.(*T).Run
C:/Go/src/testing/testing.go:824 +0x2e7
UPDATE : It's hitting the private method doLog, which is defined thus:
func doLog(contextIntf context.ContextIntf, rw web.ResponseWriter, req *web.Request) {
var (
logType int = 0
code string = ""
message string = ""
context = contextIntf.GetInfo()
)
if val, OK := context.JSONBody["type"]; OK {
if val1, noErr := val.(float64); noErr {
logType = int(val1)
}
}
if logType == 0 {
responses.Write(rw, responses.FreeUnprocessableEntity("Type"))
return
}
if val, OK := context.JSONBody["code"]; OK {
if val1, noErr := val.(string); noErr {
code = val1
} else {
responses.Write(rw, responses.FreeUnprocessableEntity("Code"))
return
}
}
if val, OK := context.JSONBody["message"]; OK {
if val1, noErr := val.(string); noErr {
message = val1
}
}
if message == "" {
responses.Write(rw, responses.FreeUnprocessableEntity("message"))
return
}
if code > "" {
code = " (" + code + ") "
}
switch logType {
case 1:
logger.Instance.LogError(code + message)
case 2:
logger.Instance.LogWarning(code + message)
case 3:
logger.Instance.LogInfo(code + message)
default:
logger.Instance.LogWarning(code + message)
}
responses.Write(rw, responses.OK(0))
}
I still don't get why that argument needs to be a context.Context, or what I, the unit-tester, can do about it.

XSS Filter to enctype="multipart/form-data" forms

I found the next code that prevent xss atacks. But it has a problem. It works fine with forms that have enctype="application/x-www-form-urlencoded", but not with forms that have enctype="multipart/form-data". I observe that getParameterValues() and rest of methods are not called.
//--- XSS Filter ---//
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
/**
* Servlet Filter implementation class XSSFilter
*/
public class XSSFilter implements Filter {
#SuppressWarnings("unused")
private FilterConfig filterConfig;
/**
* Default constructor.
*/
public XSSFilter() {
}
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
}
public void destroy() {
this.filterConfig = null;
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
chain.doFilter(new RequestWrapperXSS((HttpServletRequest) request), response);
}
}
//--- RequestWrapperXSS ---//
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
public final class RequestWrapperXSS extends HttpServletRequestWrapper {
public RequestWrapperXSS(HttpServletRequest servletRequest) {
super(servletRequest);
}
public String[] getParameterValues(String parameter) {
System.out.println("entra parameterValues");
String[] values = super.getParameterValues(parameter);
if (values == null) {
return null;
}
int count = values.length;
String[] encodedValues = new String[count];
for (int i = 0; i < count; i++) {
encodedValues[i] = cleanXSS(values[i]);
}
return encodedValues;
}
public String getParameter(String parameter) {
System.out.println("entra getParameter");
String value = super.getParameter(parameter);
if (value == null) {
return null;
}
return cleanXSS(value);
}
public String getHeader(String name) {
System.out.println("entra header");
String value = super.getHeader(name);
if (value == null)
return null;
return cleanXSS(value);
}
private String cleanXSS(String cadena) {
System.out.println("entra claean XSS");
StringBuffer sb = new StringBuffer(cadena.length());
// true if last char was blank
boolean lastWasBlankChar = false;
int len = cadena.length();
char c;
for (int i = 0; i < len; i++)
{
c = cadena.charAt(i);
if (c == ' ') {
// blank gets extra work,
// this solves the problem you get if you replace all
// blanks with , if you do that you loss
// word breaking
if (lastWasBlankChar) {
lastWasBlankChar = false;
sb.append(" ");
}
else {
lastWasBlankChar = true;
sb.append(' ');
}
}
else {
lastWasBlankChar = false;
//
// HTML Special Chars
if (c == '"')
sb.append(""");
else if (c == '&')
sb.append("&");
else if (c == '<')
sb.append("<");
else if (c == '>')
sb.append(">");
else if (c == '\n')
// Handle Newline
sb.append("<br/>");
else {
int ci = 0xffff & c;
if (ci < 160 )
// nothing special only 7 Bit
sb.append(c);
else {
// Not 7 Bit use the unicode system
sb.append("&#");
sb.append(new Integer(ci).toString());
sb.append(';');
}
}
}
}
return sb.toString();
}
}
In case of multipart/form-data requests, the data is available by getPart() and getParts() methods, not by getParameter(), getParameterValues() and consorts.
Note that those methods are introduced in Servlet 3.0 and that in older versions there is not any standard API facility to extract data from multipart/form-data requests. The defacto API which is been used for that instead is the well known Apache Commons FileUpload.
Unrelated to the concrete problem, this is IMO a bad way to prevent XSS. XSS should be prevented in the view side during redisplaying the user-controlled input, right there where it can harm. Escaping before processing the user-controlled input will only risk in double escaping because it's not the "standard" way of XSS prevention. The developers should just ensure that they always escape user-controlled data in the view side using JSTL <c:out> or fn:escapeXml() or any other MVC framework supplied facilities (JSF for example escapes everything by default).
See also
XSS prevention in JSP/Servlet web application